// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_SWAP_H
#define EIGEN_SWAP_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

namespace internal {

// Overload default assignPacket behavior for swapping them
template <typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT>
class generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT,
                                      swap_assign_op<typename DstEvaluatorTypeT::Scalar>, Specialized>
    : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT,
                                             swap_assign_op<typename DstEvaluatorTypeT::Scalar>, BuiltIn> {
 protected:
  using Base = generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT,
                                               swap_assign_op<typename DstEvaluatorTypeT::Scalar>, BuiltIn>;
  using Base::m_dst;
  using Base::m_src;

 public:
  using Scalar = typename Base::Scalar;
  using DstXprType = typename Base::DstXprType;
  using Functor = swap_assign_op<Scalar>;

  EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE generic_dense_assignment_kernel(DstEvaluatorTypeT &dst,
                                                                                  const SrcEvaluatorTypeT &src,
                                                                                  const Functor &func,
                                                                                  DstXprType &dstExpr)
      : Base(dst, src, func, dstExpr) {}

  template <int StoreMode, int LoadMode, typename PacketType>
  EIGEN_STRONG_INLINE void assignPacket(Index row, Index col) {
    PacketType tmp = m_src.template packet<LoadMode, PacketType>(row, col);
    const_cast<SrcEvaluatorTypeT &>(m_src).template writePacket<LoadMode>(
        row, col, m_dst.template packet<StoreMode, PacketType>(row, col));
    m_dst.template writePacket<StoreMode>(row, col, tmp);
  }

  template <int StoreMode, int LoadMode, typename PacketType>
  EIGEN_STRONG_INLINE void assignPacket(Index index) {
    PacketType tmp = m_src.template packet<LoadMode, PacketType>(index);
    const_cast<SrcEvaluatorTypeT &>(m_src).template writePacket<LoadMode>(
        index, m_dst.template packet<StoreMode, PacketType>(index));
    m_dst.template writePacket<StoreMode>(index, tmp);
  }

  template <int StoreMode, int LoadMode, typename PacketType>
  EIGEN_STRONG_INLINE void assignPacketByOuterInner(Index outer, Index inner) {
    Index row = Base::rowIndexByOuterInner(outer, inner);
    Index col = Base::colIndexByOuterInner(outer, inner);
    assignPacket<StoreMode, LoadMode, PacketType>(row, col);
  }

  template <int StoreMode, int LoadMode, typename PacketType>
  EIGEN_STRONG_INLINE void assignPacketSegment(Index row, Index col, Index begin, Index count) {
    PacketType tmp = m_src.template packetSegment<LoadMode, PacketType>(row, col, begin, count);
    const_cast<SrcEvaluatorTypeT &>(m_src).template writePacketSegment<LoadMode>(
        row, col, m_dst.template packetSegment<StoreMode, PacketType>(row, col, begin, count), begin, count);
    m_dst.template writePacketSegment<StoreMode>(row, col, tmp, begin, count);
  }

  template <int StoreMode, int LoadMode, typename PacketType>
  EIGEN_STRONG_INLINE void assignPacketSegment(Index index, Index begin, Index count) {
    PacketType tmp = m_src.template packetSegment<LoadMode, PacketType>(index, begin, count);
    const_cast<SrcEvaluatorTypeT &>(m_src).template writePacketSegment<LoadMode>(
        index, m_dst.template packetSegment<StoreMode, PacketType>(index, begin, count), begin, count);
    m_dst.template writePacketSegment<StoreMode>(index, tmp, begin, count);
  }

  template <int StoreMode, int LoadMode, typename PacketType>
  EIGEN_STRONG_INLINE void assignPacketSegmentByOuterInner(Index outer, Index inner, Index begin, Index count) {
    Index row = Base::rowIndexByOuterInner(outer, inner);
    Index col = Base::colIndexByOuterInner(outer, inner);
    assignPacketSegment<StoreMode, LoadMode, PacketType>(row, col, begin, count);
  }
};

}  // namespace internal

}  // end namespace Eigen

#endif  // EIGEN_SWAP_H
