| 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 | 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 | 
| 187 |  |