// 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 struct CoherentPadOp; template struct traits> : public traits { typedef typename internal::remove_all::type PlainXprType; typedef typename internal::ref_selector::type XprNested; typedef typename std::remove_reference_t XprNested_; enum : int { IsRowMajor = traits::Flags & RowMajorBit, SizeAtCompileTime = SizeAtCompileTime_, RowsAtCompileTime = IsRowMajor ? 1 : SizeAtCompileTime, ColsAtCompileTime = IsRowMajor ? SizeAtCompileTime : 1, MaxRowsAtCompileTime = RowsAtCompileTime, MaxColsAtCompileTime = ColsAtCompileTime, Flags = traits::Flags & ~NestByRefBit, }; }; // Pads a vector with zeros to a given size. template struct CoherentPadOp : public dense_xpr_base>::type { typedef typename internal::generic_xpr_base>::type Base; EIGEN_GENERIC_PUBLIC_INTERFACE(CoherentPadOp) using XprNested = typename traits::XprNested; using XprNested_ = typename traits::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::IsRowMajor ? Index(1) : size(); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index cols() const { return traits::IsRowMajor ? size() : Index(1); } private: XprNested xpr_; const internal::variable_if_dynamic size_; }; // Adapted from the Replicate evaluator. template struct unary_evaluator> : evaluator_base> { typedef CoherentPadOp XprType; typedef typename internal::remove_all_t CoeffReturnType; typedef typename internal::nested_eval::type ArgTypeNested; typedef internal::remove_all_t ArgTypeNestedCleaned; enum { CoeffReadCost = evaluator::CoeffReadCost, LinearAccessMask = XprType::IsVectorAtCompileTime ? LinearAccessBit : 0, Flags = evaluator::Flags & (HereditaryBits | LinearAccessMask | RowMajorBit), Alignment = evaluator::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 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 EIGEN_STRONG_INLINE PacketType packet(Index index) const { constexpr int kPacketSize = unpacket_traits::size; if (index + kPacketSize <= m_size.value()) { return m_argImpl.template packet(index); } else if (index < m_size.value()) { // Partial packet. EIGEN_ALIGN_MAX std::remove_const_t 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(values); } return pset1(CoeffReturnType(0)); } protected: const ArgTypeNested m_arg; evaluator m_argImpl; const variable_if_dynamic m_size; }; } // namespace internal } // namespace Eigen #endif // EIGEN_CWISE_BINARY_OP_H