// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@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_TENSOR_TENSOR_CONCATENATION_H
#define EIGEN_TENSOR_TENSOR_CONCATENATION_H

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

namespace Eigen {

namespace internal {
template <typename Axis, typename LhsXprType, typename RhsXprType>
struct traits<TensorConcatenationOp<Axis, LhsXprType, RhsXprType>> {
  // Type promotion to handle the case where the types of the lhs and the rhs are different.
  typedef typename promote_storage_type<typename LhsXprType::Scalar, typename RhsXprType::Scalar>::ret Scalar;
  typedef typename promote_storage_type<typename traits<LhsXprType>::StorageKind,
                                        typename traits<RhsXprType>::StorageKind>::ret StorageKind;
  typedef
      typename promote_index_type<typename traits<LhsXprType>::Index, typename traits<RhsXprType>::Index>::type Index;
  static constexpr int NumDimensions = traits<LhsXprType>::NumDimensions;
  static constexpr int Layout = traits<LhsXprType>::Layout;
  enum { Flags = 0 };
  typedef std::conditional_t<Pointer_type_promotion<typename LhsXprType::Scalar, Scalar>::val,
                             typename traits<LhsXprType>::PointerType, typename traits<RhsXprType>::PointerType>
      PointerType;
};

template <typename Axis, typename LhsXprType, typename RhsXprType>
struct eval<TensorConcatenationOp<Axis, LhsXprType, RhsXprType>, Eigen::Dense> {
  typedef const TensorConcatenationOp<Axis, LhsXprType, RhsXprType>& type;
};

}  // end namespace internal

/**
 * \ingroup Tensor_Module
 *
 * \brief Tensor concatenation class.
 */
template <typename Axis, typename LhsXprType, typename RhsXprType>
class TensorConcatenationOp : public TensorBase<TensorConcatenationOp<Axis, LhsXprType, RhsXprType>, WriteAccessors> {
 public:
  typedef TensorBase<TensorConcatenationOp<Axis, LhsXprType, RhsXprType>, WriteAccessors> Base;
  typedef typename internal::traits<TensorConcatenationOp>::Scalar Scalar;
  typedef typename internal::traits<TensorConcatenationOp>::StorageKind StorageKind;
  typedef typename internal::traits<TensorConcatenationOp>::Index Index;
  typedef typename internal::ref_selector<TensorConcatenationOp>::type Nested;
  typedef typename internal::promote_storage_type<typename LhsXprType::CoeffReturnType,
                                                  typename RhsXprType::CoeffReturnType>::ret CoeffReturnType;
  typedef typename NumTraits<Scalar>::Real RealScalar;

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorConcatenationOp(const LhsXprType& lhs, const RhsXprType& rhs, Axis axis)
      : m_lhs_xpr(lhs), m_rhs_xpr(rhs), m_axis(axis) {}

  EIGEN_DEVICE_FUNC const internal::remove_all_t<typename LhsXprType::Nested>& lhsExpression() const {
    return m_lhs_xpr;
  }

  EIGEN_DEVICE_FUNC const internal::remove_all_t<typename RhsXprType::Nested>& rhsExpression() const {
    return m_rhs_xpr;
  }

  EIGEN_DEVICE_FUNC const Axis& axis() const { return m_axis; }

  EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TensorConcatenationOp)
 protected:
  typename LhsXprType::Nested m_lhs_xpr;
  typename RhsXprType::Nested m_rhs_xpr;
  const Axis m_axis;
};

// Eval as rvalue
template <typename Axis, typename LeftArgType, typename RightArgType, typename Device>
struct TensorEvaluator<const TensorConcatenationOp<Axis, LeftArgType, RightArgType>, Device> {
  typedef TensorConcatenationOp<Axis, LeftArgType, RightArgType> XprType;
  typedef typename XprType::Index Index;
  static constexpr int NumDims = internal::array_size<typename TensorEvaluator<LeftArgType, Device>::Dimensions>::value;
  static constexpr int RightNumDims =
      internal::array_size<typename TensorEvaluator<RightArgType, Device>::Dimensions>::value;
  typedef DSizes<Index, NumDims> Dimensions;
  typedef typename XprType::Scalar Scalar;
  typedef typename XprType::CoeffReturnType CoeffReturnType;
  typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
  typedef StorageMemory<CoeffReturnType, Device> Storage;
  typedef typename Storage::Type EvaluatorPointerType;
  static constexpr int Layout = TensorEvaluator<LeftArgType, Device>::Layout;
  enum {
    IsAligned = false,
    PacketAccess =
        TensorEvaluator<LeftArgType, Device>::PacketAccess && TensorEvaluator<RightArgType, Device>::PacketAccess,
    // block() reads each operand's data() pointer directly, so both must
    // expose raw storage. Scalar-changing block consumers
    // (TensorCwiseUnaryOp, TensorConversionOp) drop the forwarded destination
    // buffer before reaching us, so prepareStorage always sees either a
    // matching-Scalar buffer or no buffer at all.
    BlockAccess = TensorEvaluator<LeftArgType, Device>::RawAccess && TensorEvaluator<RightArgType, Device>::RawAccess,
    // Matches TensorShuffling / TensorBroadcasting / TensorPadding: bulk copy
    // wins over the per-element coeff/packet path (which pays div/mod per
    // access) at every size we benchmarked, so always prefer block.
    PreferBlockAccess = true,
    RawAccess = false
  };

  typedef std::remove_const_t<Scalar> ScalarNoConst;

  //===- Tensor block evaluation strategy (see TensorBlock.h) -------------===//
  typedef internal::TensorBlockDescriptor<NumDims, Index> TensorBlockDesc;
  typedef internal::TensorBlockScratchAllocator<Device> TensorBlockScratch;

  typedef typename internal::TensorMaterializedBlock<ScalarNoConst, NumDims, Layout, Index> TensorBlock;
  //===--------------------------------------------------------------------===//

  EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device)
      : m_leftImpl(op.lhsExpression(), device),
        m_rightImpl(op.rhsExpression(), device),
        m_device(device),
        m_axis(op.axis()) {
    EIGEN_STATIC_ASSERT((static_cast<int>(TensorEvaluator<LeftArgType, Device>::Layout) ==
                             static_cast<int>(TensorEvaluator<RightArgType, Device>::Layout) ||
                         NumDims == 1),
                        YOU_MADE_A_PROGRAMMING_MISTAKE);
    // TensorConcatenationOp requires both operands to have the same static
    // rank. Reshape the lower-rank operand explicitly if you need to mix
    // ranks; see the concatenate() entry in contrib/Eigen/src/Tensor/README.md.
    EIGEN_STATIC_ASSERT((NumDims == RightNumDims), YOU_MADE_A_PROGRAMMING_MISTAKE);
    EIGEN_STATIC_ASSERT((NumDims > 0), YOU_MADE_A_PROGRAMMING_MISTAKE);

    eigen_assert(0 <= m_axis && m_axis < NumDims);
    m_leftAxisSize = m_leftImpl.dimensions()[m_axis];
    const Dimensions& lhs_dims = m_leftImpl.dimensions();
    const Dimensions& rhs_dims = m_rightImpl.dimensions();
    {
      int i = 0;
      for (; i < m_axis; ++i) {
        eigen_assert(lhs_dims[i] > 0);
        eigen_assert(lhs_dims[i] == rhs_dims[i]);
        m_dimensions[i] = lhs_dims[i];
      }
      eigen_assert(lhs_dims[i] > 0);  // Now i == m_axis.
      eigen_assert(rhs_dims[i] > 0);
      m_dimensions[i] = lhs_dims[i] + rhs_dims[i];
      for (++i; i < NumDims; ++i) {
        eigen_assert(lhs_dims[i] > 0);
        eigen_assert(lhs_dims[i] == rhs_dims[i]);
        m_dimensions[i] = lhs_dims[i];
      }
    }

    EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
      m_leftStrides[0] = 1;
      m_rightStrides[0] = 1;
      m_outputStrides[0] = 1;

      for (int j = 1; j < NumDims; ++j) {
        m_leftStrides[j] = m_leftStrides[j - 1] * lhs_dims[j - 1];
        m_rightStrides[j] = m_rightStrides[j - 1] * rhs_dims[j - 1];
        m_outputStrides[j] = m_outputStrides[j - 1] * m_dimensions[j - 1];
      }
    } else {
      m_leftStrides[NumDims - 1] = 1;
      m_rightStrides[NumDims - 1] = 1;
      m_outputStrides[NumDims - 1] = 1;

      for (int j = NumDims - 2; j >= 0; --j) {
        m_leftStrides[j] = m_leftStrides[j + 1] * lhs_dims[j + 1];
        m_rightStrides[j] = m_rightStrides[j + 1] * rhs_dims[j + 1];
        m_outputStrides[j] = m_outputStrides[j + 1] * m_dimensions[j + 1];
      }
    }
  }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }

  // TODO(phli): Add short-circuit memcpy evaluation if underlying data are linear.
  EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(EvaluatorPointerType) {
    m_leftImpl.evalSubExprsIfNeeded(nullptr);
    m_rightImpl.evalSubExprsIfNeeded(nullptr);
    return true;
  }

  EIGEN_STRONG_INLINE void cleanup() {
    m_leftImpl.cleanup();
    m_rightImpl.cleanup();
  }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE internal::TensorBlockResourceRequirements getResourceRequirements() const {
    // Target the L1 cache. A block straddling the concat axis is materialized
    // into a merged scratch slab that the cwise consumer reads straight back;
    // sizing the block to L1 keeps that round-trip out of the last-level
    // cache. It also splits an otherwise cache-resident output into many
    // blocks, so the off-axis ones qualify for the zero-copy view path in
    // block(). Matches TensorBroadcasting, which likewise targets L1 for its
    // materialized block path.
    const size_t target_size = m_device.firstLevelCacheSize();
    return internal::TensorBlockResourceRequirements::merge(
        internal::TensorBlockResourceRequirements::skewed<Scalar>(target_size),
        internal::TensorBlockResourceRequirements::merge(m_leftImpl.getResourceRequirements(),
                                                         m_rightImpl.getResourceRequirements()));
  }

  // True when a block of shape `block_dims` is a contiguous run of an operand
  // whose shape is `operand_dims` -- i.e. it can be addressed as a plain
  // pointer offset with no per-row stride walk. Mirrors the direct-access test
  // in TensorMaterializedBlock::materialize().
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool isContiguousOperandSlab(const Dimensions& operand_dims,
                                                                     const Dimensions& block_dims) const {
    static constexpr bool IsColMajor = Layout == static_cast<int>(ColMajor);
    int matching_inner_dims = 0;
    for (int i = 0; i < NumDims; ++i) {
      const int dim = IsColMajor ? i : NumDims - i - 1;
      if (operand_dims[dim] != block_dims[dim]) break;
      ++matching_inner_dims;
    }
    // Every dimension above the single partial dimension must be of size 1.
    for (int i = matching_inner_dims + 1; i < NumDims; ++i) {
      const int dim = IsColMajor ? i : NumDims - i - 1;
      if (block_dims[dim] != 1) return false;
    }
    return true;
  }

  // Returns a zero-copy view when the block lies within a single operand and
  // is contiguous there; otherwise materializes the slab(s) with
  // TensorBlockIO::Copy, which collapses to a memcpy per contiguous slab.
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorBlock block(TensorBlockDesc& desc, TensorBlockScratch& scratch,
                                                          bool root_of_expr_ast = false) const {
    static constexpr bool IsColMajor = Layout == static_cast<int>(ColMajor);

    if (desc.size() == 0) {
      return TensorBlock(internal::TensorBlockKind::kView, nullptr, desc.dimensions());
    }

    Index remaining = desc.offset();
    DSizes<Index, NumDims> out_coords;
    EIGEN_IF_CONSTEXPR (IsColMajor) {
      for (int i = NumDims - 1; i > 0; --i) {
        out_coords[i] = remaining / m_outputStrides[i];
        remaining -= out_coords[i] * m_outputStrides[i];
      }
      out_coords[0] = remaining;
    } else {
      for (int i = 0; i < NumDims - 1; ++i) {
        out_coords[i] = remaining / m_outputStrides[i];
        remaining -= out_coords[i] * m_outputStrides[i];
      }
      out_coords[NumDims - 1] = remaining;
    }

    const Index axis_start = out_coords[m_axis];
    const Index axis_size = desc.dimension(static_cast<int>(m_axis));
    const Index axis_end = axis_start + axis_size;

    // Fast path: a block that lies entirely within one operand and forms a
    // contiguous run of its storage needs no copy at all -- return a view
    // straight into A / B. This is what keeps a cwise expression that reads
    // the concatenation (e.g. `(A.concatenate(B, axis) + C)`) streaming: a
    // cwise consumer drops our destination buffer before calling block() (see
    // TensorCwiseBinaryOp::block), so without the view the slab would be
    // bounced through a scratch buffer and read straight back, doubling cache
    // traffic. Straddling blocks still need the merged buffer materialized
    // below.
    if (axis_end <= m_leftAxisSize) {
      if (isContiguousOperandSlab(m_leftImpl.dimensions(), desc.dimensions())) {
        Index left_src_offset = 0;
        for (int i = 0; i < NumDims; ++i) {
          left_src_offset += out_coords[i] * m_leftStrides[i];
        }
        return TensorBlock(internal::TensorBlockKind::kView, m_leftImpl.data() + left_src_offset, desc.dimensions());
      }
    } else if (axis_start >= m_leftAxisSize) {
      if (isContiguousOperandSlab(m_rightImpl.dimensions(), desc.dimensions())) {
        Index right_src_offset = (axis_start - m_leftAxisSize) * m_rightStrides[m_axis];
        for (int i = 0; i < NumDims; ++i) {
          if (i != m_axis) {
            right_src_offset += out_coords[i] * m_rightStrides[i];
          }
        }
        return TensorBlock(internal::TensorBlockKind::kView, m_rightImpl.data() + right_src_offset, desc.dimensions());
      }
    }

    typedef internal::TensorBlockIO<ScalarNoConst, Index, NumDims, Layout> TensorBlockIO;
    typedef typename TensorBlockIO::Dst TensorBlockIODst;
    typedef typename TensorBlockIO::Src TensorBlockIOSrc;

    // Strided destination buffers are safe here because we only ever write
    // dense slabs into them; allowing strided storage lets a root-of-AST
    // assignment materialize directly into the output tensor.
    typename TensorBlock::Storage block_storage =
        TensorBlock::prepareStorage(desc, scratch, /*allow_strided_storage=*/root_of_expr_ast);

    if (axis_start < m_leftAxisSize) {
      const Index left_rows_in_block = numext::mini(m_leftAxisSize, axis_end) - axis_start;
      DSizes<Index, NumDims> left_sub_dims = desc.dimensions();
      left_sub_dims[m_axis] = left_rows_in_block;

      Index left_src_offset = 0;
      for (int i = 0; i < NumDims; ++i) {
        left_src_offset += out_coords[i] * m_leftStrides[i];
      }

      typename TensorBlockIO::Dimensions left_strides(m_leftStrides);
      TensorBlockIOSrc src(left_strides, m_leftImpl.data(), left_src_offset);
      TensorBlockIODst dst(left_sub_dims, block_storage.strides(), block_storage.data(),
                           /*dst_offset=*/0);
      TensorBlockIO::Copy(dst, src);
    }

    if (axis_end > m_leftAxisSize) {
      const Index right_rows_in_block = axis_end - numext::maxi(m_leftAxisSize, axis_start);
      DSizes<Index, NumDims> right_sub_dims = desc.dimensions();
      right_sub_dims[m_axis] = right_rows_in_block;

      // Right operand has the same per-dim coords as out_coords except along
      // the concat axis, where it starts at max(0, axis_start - left_size).
      const Index right_axis_start = numext::maxi(Index(0), axis_start - m_leftAxisSize);
      Index right_src_offset = right_axis_start * m_rightStrides[m_axis];
      for (int i = 0; i < NumDims; ++i) {
        if (i != m_axis) {
          right_src_offset += out_coords[i] * m_rightStrides[i];
        }
      }

      // Offset within the materialized buffer where the right-side slab starts.
      const Index dst_axis_offset = numext::maxi(Index(0), m_leftAxisSize - axis_start);
      const Index dst_offset = dst_axis_offset * block_storage.strides()[m_axis];

      typename TensorBlockIO::Dimensions right_strides(m_rightStrides);
      TensorBlockIOSrc src(right_strides, m_rightImpl.data(), right_src_offset);
      TensorBlockIODst dst(right_sub_dims, block_storage.strides(), block_storage.data(), dst_offset);
      TensorBlockIO::Copy(dst, src);
    }

    return block_storage.AsTensorMaterializedBlock();
  }

  // The per-dim integer div/mod in this loop are the obvious "slow" candidates,
  // but the same TensorIntDivisor substitution was measured net-negative on
  // Intel Raptor Lake when prototyped for TensorBroadcasting (see the comment
  // on TensorBroadcasting::indexColMajor). Modern x86 hardware div (~20
  // cycles) amortizes well and the mul+shifts don't win back the added state.
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const {
    // Collect dimension-wise indices (subs).
    array<Index, NumDims> subs;
    EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
      for (int i = NumDims - 1; i > 0; --i) {
        subs[i] = index / m_outputStrides[i];
        index -= subs[i] * m_outputStrides[i];
      }
      subs[0] = index;
    } else {
      for (int i = 0; i < NumDims - 1; ++i) {
        subs[i] = index / m_outputStrides[i];
        index -= subs[i] * m_outputStrides[i];
      }
      subs[NumDims - 1] = index;
    }

    const Dimensions& left_dims = m_leftImpl.dimensions();
    if (subs[m_axis] < left_dims[m_axis]) {
      Index left_index;
      EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
        left_index = subs[0];
        EIGEN_UNROLL_LOOP
        for (int i = 1; i < NumDims; ++i) {
          left_index += (subs[i] % left_dims[i]) * m_leftStrides[i];
        }
      } else {
        left_index = subs[NumDims - 1];
        EIGEN_UNROLL_LOOP
        for (int i = NumDims - 2; i >= 0; --i) {
          left_index += (subs[i] % left_dims[i]) * m_leftStrides[i];
        }
      }
      return m_leftImpl.coeff(left_index);
    } else {
      subs[m_axis] -= left_dims[m_axis];
      const Dimensions& right_dims = m_rightImpl.dimensions();
      Index right_index;
      EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
        right_index = subs[0];
        EIGEN_UNROLL_LOOP
        for (int i = 1; i < NumDims; ++i) {
          right_index += (subs[i] % right_dims[i]) * m_rightStrides[i];
        }
      } else {
        right_index = subs[NumDims - 1];
        EIGEN_UNROLL_LOOP
        for (int i = NumDims - 2; i >= 0; --i) {
          right_index += (subs[i] % right_dims[i]) * m_rightStrides[i];
        }
      }
      return m_rightImpl.coeff(right_index);
    }
  }

  // When the packet sits entirely on one side of the concat boundary, delegate
  // to that operand's packet<>() rather than assembling PacketSize coeff()
  // calls. The packet stays on one side iff only the innermost dim varies
  // across the packet -- i.e. all other subs match between the first and last
  // index. When that holds, subs[m_axis] is either constant (m_axis is not
  // innermost) or monotonic non-decreasing (m_axis is innermost), so checking
  // just the endpoints decides the side. Otherwise subs[m_axis] can wrap back
  // through the boundary mid-packet (as when the inner dim has fewer than
  // PacketSize elements and the packet spills past the concat axis), so fall
  // back to scalars.
  template <int LoadMode>
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const {
    const int packetSize = PacketType<CoeffReturnType, Device>::size;
    EIGEN_STATIC_ASSERT((packetSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
    eigen_assert(index + packetSize - 1 < dimensions().TotalSize());

    array<Index, NumDims> subs;
    array<Index, NumDims> subs_end;
    Index remaining = index;
    Index remaining_end = index + packetSize - 1;
    EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
      for (int i = NumDims - 1; i > 0; --i) {
        subs[i] = remaining / m_outputStrides[i];
        remaining -= subs[i] * m_outputStrides[i];
        subs_end[i] = remaining_end / m_outputStrides[i];
        remaining_end -= subs_end[i] * m_outputStrides[i];
      }
      subs[0] = remaining;
      subs_end[0] = remaining_end;
    } else {
      for (int i = 0; i < NumDims - 1; ++i) {
        subs[i] = remaining / m_outputStrides[i];
        remaining -= subs[i] * m_outputStrides[i];
        subs_end[i] = remaining_end / m_outputStrides[i];
        remaining_end -= subs_end[i] * m_outputStrides[i];
      }
      subs[NumDims - 1] = remaining;
      subs_end[NumDims - 1] = remaining_end;
    }

    const Dimensions& left_dims = m_leftImpl.dimensions();
    const Index left_axis_size = left_dims[m_axis];

    constexpr int innermost = (static_cast<int>(Layout) == static_cast<int>(ColMajor)) ? 0 : NumDims - 1;
    bool packet_in_single_inner_row = true;
    EIGEN_UNROLL_LOOP
    for (int i = 0; i < NumDims; ++i) {
      if (i != innermost && subs[i] != subs_end[i]) {
        packet_in_single_inner_row = false;
      }
    }

    const bool on_left =
        packet_in_single_inner_row && subs[m_axis] < left_axis_size && subs_end[m_axis] < left_axis_size;
    const bool on_right =
        packet_in_single_inner_row && subs[m_axis] >= left_axis_size && subs_end[m_axis] >= left_axis_size;

    if (on_left) {
      Index left_index;
      EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
        left_index = subs[0];
        EIGEN_UNROLL_LOOP
        for (int i = 1; i < NumDims; ++i) {
          left_index += subs[i] * m_leftStrides[i];
        }
      } else {
        left_index = subs[NumDims - 1];
        EIGEN_UNROLL_LOOP
        for (int i = NumDims - 2; i >= 0; --i) {
          left_index += subs[i] * m_leftStrides[i];
        }
      }
      return m_leftImpl.template packet<LoadMode>(left_index);
    }
    if (on_right) {
      subs[m_axis] -= left_axis_size;
      Index right_index;
      EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
        right_index = subs[0];
        EIGEN_UNROLL_LOOP
        for (int i = 1; i < NumDims; ++i) {
          right_index += subs[i] * m_rightStrides[i];
        }
      } else {
        right_index = subs[NumDims - 1];
        EIGEN_UNROLL_LOOP
        for (int i = NumDims - 2; i >= 0; --i) {
          right_index += subs[i] * m_rightStrides[i];
        }
      }
      return m_rightImpl.template packet<LoadMode>(right_index);
    }

    // The packet straddles the boundary or spans multiple inner rows: fall
    // back to assembling scalars.
    EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment) CoeffReturnType values[packetSize];
    EIGEN_UNROLL_LOOP
    for (int i = 0; i < packetSize; ++i) {
      values[i] = coeff(index + i);
    }
    PacketReturnType rslt = internal::pload<PacketReturnType>(values);
    return rslt;
  }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(bool vectorized) const {
    const double compute_cost = NumDims * (2 * TensorOpCost::AddCost<Index>() + 2 * TensorOpCost::MulCost<Index>() +
                                           TensorOpCost::DivCost<Index>() + TensorOpCost::ModCost<Index>());
    const double lhs_size = m_leftImpl.dimensions().TotalSize();
    const double rhs_size = m_rightImpl.dimensions().TotalSize();
    return (lhs_size / (lhs_size + rhs_size)) * m_leftImpl.costPerCoeff(vectorized) +
           (rhs_size / (lhs_size + rhs_size)) * m_rightImpl.costPerCoeff(vectorized) + TensorOpCost(0, 0, compute_cost);
  }

  EIGEN_DEVICE_FUNC EvaluatorPointerType data() const { return nullptr; }

 protected:
  Dimensions m_dimensions;
  array<Index, NumDims> m_outputStrides;
  array<Index, NumDims> m_leftStrides;
  array<Index, NumDims> m_rightStrides;
  TensorEvaluator<LeftArgType, Device> m_leftImpl;
  TensorEvaluator<RightArgType, Device> m_rightImpl;
  const Device EIGEN_DEVICE_REF m_device;
  const Axis m_axis;
  Index m_leftAxisSize;
};

// Eval as lvalue
template <typename Axis, typename LeftArgType, typename RightArgType, typename Device>
struct TensorEvaluator<TensorConcatenationOp<Axis, LeftArgType, RightArgType>, Device>
    : public TensorEvaluator<const TensorConcatenationOp<Axis, LeftArgType, RightArgType>, Device> {
  typedef TensorEvaluator<const TensorConcatenationOp<Axis, LeftArgType, RightArgType>, Device> Base;
  typedef TensorConcatenationOp<Axis, LeftArgType, RightArgType> XprType;
  typedef typename Base::Dimensions Dimensions;
  static constexpr int NumDims = Base::NumDims;
  static constexpr int Layout = TensorEvaluator<LeftArgType, Device>::Layout;
  enum {
    IsAligned = false,
    PacketAccess =
        TensorEvaluator<LeftArgType, Device>::PacketAccess && TensorEvaluator<RightArgType, Device>::PacketAccess,
    // writeBlock() splits the block at the concat axis and copies each piece
    // straight into the operand's buffer, so both must expose raw storage.
    BlockAccess = TensorEvaluator<LeftArgType, Device>::RawAccess && TensorEvaluator<RightArgType, Device>::RawAccess,
    // The coeff/packet write path pays a div/mod cascade plus a per-dim mod
    // for every scalar; the block path is a pair of bulk copies. Mirrors the
    // rvalue evaluator.
    PreferBlockAccess = true,
    RawAccess = false
  };

  typedef std::remove_const_t<typename XprType::Scalar> ScalarNoConst;

  //===- Tensor block evaluation strategy (see TensorBlock.h) -------------===//
  typedef internal::TensorBlockDescriptor<NumDims, typename XprType::Index> TensorBlockDesc;
  //===--------------------------------------------------------------------===//

  // The ColMajor-only static_assert lives in coeffRef/writePacket rather than
  // here so that passthrough evaluators (e.g. TensorSlicingOp's) can
  // instantiate this type for RowMajor concat operands without ever calling
  // its lvalue methods. writeBlock() below is layout-generic, so tiled
  // assignments through a RowMajor concatenation are supported.
  EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device) : Base(op, device) {}

  typedef typename XprType::Index Index;
  typedef typename XprType::Scalar Scalar;
  typedef typename XprType::CoeffReturnType CoeffReturnType;
  typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType& coeffRef(Index index) const {
    EIGEN_STATIC_ASSERT((static_cast<int>(Layout) == static_cast<int>(ColMajor)), YOU_MADE_A_PROGRAMMING_MISTAKE);
    // Collect dimension-wise indices (subs).
    array<Index, Base::NumDims> subs;
    for (int i = Base::NumDims - 1; i > 0; --i) {
      subs[i] = index / this->m_outputStrides[i];
      index -= subs[i] * this->m_outputStrides[i];
    }
    subs[0] = index;

    const Dimensions& left_dims = this->m_leftImpl.dimensions();
    if (subs[this->m_axis] < left_dims[this->m_axis]) {
      Index left_index = subs[0];
      for (int i = 1; i < Base::NumDims; ++i) {
        left_index += (subs[i] % left_dims[i]) * this->m_leftStrides[i];
      }
      return this->m_leftImpl.coeffRef(left_index);
    } else {
      subs[this->m_axis] -= left_dims[this->m_axis];
      const Dimensions& right_dims = this->m_rightImpl.dimensions();
      Index right_index = subs[0];
      for (int i = 1; i < Base::NumDims; ++i) {
        right_index += (subs[i] % right_dims[i]) * this->m_rightStrides[i];
      }
      return this->m_rightImpl.coeffRef(right_index);
    }
  }

  template <int StoreMode>
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void writePacket(Index index, const PacketReturnType& x) const {
    EIGEN_STATIC_ASSERT((static_cast<int>(Layout) == static_cast<int>(ColMajor)), YOU_MADE_A_PROGRAMMING_MISTAKE);
    const int packetSize = PacketType<CoeffReturnType, Device>::size;
    EIGEN_STATIC_ASSERT((packetSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
    eigen_assert(index + packetSize - 1 < this->dimensions().TotalSize());

    EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment) CoeffReturnType values[packetSize];
    internal::pstore<CoeffReturnType, PacketReturnType>(values, x);
    for (int i = 0; i < packetSize; ++i) {
      coeffRef(index + i) = values[i];
    }
  }

  // Mirror of the rvalue block(): split the block at the concat axis and copy
  // each piece into the corresponding operand's buffer.
  template <typename TensorBlock>
  EIGEN_STRONG_INLINE void writeBlock(const TensorBlockDesc& desc, const TensorBlock& block) {
    if (desc.size() == 0) return;
    eigen_assert(this->m_leftImpl.data() != nullptr && this->m_rightImpl.data() != nullptr);

    const DSizes<Index, NumDims> block_strides = internal::strides<Layout>(desc.dimensions());

    // Materialize the block into a temporary buffer if it is lazy.
    const ScalarNoConst* block_buffer = block.data();
    void* mem = nullptr;
    if (block_buffer == nullptr) {
      mem = this->m_device.allocate(desc.size() * sizeof(Scalar));
      ScalarNoConst* buf = static_cast<ScalarNoConst*>(mem);

      typedef internal::TensorBlockAssignment<ScalarNoConst, NumDims, typename TensorBlock::XprType, Index>
          TensorBlockAssignment;
      TensorBlockAssignment::Run(TensorBlockAssignment::target(desc.dimensions(), block_strides, buf), block.expr());

      block_buffer = buf;
    }

    // Decompose the block's offset into output coordinates.
    Index remaining = desc.offset();
    DSizes<Index, NumDims> out_coords;
    EIGEN_IF_CONSTEXPR (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
      for (int i = NumDims - 1; i > 0; --i) {
        out_coords[i] = remaining / this->m_outputStrides[i];
        remaining -= out_coords[i] * this->m_outputStrides[i];
      }
      out_coords[0] = remaining;
    } else {
      for (int i = 0; i < NumDims - 1; ++i) {
        out_coords[i] = remaining / this->m_outputStrides[i];
        remaining -= out_coords[i] * this->m_outputStrides[i];
      }
      out_coords[NumDims - 1] = remaining;
    }

    const Index axis_start = out_coords[this->m_axis];
    const Index axis_size = desc.dimension(static_cast<int>(this->m_axis));
    const Index axis_end = axis_start + axis_size;
    const Index left_axis_size = this->m_leftAxisSize;

    typedef internal::TensorBlockIO<ScalarNoConst, Index, NumDims, Layout> TensorBlockIO;
    typedef typename TensorBlockIO::Dst TensorBlockIODst;
    typedef typename TensorBlockIO::Src TensorBlockIOSrc;

    if (axis_start < left_axis_size) {
      DSizes<Index, NumDims> left_sub_dims = desc.dimensions();
      left_sub_dims[this->m_axis] = numext::mini(left_axis_size, axis_end) - axis_start;

      Index left_dst_offset = 0;
      for (int i = 0; i < NumDims; ++i) {
        left_dst_offset += out_coords[i] * this->m_leftStrides[i];
      }

      TensorBlockIOSrc src(block_strides, block_buffer, /*src_offset=*/0);
      TensorBlockIODst dst(left_sub_dims, typename TensorBlockIO::Dimensions(this->m_leftStrides),
                           this->m_leftImpl.data(), left_dst_offset);
      TensorBlockIO::Copy(dst, src);
    }

    if (axis_end > left_axis_size) {
      DSizes<Index, NumDims> right_sub_dims = desc.dimensions();
      right_sub_dims[this->m_axis] = axis_end - numext::maxi(left_axis_size, axis_start);

      const Index right_axis_start = numext::maxi(Index(0), axis_start - left_axis_size);
      Index right_dst_offset = right_axis_start * this->m_rightStrides[this->m_axis];
      for (int i = 0; i < NumDims; ++i) {
        if (i != this->m_axis) {
          right_dst_offset += out_coords[i] * this->m_rightStrides[i];
        }
      }

      // Offset within the block buffer where the right-side piece starts.
      const Index src_offset = numext::maxi(Index(0), left_axis_size - axis_start) * block_strides[this->m_axis];

      TensorBlockIOSrc src(block_strides, block_buffer, src_offset);
      TensorBlockIODst dst(right_sub_dims, typename TensorBlockIO::Dimensions(this->m_rightStrides),
                           this->m_rightImpl.data(), right_dst_offset);
      TensorBlockIO::Copy(dst, src);
    }

    // Deallocate temporary buffer used for the block materialization.
    if (mem != nullptr) this->m_device.deallocate(mem);
  }
};

}  // end namespace Eigen

#endif  // EIGEN_TENSOR_TENSOR_CONCATENATION_H
