| // This file is part of Eigen, a lightweight C++ template library | 
 | // for linear algebra. | 
 | // | 
 | // Copyright (C) 2020 The Eigen Team. | 
 | // | 
 | // 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/. | 
 |  | 
 | #ifndef EIGEN_COHERENT_PAD_OP_H | 
 | #define EIGEN_COHERENT_PAD_OP_H | 
 |  | 
 | #include "./InternalHeaderCheck.h" | 
 |  | 
 | namespace Eigen { | 
 |  | 
 | namespace internal { | 
 |  | 
 | // Pads a vector with zeros to a given size. | 
 | template <typename XprType, int SizeAtCompileTime_> | 
 | struct CoherentPadOp; | 
 |  | 
 | template <typename XprType, int SizeAtCompileTime_> | 
 | struct traits<CoherentPadOp<XprType, SizeAtCompileTime_>> : public traits<XprType> { | 
 |   typedef typename internal::remove_all<XprType>::type PlainXprType; | 
 |   typedef typename internal::ref_selector<XprType>::type XprNested; | 
 |   typedef typename std::remove_reference_t<XprNested> XprNested_; | 
 |   enum : int { | 
 |     IsRowMajor = traits<PlainXprType>::Flags & RowMajorBit, | 
 |     SizeAtCompileTime = SizeAtCompileTime_, | 
 |     RowsAtCompileTime = IsRowMajor ? 1 : SizeAtCompileTime, | 
 |     ColsAtCompileTime = IsRowMajor ? SizeAtCompileTime : 1, | 
 |     MaxRowsAtCompileTime = RowsAtCompileTime, | 
 |     MaxColsAtCompileTime = ColsAtCompileTime, | 
 |     Flags = traits<XprType>::Flags & ~NestByRefBit, | 
 |   }; | 
 | }; | 
 |  | 
 | // Pads a vector with zeros to a given size. | 
 | template <typename XprType, int SizeAtCompileTime_> | 
 | struct CoherentPadOp : public dense_xpr_base<CoherentPadOp<XprType, SizeAtCompileTime_>>::type { | 
 |   typedef typename internal::generic_xpr_base<CoherentPadOp<XprType, SizeAtCompileTime_>>::type Base; | 
 |   EIGEN_GENERIC_PUBLIC_INTERFACE(CoherentPadOp) | 
 |  | 
 |   using XprNested = typename traits<CoherentPadOp>::XprNested; | 
 |   using XprNested_ = typename traits<CoherentPadOp>::XprNested_; | 
 |   using NestedExpression = XprNested_; | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoherentPadOp() = delete; | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoherentPadOp(const CoherentPadOp&) = default; | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoherentPadOp(CoherentPadOp&& other) = default; | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoherentPadOp(const XprType& xpr, Index size) : xpr_(xpr), size_(size) { | 
 |     static_assert(XprNested_::IsVectorAtCompileTime, "input type must be a vector"); | 
 |   } | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const XprNested_& nestedExpression() const { return xpr_; } | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const { return size_.value(); } | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rows() const { | 
 |     return traits<CoherentPadOp>::IsRowMajor ? Index(1) : size(); | 
 |   } | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const { | 
 |     return traits<CoherentPadOp>::IsRowMajor ? size() : Index(1); | 
 |   } | 
 |  | 
 |  private: | 
 |   XprNested xpr_; | 
 |   const internal::variable_if_dynamic<Index, SizeAtCompileTime> size_; | 
 | }; | 
 |  | 
 | // Adapted from the Replicate evaluator. | 
 | template <typename ArgType, int SizeAtCompileTime> | 
 | struct unary_evaluator<CoherentPadOp<ArgType, SizeAtCompileTime>> | 
 |     : evaluator_base<CoherentPadOp<ArgType, SizeAtCompileTime>> { | 
 |   typedef CoherentPadOp<ArgType, SizeAtCompileTime> XprType; | 
 |   typedef typename internal::remove_all_t<typename XprType::CoeffReturnType> CoeffReturnType; | 
 |   typedef typename internal::nested_eval<ArgType, 1>::type ArgTypeNested; | 
 |   typedef internal::remove_all_t<ArgTypeNested> ArgTypeNestedCleaned; | 
 |  | 
 |   enum { | 
 |     CoeffReadCost = evaluator<ArgTypeNestedCleaned>::CoeffReadCost, | 
 |     LinearAccessMask = XprType::IsVectorAtCompileTime ? LinearAccessBit : 0, | 
 |     Flags = evaluator<ArgTypeNestedCleaned>::Flags & (HereditaryBits | LinearAccessMask | RowMajorBit), | 
 |     Alignment = evaluator<ArgTypeNestedCleaned>::Alignment | 
 |   }; | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE explicit unary_evaluator(const XprType& pad) | 
 |       : m_arg(pad.nestedExpression()), m_argImpl(m_arg), m_size(pad.nestedExpression().size()) {} | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { | 
 |     EIGEN_IF_CONSTEXPR(XprType::IsRowMajor) { | 
 |       if (col < m_size.value()) { | 
 |         return m_argImpl.coeff(1, col); | 
 |       } | 
 |     } | 
 |     else { | 
 |       if (row < m_size.value()) { | 
 |         return m_argImpl.coeff(row, 1); | 
 |       } | 
 |     } | 
 |     return CoeffReturnType(0); | 
 |   } | 
 |  | 
 |   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const { | 
 |     if (index < m_size.value()) { | 
 |       return m_argImpl.coeff(index); | 
 |     } | 
 |     return CoeffReturnType(0); | 
 |   } | 
 |  | 
 |   template <int LoadMode, typename PacketType> | 
 |   EIGEN_STRONG_INLINE PacketType packet(Index row, Index col) const { | 
 |     // AutoDiff scalar's derivative must be a vector, which is enforced by static assert. | 
 |     // Defer to linear access for simplicity. | 
 |     EIGEN_IF_CONSTEXPR(XprType::IsRowMajor) { return packet(col); } | 
 |     return packet(row); | 
 |   } | 
 |  | 
 |   template <int LoadMode, typename PacketType> | 
 |   EIGEN_STRONG_INLINE PacketType packet(Index index) const { | 
 |     constexpr int kPacketSize = unpacket_traits<PacketType>::size; | 
 |     if (index + kPacketSize <= m_size.value()) { | 
 |       return m_argImpl.template packet<LoadMode, PacketType>(index); | 
 |     } else if (index < m_size.value()) { | 
 |       // Partial packet. | 
 |       EIGEN_ALIGN_MAX std::remove_const_t<CoeffReturnType> values[kPacketSize]; | 
 |       const int partial = m_size.value() - index; | 
 |       for (int i = 0; i < partial && i < kPacketSize; ++i) { | 
 |         values[i] = m_argImpl.coeff(index + i); | 
 |       } | 
 |       for (int i = partial; i < kPacketSize; ++i) { | 
 |         values[i] = CoeffReturnType(0); | 
 |       } | 
 |       return pload<PacketType>(values); | 
 |     } | 
 |     return pset1<PacketType>(CoeffReturnType(0)); | 
 |   } | 
 |  | 
 |  protected: | 
 |   const ArgTypeNested m_arg; | 
 |   evaluator<ArgTypeNestedCleaned> m_argImpl; | 
 |   const variable_if_dynamic<Index, ArgTypeNestedCleaned::SizeAtCompileTime> m_size; | 
 | }; | 
 |  | 
 | }  // namespace internal | 
 |  | 
 | }  // namespace Eigen | 
 |  | 
 | #endif  // EIGEN_CWISE_BINARY_OP_H |