|  | // This file is part of Eigen, a lightweight C++ template library | 
|  | // for linear algebra. | 
|  | // | 
|  | // Copyright (C) 2017 Gael Guennebaud <gael.guennebaud@inria.fr> | 
|  | // | 
|  | // 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_INDEXED_VIEW_H | 
|  | #define EIGEN_INDEXED_VIEW_H | 
|  |  | 
|  | // IWYU pragma: private | 
|  | #include "./InternalHeaderCheck.h" | 
|  |  | 
|  | namespace Eigen { | 
|  |  | 
|  | namespace internal { | 
|  |  | 
|  | template <typename XprType, typename RowIndices, typename ColIndices> | 
|  | struct traits<IndexedView<XprType, RowIndices, ColIndices>> : traits<XprType> { | 
|  | enum { | 
|  | RowsAtCompileTime = int(array_size<RowIndices>::value), | 
|  | ColsAtCompileTime = int(array_size<ColIndices>::value), | 
|  | MaxRowsAtCompileTime = RowsAtCompileTime, | 
|  | MaxColsAtCompileTime = ColsAtCompileTime, | 
|  |  | 
|  | XprTypeIsRowMajor = (int(traits<XprType>::Flags) & RowMajorBit) != 0, | 
|  | IsRowMajor = (MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1)   ? 1 | 
|  | : (MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1) ? 0 | 
|  | : XprTypeIsRowMajor, | 
|  |  | 
|  | RowIncr = int(get_compile_time_incr<RowIndices>::value), | 
|  | ColIncr = int(get_compile_time_incr<ColIndices>::value), | 
|  | InnerIncr = IsRowMajor ? ColIncr : RowIncr, | 
|  | OuterIncr = IsRowMajor ? RowIncr : ColIncr, | 
|  |  | 
|  | HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), | 
|  | XprInnerStride = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time<XprType>::ret) | 
|  | : int(outer_stride_at_compile_time<XprType>::ret), | 
|  | XprOuterstride = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time<XprType>::ret) | 
|  | : int(inner_stride_at_compile_time<XprType>::ret), | 
|  |  | 
|  | InnerSize = XprTypeIsRowMajor ? ColsAtCompileTime : RowsAtCompileTime, | 
|  | IsBlockAlike = InnerIncr == 1 && OuterIncr == 1, | 
|  | IsInnerPannel = HasSameStorageOrderAsXprType && | 
|  | is_same<AllRange<InnerSize>, std::conditional_t<XprTypeIsRowMajor, ColIndices, RowIndices>>::value, | 
|  |  | 
|  | InnerStrideAtCompileTime = | 
|  | InnerIncr < 0 || InnerIncr == DynamicIndex || XprInnerStride == Dynamic || InnerIncr == UndefinedIncr | 
|  | ? Dynamic | 
|  | : XprInnerStride * InnerIncr, | 
|  | OuterStrideAtCompileTime = | 
|  | OuterIncr < 0 || OuterIncr == DynamicIndex || XprOuterstride == Dynamic || OuterIncr == UndefinedIncr | 
|  | ? Dynamic | 
|  | : XprOuterstride * OuterIncr, | 
|  |  | 
|  | ReturnAsScalar = is_same<RowIndices, SingleRange>::value && is_same<ColIndices, SingleRange>::value, | 
|  | ReturnAsBlock = (!ReturnAsScalar) && IsBlockAlike, | 
|  | ReturnAsIndexedView = (!ReturnAsScalar) && (!ReturnAsBlock), | 
|  |  | 
|  | // FIXME we deal with compile-time strides if and only if we have DirectAccessBit flag, | 
|  | // but this is too strict regarding negative strides... | 
|  | DirectAccessMask = | 
|  | (int(InnerIncr) != UndefinedIncr && int(OuterIncr) != UndefinedIncr && InnerIncr >= 0 && OuterIncr >= 0) | 
|  | ? DirectAccessBit | 
|  | : 0, | 
|  | FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, | 
|  | FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0, | 
|  | FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0, | 
|  | Flags = (traits<XprType>::Flags & (HereditaryBits | DirectAccessMask)) | FlagsLvalueBit | FlagsRowMajorBit | | 
|  | FlagsLinearAccessBit | 
|  | }; | 
|  |  | 
|  | typedef Block<XprType, RowsAtCompileTime, ColsAtCompileTime, IsInnerPannel> BlockType; | 
|  | }; | 
|  |  | 
|  | template <typename XprType, typename RowIndices, typename ColIndices, typename StorageKind, bool DirectAccess> | 
|  | class IndexedViewImpl; | 
|  |  | 
|  | }  // namespace internal | 
|  |  | 
|  | /** \class IndexedView | 
|  | * \ingroup Core_Module | 
|  | * | 
|  | * \brief Expression of a non-sequential sub-matrix defined by arbitrary sequences of row and column indices | 
|  | * | 
|  | * \tparam XprType the type of the expression in which we are taking the intersections of sub-rows and sub-columns | 
|  | * \tparam RowIndices the type of the object defining the sequence of row indices | 
|  | * \tparam ColIndices the type of the object defining the sequence of column indices | 
|  | * | 
|  | * This class represents an expression of a sub-matrix (or sub-vector) defined as the intersection | 
|  | * of sub-sets of rows and columns, that are themself defined by generic sequences of row indices \f$ | 
|  | * \{r_0,r_1,..r_{m-1}\} \f$ and column indices \f$ \{c_0,c_1,..c_{n-1} \}\f$. Let \f$ A \f$  be the nested matrix, then | 
|  | * the resulting matrix \f$ B \f$ has \c m rows and \c n columns, and its entries are given by: \f$ B(i,j) = A(r_i,c_j) | 
|  | * \f$. | 
|  | * | 
|  | * The \c RowIndices and \c ColIndices types must be compatible with the following API: | 
|  | * \code | 
|  | * <integral type> operator[](Index) const; | 
|  | * Index size() const; | 
|  | * \endcode | 
|  | * | 
|  | * Typical supported types thus include: | 
|  | *  - std::vector<int> | 
|  | *  - std::valarray<int> | 
|  | *  - std::array<int> | 
|  | *  - Eigen::ArrayXi | 
|  | *  - decltype(ArrayXi::LinSpaced(...)) | 
|  | *  - Any view/expressions of the previous types | 
|  | *  - Eigen::ArithmeticSequence | 
|  | *  - Eigen::internal::AllRange     (helper for Eigen::placeholders::all) | 
|  | *  - Eigen::internal::SingleRange  (helper for single index) | 
|  | *  - etc. | 
|  | * | 
|  | * In typical usages of %Eigen, this class should never be used directly. It is the return type of | 
|  | * DenseBase::operator()(const RowIndices&, const ColIndices&). | 
|  | * | 
|  | * \sa class Block | 
|  | */ | 
|  | template <typename XprType, typename RowIndices, typename ColIndices> | 
|  | class IndexedView | 
|  | : public internal::IndexedViewImpl<XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind, | 
|  | (internal::traits<IndexedView<XprType, RowIndices, ColIndices>>::Flags & | 
|  | DirectAccessBit) != 0> { | 
|  | public: | 
|  | typedef typename internal::IndexedViewImpl< | 
|  | XprType, RowIndices, ColIndices, typename internal::traits<XprType>::StorageKind, | 
|  | (internal::traits<IndexedView<XprType, RowIndices, ColIndices>>::Flags & DirectAccessBit) != 0> | 
|  | Base; | 
|  | EIGEN_GENERIC_PUBLIC_INTERFACE(IndexedView) | 
|  | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedView) | 
|  |  | 
|  | template <typename T0, typename T1> | 
|  | IndexedView(XprType& xpr, const T0& rowIndices, const T1& colIndices) : Base(xpr, rowIndices, colIndices) {} | 
|  | }; | 
|  |  | 
|  | namespace internal { | 
|  |  | 
|  | // Generic API dispatcher | 
|  | template <typename XprType, typename RowIndices, typename ColIndices, typename StorageKind, bool DirectAccess> | 
|  | class IndexedViewImpl : public internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices>>::type { | 
|  | public: | 
|  | typedef typename internal::generic_xpr_base<IndexedView<XprType, RowIndices, ColIndices>>::type Base; | 
|  | typedef typename internal::ref_selector<XprType>::non_const_type MatrixTypeNested; | 
|  | typedef internal::remove_all_t<XprType> NestedExpression; | 
|  | typedef typename XprType::Scalar Scalar; | 
|  |  | 
|  | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedViewImpl) | 
|  |  | 
|  | template <typename T0, typename T1> | 
|  | IndexedViewImpl(XprType& xpr, const T0& rowIndices, const T1& colIndices) | 
|  | : m_xpr(xpr), m_rowIndices(rowIndices), m_colIndices(colIndices) {} | 
|  |  | 
|  | /** \returns number of rows */ | 
|  | Index rows() const { return internal::index_list_size(m_rowIndices); } | 
|  |  | 
|  | /** \returns number of columns */ | 
|  | Index cols() const { return internal::index_list_size(m_colIndices); } | 
|  |  | 
|  | /** \returns the nested expression */ | 
|  | const internal::remove_all_t<XprType>& nestedExpression() const { return m_xpr; } | 
|  |  | 
|  | /** \returns the nested expression */ | 
|  | std::remove_reference_t<XprType>& nestedExpression() { return m_xpr; } | 
|  |  | 
|  | /** \returns a const reference to the object storing/generating the row indices */ | 
|  | const RowIndices& rowIndices() const { return m_rowIndices; } | 
|  |  | 
|  | /** \returns a const reference to the object storing/generating the column indices */ | 
|  | const ColIndices& colIndices() const { return m_colIndices; } | 
|  |  | 
|  | constexpr Scalar& coeffRef(Index rowId, Index colId) { | 
|  | return nestedExpression().coeffRef(m_rowIndices[rowId], m_colIndices[colId]); | 
|  | } | 
|  |  | 
|  | constexpr const Scalar& coeffRef(Index rowId, Index colId) const { | 
|  | return nestedExpression().coeffRef(m_rowIndices[rowId], m_colIndices[colId]); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | MatrixTypeNested m_xpr; | 
|  | RowIndices m_rowIndices; | 
|  | ColIndices m_colIndices; | 
|  | }; | 
|  |  | 
|  | template <typename XprType, typename RowIndices, typename ColIndices, typename StorageKind> | 
|  | class IndexedViewImpl<XprType, RowIndices, ColIndices, StorageKind, true> | 
|  | : public IndexedViewImpl<XprType, RowIndices, ColIndices, StorageKind, false> { | 
|  | public: | 
|  | using Base = internal::IndexedViewImpl<XprType, RowIndices, ColIndices, | 
|  | typename internal::traits<XprType>::StorageKind, false>; | 
|  | using Derived = IndexedView<XprType, RowIndices, ColIndices>; | 
|  |  | 
|  | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(IndexedViewImpl) | 
|  |  | 
|  | template <typename T0, typename T1> | 
|  | IndexedViewImpl(XprType& xpr, const T0& rowIndices, const T1& colIndices) : Base(xpr, rowIndices, colIndices) {} | 
|  |  | 
|  | Index rowIncrement() const { | 
|  | if (traits<Derived>::RowIncr != DynamicIndex && traits<Derived>::RowIncr != UndefinedIncr) { | 
|  | return traits<Derived>::RowIncr; | 
|  | } | 
|  | return get_runtime_incr(this->rowIndices()); | 
|  | } | 
|  | Index colIncrement() const { | 
|  | if (traits<Derived>::ColIncr != DynamicIndex && traits<Derived>::ColIncr != UndefinedIncr) { | 
|  | return traits<Derived>::ColIncr; | 
|  | } | 
|  | return get_runtime_incr(this->colIndices()); | 
|  | } | 
|  |  | 
|  | Index innerIncrement() const { return traits<Derived>::IsRowMajor ? colIncrement() : rowIncrement(); } | 
|  |  | 
|  | Index outerIncrement() const { return traits<Derived>::IsRowMajor ? rowIncrement() : colIncrement(); } | 
|  |  | 
|  | std::decay_t<typename XprType::Scalar>* data() { | 
|  | Index row_offset = this->rowIndices()[0] * this->nestedExpression().rowStride(); | 
|  | Index col_offset = this->colIndices()[0] * this->nestedExpression().colStride(); | 
|  | return this->nestedExpression().data() + row_offset + col_offset; | 
|  | } | 
|  |  | 
|  | const std::decay_t<typename XprType::Scalar>* data() const { | 
|  | Index row_offset = this->rowIndices()[0] * this->nestedExpression().rowStride(); | 
|  | Index col_offset = this->colIndices()[0] * this->nestedExpression().colStride(); | 
|  | return this->nestedExpression().data() + row_offset + col_offset; | 
|  | } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index innerStride() const EIGEN_NOEXCEPT { | 
|  | if (traits<Derived>::InnerStrideAtCompileTime != Dynamic) { | 
|  | return traits<Derived>::InnerStrideAtCompileTime; | 
|  | } | 
|  | return innerIncrement() * this->nestedExpression().innerStride(); | 
|  | } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR inline Index outerStride() const EIGEN_NOEXCEPT { | 
|  | if (traits<Derived>::OuterStrideAtCompileTime != Dynamic) { | 
|  | return traits<Derived>::OuterStrideAtCompileTime; | 
|  | } | 
|  | return outerIncrement() * this->nestedExpression().outerStride(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename ArgType, typename RowIndices, typename ColIndices> | 
|  | struct unary_evaluator<IndexedView<ArgType, RowIndices, ColIndices>, IndexBased> | 
|  | : evaluator_base<IndexedView<ArgType, RowIndices, ColIndices>> { | 
|  | typedef IndexedView<ArgType, RowIndices, ColIndices> XprType; | 
|  |  | 
|  | enum { | 
|  | CoeffReadCost = evaluator<ArgType>::CoeffReadCost /* TODO + cost of row/col index */, | 
|  |  | 
|  | FlagsLinearAccessBit = | 
|  | (traits<XprType>::RowsAtCompileTime == 1 || traits<XprType>::ColsAtCompileTime == 1) ? LinearAccessBit : 0, | 
|  |  | 
|  | FlagsRowMajorBit = traits<XprType>::FlagsRowMajorBit, | 
|  |  | 
|  | Flags = (evaluator<ArgType>::Flags & (HereditaryBits & ~RowMajorBit /*| LinearAccessBit | DirectAccessBit*/)) | | 
|  | FlagsLinearAccessBit | FlagsRowMajorBit, | 
|  |  | 
|  | Alignment = 0 | 
|  | }; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& xpr) : m_argImpl(xpr.nestedExpression()), m_xpr(xpr) { | 
|  | EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); | 
|  | } | 
|  |  | 
|  | typedef typename XprType::Scalar Scalar; | 
|  | typedef typename XprType::CoeffReturnType CoeffReturnType; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index row, Index col) const { | 
|  | eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && | 
|  | m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); | 
|  | return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); | 
|  | } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col) { | 
|  | eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && | 
|  | m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); | 
|  | return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); | 
|  | } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { | 
|  | EIGEN_STATIC_ASSERT_LVALUE(XprType) | 
|  | Index row = XprType::RowsAtCompileTime == 1 ? 0 : index; | 
|  | Index col = XprType::RowsAtCompileTime == 1 ? index : 0; | 
|  | eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && | 
|  | m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); | 
|  | return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); | 
|  | } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const { | 
|  | Index row = XprType::RowsAtCompileTime == 1 ? 0 : index; | 
|  | Index col = XprType::RowsAtCompileTime == 1 ? index : 0; | 
|  | eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && | 
|  | m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); | 
|  | return m_argImpl.coeffRef(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); | 
|  | } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index index) const { | 
|  | Index row = XprType::RowsAtCompileTime == 1 ? 0 : index; | 
|  | Index col = XprType::RowsAtCompileTime == 1 ? index : 0; | 
|  | eigen_assert(m_xpr.rowIndices()[row] >= 0 && m_xpr.rowIndices()[row] < m_xpr.nestedExpression().rows() && | 
|  | m_xpr.colIndices()[col] >= 0 && m_xpr.colIndices()[col] < m_xpr.nestedExpression().cols()); | 
|  | return m_argImpl.coeff(m_xpr.rowIndices()[row], m_xpr.colIndices()[col]); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | evaluator<ArgType> m_argImpl; | 
|  | const XprType& m_xpr; | 
|  | }; | 
|  |  | 
|  | }  // end namespace internal | 
|  |  | 
|  | }  // end namespace Eigen | 
|  |  | 
|  | #endif  // EIGEN_INDEXED_VIEW_H |