// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2017 Gael Guennebaud // // 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 {}; struct all_t {}; } // namespace internal namespace placeholders { typedef symbolic::SymbolExpr 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 constexpr const last_t last; typedef symbolic::AddExpr, symbolic::ValueExpr>> 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 constexpr 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 constexpr lastp1_t lastp1(last + fix<1>()); #endif /** \var end * \ingroup Core_Module * \sa lastp1 */ static constexpr 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 constexpr Eigen::internal::all_t all; } // namespace placeholders namespace internal { // Evaluate a symbolic expression or constant given the "size" of an object, allowing // any symbols like `last` to be evaluated. The default here assumes a dynamic constant. template struct SymbolicExpressionEvaluator { static constexpr Index ValueAtCompileTime = Undefined; static Index eval(const Expr& expr, Index /*size*/) { return static_cast(expr); } }; // Symbolic expression with size known at compile-time. template struct SymbolicExpressionEvaluator::value>> { static constexpr Index ValueAtCompileTime = Expr::Derived::eval_at_compile_time(Eigen::placeholders::last = fix); static Index eval(const Expr& expr, Index /*size*/) { return expr.eval(Eigen::placeholders::last = fix); } }; // Symbolic expression with dynamic size. template struct SymbolicExpressionEvaluator::value>> { static constexpr Index ValueAtCompileTime = Undefined; static Index eval(const Expr& expr, Index size) { return expr.eval(Eigen::placeholders::last = size - 1); } }; // Fixed int. template struct SymbolicExpressionEvaluator, SizeAtCompileTime, void> { static constexpr Index ValueAtCompileTime = static_cast(N); static Index eval(const FixedInt& /*expr*/, Index /*size*/) { return ValueAtCompileTime; } }; //-------------------------------------------------------------------------------- // Handling of generic indices (e.g. array) //-------------------------------------------------------------------------------- // Potentially wrap indices in a type that is better-suited for IndexedView evaluation. template struct IndexedViewHelperIndicesWrapper { using type = Indices; static const type& CreateIndexSequence(const Indices& indices, Index /*nested_size*/) { return indices; } }; // Extract compile-time and runtime first, size, increments. template struct IndexedViewHelper { static constexpr Index FirstAtCompileTime = Undefined; static constexpr Index SizeAtCompileTime = array_size::value; static constexpr Index IncrAtCompileTime = Undefined; static constexpr Index first(const Indices& indices) { return static_cast(indices[0]); } static constexpr Index size(const Indices& indices) { return index_list_size(indices); } static constexpr Index incr(const Indices& /*indices*/) { return Undefined; } }; //-------------------------------------------------------------------------------- // Handling of ArithmeticSequence //-------------------------------------------------------------------------------- template class ArithmeticSequenceRange { public: static constexpr Index FirstAtCompileTime = FirstAtCompileTime_; static constexpr Index SizeAtCompileTime = SizeAtCompileTime_; static constexpr Index IncrAtCompileTime = IncrAtCompileTime_; constexpr ArithmeticSequenceRange(Index first, Index size, Index incr) : first_{first}, size_{size}, incr_{incr} {} constexpr Index operator[](Index i) const { return first() + i * incr(); } constexpr Index first() const noexcept { return first_.value(); } constexpr Index size() const noexcept { return size_.value(); } constexpr Index incr() const noexcept { return incr_.value(); } private: variable_if_dynamicindex first_; variable_if_dynamic size_; variable_if_dynamicindex incr_; }; template struct IndexedViewHelperIndicesWrapper, NestedSizeAtCompileTime, void> { static constexpr Index EvalFirstAtCompileTime = SymbolicExpressionEvaluator::ValueAtCompileTime; static constexpr Index EvalSizeAtCompileTime = SymbolicExpressionEvaluator::ValueAtCompileTime; static constexpr Index EvalIncrAtCompileTime = SymbolicExpressionEvaluator::ValueAtCompileTime; static constexpr Index FirstAtCompileTime = (int(EvalFirstAtCompileTime) == Undefined) ? Index(DynamicIndex) : EvalFirstAtCompileTime; static constexpr Index SizeAtCompileTime = (int(EvalSizeAtCompileTime) == Undefined) ? Index(Dynamic) : EvalSizeAtCompileTime; static constexpr Index IncrAtCompileTime = (int(EvalIncrAtCompileTime) == Undefined) ? Index(DynamicIndex) : EvalIncrAtCompileTime; using Indices = ArithmeticSequence; using type = ArithmeticSequenceRange; static type CreateIndexSequence(const Indices& indices, Index nested_size) { Index first = SymbolicExpressionEvaluator::eval(indices.firstObject(), nested_size); Index size = SymbolicExpressionEvaluator::eval(indices.sizeObject(), nested_size); Index incr = SymbolicExpressionEvaluator::eval(indices.incrObject(), nested_size); return type(first, size, incr); } }; template struct IndexedViewHelper, void> { public: using Indices = ArithmeticSequenceRange; static constexpr Index FirstAtCompileTime = Indices::FirstAtCompileTime; static constexpr Index SizeAtCompileTime = Indices::SizeAtCompileTime; static constexpr Index IncrAtCompileTime = Indices::IncrAtCompileTime; static Index first(const Indices& indices) { return indices.first(); } static Index size(const Indices& indices) { return indices.size(); } static Index incr(const Indices& indices) { return indices.incr(); } }; //-------------------------------------------------------------------------------- // Handling of a single index. //-------------------------------------------------------------------------------- template class SingleRange { public: static constexpr Index FirstAtCompileTime = ValueAtCompileTime; static constexpr Index SizeAtCompileTime = Index(1); static constexpr Index IncrAtCompileTime = Index(1); // Needs to be 1 to be treated as block-like. constexpr SingleRange(Index v) noexcept : value_(v) {} constexpr Index operator[](Index) const noexcept { return first(); } constexpr Index first() const noexcept { return value_.value(); } constexpr Index size() const noexcept { return SizeAtCompileTime; } constexpr Index incr() const noexcept { return IncrAtCompileTime; } private: variable_if_dynamicindex value_; }; template struct is_single_range : public std::false_type {}; template struct is_single_range> : public std::true_type {}; template struct IndexedViewHelperIndicesWrapper< SingleIndex, NestedSizeAtCompileTime, std::enable_if_t::value || symbolic::is_symbolic::value>> { static constexpr Index EvalValueAtCompileTime = SymbolicExpressionEvaluator::ValueAtCompileTime; static constexpr Index ValueAtCompileTime = (int(EvalValueAtCompileTime) == Undefined) ? Index(DynamicIndex) : EvalValueAtCompileTime; using type = SingleRange; static type CreateIndexSequence(const SingleIndex& index, Index nested_size) { return type(SymbolicExpressionEvaluator::eval(index, nested_size)); } }; template struct IndexedViewHelperIndicesWrapper, NestedSizeAtCompileTime, void> { using type = SingleRange; static type CreateIndexSequence(const FixedInt& /*index*/) { return type(Index(N)); } }; template struct IndexedViewHelper, void> { using Indices = SingleRange; static constexpr Index FirstAtCompileTime = Indices::FirstAtCompileTime; static constexpr Index SizeAtCompileTime = Indices::SizeAtCompileTime; static constexpr Index IncrAtCompileTime = Indices::IncrAtCompileTime; static constexpr Index first(const Indices& indices) { return indices.first(); } static constexpr Index size(const Indices& /*indices*/) { return SizeAtCompileTime; } static constexpr Index incr(const Indices& /*indices*/) { return IncrAtCompileTime; } }; //-------------------------------------------------------------------------------- // Handling of all //-------------------------------------------------------------------------------- // Convert a symbolic 'all' into a usable range type template class AllRange { public: static constexpr Index FirstAtCompileTime = Index(0); static constexpr Index SizeAtCompileTime = SizeAtCompileTime_; static constexpr Index IncrAtCompileTime = Index(1); constexpr AllRange(Index size) : size_(size) {} constexpr Index operator[](Index i) const noexcept { return i; } constexpr Index first() const noexcept { return FirstAtCompileTime; } constexpr Index size() const noexcept { return size_.value(); } constexpr Index incr() const noexcept { return IncrAtCompileTime; } private: variable_if_dynamic size_; }; template struct IndexedViewHelperIndicesWrapper { using type = AllRange; static type CreateIndexSequence(const all_t& /*indices*/, Index nested_size) { return type(nested_size); } }; template struct IndexedViewHelper, void> { using Indices = AllRange; static constexpr Index FirstAtCompileTime = Indices::FirstAtCompileTime; static constexpr Index SizeAtCompileTime = Indices::SizeAtCompileTime; static constexpr Index IncrAtCompileTime = Indices::IncrAtCompileTime; static Index first(const Indices& indices) { return indices.first(); } static Index size(const Indices& indices) { return indices.size(); } static Index incr(const Indices& indices) { return indices.incr(); } }; } // end namespace internal } // end namespace Eigen #endif // EIGEN_INDEXED_VIEW_HELPER_H