| // 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_HELPER_H |
| #define EIGEN_INDEXED_VIEW_HELPER_H |
| |
| // IWYU pragma: private |
| #include "../InternalHeaderCheck.h" |
| |
| namespace Eigen { |
| |
| namespace internal { |
| struct symbolic_last_tag {}; |
| } // namespace internal |
| |
| namespace placeholders { |
| |
| typedef symbolic::SymbolExpr<internal::symbolic_last_tag> last_t; |
| |
| /** \var last |
| * \ingroup Core_Module |
| * |
| * Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last |
| * element/row/columns of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const |
| * ColIndices&). |
| * |
| * This symbolic placeholder supports standard arithmetic operations. |
| * |
| * A typical usage example would be: |
| * \code |
| * using namespace Eigen; |
| * using Eigen::placeholders::last; |
| * VectorXd v(n); |
| * v(seq(2,last-2)).setOnes(); |
| * \endcode |
| * |
| * \sa end |
| */ |
| static const last_t last; |
| |
| } // namespace placeholders |
| |
| namespace internal { |
| |
| // Replace symbolic last/end "keywords" by their true runtime value |
| inline Index eval_expr_given_size(Index x, Index /* size */) { return x; } |
| |
| template <int N> |
| FixedInt<N> eval_expr_given_size(FixedInt<N> x, Index /*size*/) { |
| return x; |
| } |
| |
| template <typename Derived> |
| Index eval_expr_given_size(const symbolic::BaseExpr<Derived>& x, Index size) { |
| return x.derived().eval(Eigen::placeholders::last = size - 1); |
| } |
| |
| // Extract increment/step at compile time |
| template <typename T, typename EnableIf = void> |
| struct get_compile_time_incr { |
| enum { value = UndefinedIncr }; |
| }; |
| |
| // Analogue of std::get<0>(x), but tailored for our needs. |
| template <typename T> |
| EIGEN_CONSTEXPR Index first(const T& x) EIGEN_NOEXCEPT { |
| return x.first(); |
| } |
| |
| // IndexedViewCompatibleType/makeIndexedViewCompatible turn an arbitrary object of type T into something usable by |
| // MatrixSlice The generic implementation is a no-op |
| template <typename T, int XprSize, typename EnableIf = void> |
| struct IndexedViewCompatibleType { |
| typedef T type; |
| }; |
| |
| template <typename T, typename Q> |
| const T& makeIndexedViewCompatible(const T& x, Index /*size*/, Q) { |
| return x; |
| } |
| |
| //-------------------------------------------------------------------------------- |
| // Handling of a single Index |
| //-------------------------------------------------------------------------------- |
| |
| struct SingleRange { |
| enum { SizeAtCompileTime = 1 }; |
| SingleRange(Index val) : m_value(val) {} |
| Index operator[](Index) const { return m_value; } |
| static EIGEN_CONSTEXPR Index size() EIGEN_NOEXCEPT { return 1; } |
| Index first() const EIGEN_NOEXCEPT { return m_value; } |
| Index m_value; |
| }; |
| |
| template <> |
| struct get_compile_time_incr<SingleRange> { |
| enum { value = 1 }; // 1 or 0 ?? |
| }; |
| |
| // Turn a single index into something that looks like an array (i.e., that exposes a .size(), and operator[](int) |
| // methods) |
| template <typename T, int XprSize> |
| struct IndexedViewCompatibleType<T, XprSize, std::enable_if_t<internal::is_integral<T>::value>> { |
| // Here we could simply use Array, but maybe it's less work for the compiler to use |
| // a simpler wrapper as SingleRange |
| // typedef Eigen::Array<Index,1,1> type; |
| typedef SingleRange type; |
| }; |
| |
| template <typename T, int XprSize> |
| struct IndexedViewCompatibleType<T, XprSize, std::enable_if_t<symbolic::is_symbolic<T>::value>> { |
| typedef SingleRange type; |
| }; |
| |
| template <typename T> |
| std::enable_if_t<symbolic::is_symbolic<T>::value, SingleRange> makeIndexedViewCompatible(const T& id, Index size, |
| SpecializedType) { |
| return eval_expr_given_size(id, size); |
| } |
| |
| //-------------------------------------------------------------------------------- |
| // Handling of all |
| //-------------------------------------------------------------------------------- |
| |
| struct all_t { |
| all_t() {} |
| }; |
| |
| // Convert a symbolic 'all' into a usable range type |
| template <int XprSize> |
| struct AllRange { |
| enum { SizeAtCompileTime = XprSize }; |
| AllRange(Index size = XprSize) : m_size(size) {} |
| EIGEN_CONSTEXPR Index operator[](Index i) const EIGEN_NOEXCEPT { return i; } |
| EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_size.value(); } |
| EIGEN_CONSTEXPR Index first() const EIGEN_NOEXCEPT { return 0; } |
| variable_if_dynamic<Index, XprSize> m_size; |
| }; |
| |
| template <int XprSize> |
| struct IndexedViewCompatibleType<all_t, XprSize> { |
| typedef AllRange<XprSize> type; |
| }; |
| |
| template <typename XprSizeType> |
| inline AllRange<get_fixed_value<XprSizeType>::value> makeIndexedViewCompatible(all_t, XprSizeType size, |
| SpecializedType) { |
| return AllRange<get_fixed_value<XprSizeType>::value>(size); |
| } |
| |
| template <int Size> |
| struct get_compile_time_incr<AllRange<Size>> { |
| enum { value = 1 }; |
| }; |
| |
| } // end namespace internal |
| |
| namespace placeholders { |
| |
| typedef symbolic::AddExpr<symbolic::SymbolExpr<internal::symbolic_last_tag>, |
| symbolic::ValueExpr<Eigen::internal::FixedInt<1>>> |
| lastp1_t; |
| typedef Eigen::internal::all_t all_t; |
| |
| /** \var lastp1 |
| * \ingroup Core_Module |
| * |
| * Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically |
| * reference the last+1 element/row/columns of the underlying vector or matrix once |
| * passed to DenseBase::operator()(const RowIndices&, const ColIndices&). |
| * |
| * This symbolic placeholder supports standard arithmetic operations. |
| * It is essentially an alias to last+fix<1>. |
| * |
| * \sa last |
| */ |
| #ifdef EIGEN_PARSED_BY_DOXYGEN |
| static const auto lastp1 = last + fix<1>; |
| #else |
| // Using a FixedExpr<1> expression is important here to make sure the compiler |
| // can fully optimize the computation starting indices with zero overhead. |
| static const lastp1_t lastp1(last + fix<1>()); |
| #endif |
| |
| /** \var end |
| * \ingroup Core_Module |
| * \sa lastp1 |
| */ |
| static const lastp1_t end = lastp1; |
| |
| /** \var all |
| * \ingroup Core_Module |
| * Can be used as a parameter to DenseBase::operator()(const RowIndices&, const ColIndices&) to index all rows or |
| * columns |
| */ |
| static const Eigen::internal::all_t all; |
| |
| } // namespace placeholders |
| |
| } // end namespace Eigen |
| |
| #endif // EIGEN_INDEXED_VIEW_HELPER_H |