Branch data Line data Source code
1 : : // This file is part of Eigen, a lightweight C++ template library 2 : : // for linear algebra. 3 : : // 4 : : // Copyright (C) 2017 Gael Guennebaud <gael.guennebaud@inria.fr> 5 : : // 6 : : // This Source Code Form is subject to the terms of the Mozilla 7 : : // Public License v. 2.0. If a copy of the MPL was not distributed 8 : : // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 : : 10 : : 11 : : #ifndef EIGEN_INDEXED_VIEW_HELPER_H 12 : : #define EIGEN_INDEXED_VIEW_HELPER_H 13 : : 14 : : namespace Eigen { 15 : : 16 : : namespace internal { 17 : : struct symbolic_last_tag {}; 18 : : } 19 : : 20 : : /** \var last 21 : : * \ingroup Core_Module 22 : : * 23 : : * Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically reference the last element/row/columns 24 : : * of the underlying vector or matrix once passed to DenseBase::operator()(const RowIndices&, const ColIndices&). 25 : : * 26 : : * This symbolic placeholder supports standard arithmetic operations. 27 : : * 28 : : * A typical usage example would be: 29 : : * \code 30 : : * using namespace Eigen; 31 : : * using Eigen::last; 32 : : * VectorXd v(n); 33 : : * v(seq(2,last-2)).setOnes(); 34 : : * \endcode 35 : : * 36 : : * \sa end 37 : : */ 38 : : static const symbolic::SymbolExpr<internal::symbolic_last_tag> last; // PLEASE use Eigen::last instead of Eigen::placeholders::last 39 : : 40 : : /** \var lastp1 41 : : * \ingroup Core_Module 42 : : * 43 : : * Can be used as a parameter to Eigen::seq and Eigen::seqN functions to symbolically 44 : : * reference the last+1 element/row/columns of the underlying vector or matrix once 45 : : * passed to DenseBase::operator()(const RowIndices&, const ColIndices&). 46 : : * 47 : : * This symbolic placeholder supports standard arithmetic operations. 48 : : * It is essentially an alias to last+fix<1>. 49 : : * 50 : : * \sa last 51 : : */ 52 : : #ifdef EIGEN_PARSED_BY_DOXYGEN 53 : : static const auto lastp1 = last+fix<1>; 54 : : #else 55 : : // Using a FixedExpr<1> expression is important here to make sure the compiler 56 : : // can fully optimize the computation starting indices with zero overhead. 57 : : static const symbolic::AddExpr<symbolic::SymbolExpr<internal::symbolic_last_tag>,symbolic::ValueExpr<Eigen::internal::FixedInt<1> > > lastp1(last+fix<1>()); 58 : : #endif 59 : : 60 : : namespace internal { 61 : : 62 : : // Replace symbolic last/end "keywords" by their true runtime value 63 : : inline Index eval_expr_given_size(Index x, Index /* size */) { return x; } 64 : : 65 : : template<int N> 66 : : FixedInt<N> eval_expr_given_size(FixedInt<N> x, Index /*size*/) { return x; } 67 : : 68 : : template<typename Derived> 69 : : Index eval_expr_given_size(const symbolic::BaseExpr<Derived> &x, Index size) 70 : : { 71 : : return x.derived().eval(last=size-1); 72 : : } 73 : : 74 : : // Extract increment/step at compile time 75 : : template<typename T, typename EnableIf = void> struct get_compile_time_incr { 76 : : enum { value = UndefinedIncr }; 77 : : }; 78 : : 79 : : // Analogue of std::get<0>(x), but tailored for our needs. 80 : : template<typename T> 81 : : EIGEN_CONSTEXPR Index first(const T& x) EIGEN_NOEXCEPT { return x.first(); } 82 : : 83 : : // IndexedViewCompatibleType/makeIndexedViewCompatible turn an arbitrary object of type T into something usable by MatrixSlice 84 : : // The generic implementation is a no-op 85 : : template<typename T,int XprSize,typename EnableIf=void> 86 : : struct IndexedViewCompatibleType { 87 : : typedef T type; 88 : : }; 89 : : 90 : : template<typename T,typename Q> 91 : : const T& makeIndexedViewCompatible(const T& x, Index /*size*/, Q) { return x; } 92 : : 93 : : //-------------------------------------------------------------------------------- 94 : : // Handling of a single Index 95 : : //-------------------------------------------------------------------------------- 96 : : 97 : : struct SingleRange { 98 : : enum { 99 : : SizeAtCompileTime = 1 100 : : }; 101 : : SingleRange(Index val) : m_value(val) {} 102 : : Index operator[](Index) const { return m_value; } 103 : : static EIGEN_CONSTEXPR Index size() EIGEN_NOEXCEPT { return 1; } 104 : : Index first() const EIGEN_NOEXCEPT { return m_value; } 105 : : Index m_value; 106 : : }; 107 : : 108 : : template<> struct get_compile_time_incr<SingleRange> { 109 : : enum { value = 1 }; // 1 or 0 ?? 110 : : }; 111 : : 112 : : // Turn a single index into something that looks like an array (i.e., that exposes a .size(), and operator[](int) methods) 113 : : template<typename T, int XprSize> 114 : : struct IndexedViewCompatibleType<T,XprSize,typename internal::enable_if<internal::is_integral<T>::value>::type> { 115 : : // Here we could simply use Array, but maybe it's less work for the compiler to use 116 : : // a simpler wrapper as SingleRange 117 : : //typedef Eigen::Array<Index,1,1> type; 118 : : typedef SingleRange type; 119 : : }; 120 : : 121 : : template<typename T, int XprSize> 122 : : struct IndexedViewCompatibleType<T, XprSize, typename enable_if<symbolic::is_symbolic<T>::value>::type> { 123 : : typedef SingleRange type; 124 : : }; 125 : : 126 : : 127 : : template<typename T> 128 : : typename enable_if<symbolic::is_symbolic<T>::value,SingleRange>::type 129 : : makeIndexedViewCompatible(const T& id, Index size, SpecializedType) { 130 : : return eval_expr_given_size(id,size); 131 : : } 132 : : 133 : : //-------------------------------------------------------------------------------- 134 : : // Handling of all 135 : : //-------------------------------------------------------------------------------- 136 : : 137 : 4 : struct all_t { all_t() {} }; 138 : : 139 : : // Convert a symbolic 'all' into a usable range type 140 : : template<int XprSize> 141 : : struct AllRange { 142 : : enum { SizeAtCompileTime = XprSize }; 143 : : AllRange(Index size = XprSize) : m_size(size) {} 144 : : EIGEN_CONSTEXPR Index operator[](Index i) const EIGEN_NOEXCEPT { return i; } 145 : : EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_size.value(); } 146 : : EIGEN_CONSTEXPR Index first() const EIGEN_NOEXCEPT { return 0; } 147 : : variable_if_dynamic<Index,XprSize> m_size; 148 : : }; 149 : : 150 : : template<int XprSize> 151 : : struct IndexedViewCompatibleType<all_t,XprSize> { 152 : : typedef AllRange<XprSize> type; 153 : : }; 154 : : 155 : : template<typename XprSizeType> 156 : : inline AllRange<get_fixed_value<XprSizeType>::value> makeIndexedViewCompatible(all_t , XprSizeType size, SpecializedType) { 157 : : return AllRange<get_fixed_value<XprSizeType>::value>(size); 158 : : } 159 : : 160 : : template<int Size> struct get_compile_time_incr<AllRange<Size> > { 161 : : enum { value = 1 }; 162 : : }; 163 : : 164 : : } // end namespace internal 165 : : 166 : : 167 : : /** \var all 168 : : * \ingroup Core_Module 169 : : * Can be used as a parameter to DenseBase::operator()(const RowIndices&, const ColIndices&) to index all rows or columns 170 : : */ 171 : : static const Eigen::internal::all_t all; // PLEASE use Eigen::all instead of Eigen::placeholders::all 172 : : 173 : : 174 : : namespace placeholders { 175 : : typedef symbolic::SymbolExpr<internal::symbolic_last_tag> last_t; 176 : : typedef symbolic::AddExpr<symbolic::SymbolExpr<internal::symbolic_last_tag>,symbolic::ValueExpr<Eigen::internal::FixedInt<1> > > end_t; 177 : : typedef Eigen::internal::all_t all_t; 178 : : 179 : : EIGEN_DEPRECATED static const all_t all = Eigen::all; // PLEASE use Eigen::all instead of Eigen::placeholders::all 180 : : EIGEN_DEPRECATED static const last_t last = Eigen::last; // PLEASE use Eigen::last instead of Eigen::placeholders::last 181 : : EIGEN_DEPRECATED static const end_t end = Eigen::lastp1; // PLEASE use Eigen::lastp1 instead of Eigen::placeholders::end 182 : : } 183 : : 184 : : } // end namespace Eigen 185 : : 186 : : #endif // EIGEN_INDEXED_VIEW_HELPER_H