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
eval_expr_given_size(Index x,Index)63 inline Index eval_expr_given_size(Index x, Index /* size */)   { return x; }
64 
65 template<int N>
eval_expr_given_size(FixedInt<N> x,Index)66 FixedInt<N> eval_expr_given_size(FixedInt<N> x, Index /*size*/)   { return x; }
67 
68 template<typename Derived>
eval_expr_given_size(const symbolic::BaseExpr<Derived> & x,Index size)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>
first(const T & x)81 Index first(const T& x) { 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>
makeIndexedViewCompatible(const T & x,Index,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   };
SingleRangeSingleRange101   SingleRange(Index val) : m_value(val) {}
102   Index operator[](Index) const { return m_value; }
sizeSingleRange103   Index size() const { return 1; }
firstSingleRange104   Index first() const { 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   Index operator[](Index i) const { return i; }
145   Index size() const { return m_size.value(); }
146   Index first() const { 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