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_INTEGRAL_CONSTANT_H
12 : : #define EIGEN_INTEGRAL_CONSTANT_H
13 : :
14 : : namespace Eigen {
15 : :
16 : : namespace internal {
17 : :
18 : : template<int N> class FixedInt;
19 : : template<int N> class VariableAndFixedInt;
20 : :
21 : : /** \internal
22 : : * \class FixedInt
23 : : *
24 : : * This class embeds a compile-time integer \c N.
25 : : *
26 : : * It is similar to c++11 std::integral_constant<int,N> but with some additional features
27 : : * such as:
28 : : * - implicit conversion to int
29 : : * - arithmetic and some bitwise operators: -, +, *, /, %, &, |
30 : : * - c++98/14 compatibility with fix<N> and fix<N>() syntax to define integral constants.
31 : : *
32 : : * It is strongly discouraged to directly deal with this class FixedInt. Instances are expcected to
33 : : * be created by the user using Eigen::fix<N> or Eigen::fix<N>(). In C++98-11, the former syntax does
34 : : * not create a FixedInt<N> instance but rather a point to function that needs to be \em cleaned-up
35 : : * using the generic helper:
36 : : * \code
37 : : * internal::cleanup_index_type<T>::type
38 : : * internal::cleanup_index_type<T,DynamicKey>::type
39 : : * \endcode
40 : : * where T can a FixedInt<N>, a pointer to function FixedInt<N> (*)(), or numerous other integer-like representations.
41 : : * \c DynamicKey is either Dynamic (default) or DynamicIndex and used to identify true compile-time values.
42 : : *
43 : : * For convenience, you can extract the compile-time value \c N in a generic way using the following helper:
44 : : * \code
45 : : * internal::get_fixed_value<T,DefaultVal>::value
46 : : * \endcode
47 : : * that will give you \c N if T equals FixedInt<N> or FixedInt<N> (*)(), and \c DefaultVal if T does not embed any compile-time value (e.g., T==int).
48 : : *
49 : : * \sa fix<N>, class VariableAndFixedInt
50 : : */
51 : : template<int N> class FixedInt
52 : : {
53 : : public:
54 : : static const int value = N;
55 : : EIGEN_CONSTEXPR operator int() const { return value; }
56 : 4 : FixedInt() {}
57 : : FixedInt( VariableAndFixedInt<N> other) {
58 : : #ifndef EIGEN_INTERNAL_DEBUGGING
59 : : EIGEN_UNUSED_VARIABLE(other);
60 : : #endif
61 : : eigen_internal_assert(int(other)==N);
62 : : }
63 : :
64 : : FixedInt<-N> operator-() const { return FixedInt<-N>(); }
65 : : template<int M>
66 : : FixedInt<N+M> operator+( FixedInt<M>) const { return FixedInt<N+M>(); }
67 : : template<int M>
68 : : FixedInt<N-M> operator-( FixedInt<M>) const { return FixedInt<N-M>(); }
69 : : template<int M>
70 : : FixedInt<N*M> operator*( FixedInt<M>) const { return FixedInt<N*M>(); }
71 : : template<int M>
72 : : FixedInt<N/M> operator/( FixedInt<M>) const { return FixedInt<N/M>(); }
73 : : template<int M>
74 : : FixedInt<N%M> operator%( FixedInt<M>) const { return FixedInt<N%M>(); }
75 : : template<int M>
76 : : FixedInt<N|M> operator|( FixedInt<M>) const { return FixedInt<N|M>(); }
77 : : template<int M>
78 : : FixedInt<N&M> operator&( FixedInt<M>) const { return FixedInt<N&M>(); }
79 : :
80 : : #if EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
81 : : // Needed in C++14 to allow fix<N>():
82 : 4 : FixedInt operator() () const { return *this; }
83 : :
84 : : VariableAndFixedInt<N> operator() (int val) const { return VariableAndFixedInt<N>(val); }
85 : : #else
86 : : FixedInt ( FixedInt<N> (*)() ) {}
87 : : #endif
88 : :
89 : : #if EIGEN_HAS_CXX11
90 : : FixedInt(std::integral_constant<int,N>) {}
91 : : #endif
92 : : };
93 : :
94 : : /** \internal
95 : : * \class VariableAndFixedInt
96 : : *
97 : : * This class embeds both a compile-time integer \c N and a runtime integer.
98 : : * Both values are supposed to be equal unless the compile-time value \c N has a special
99 : : * value meaning that the runtime-value should be used. Depending on the context, this special
100 : : * value can be either Eigen::Dynamic (for positive quantities) or Eigen::DynamicIndex (for
101 : : * quantities that can be negative).
102 : : *
103 : : * It is the return-type of the function Eigen::fix<N>(int), and most of the time this is the only
104 : : * way it is used. It is strongly discouraged to directly deal with instances of VariableAndFixedInt.
105 : : * Indeed, in order to write generic code, it is the responsibility of the callee to properly convert
106 : : * it to either a true compile-time quantity (i.e. a FixedInt<N>), or to a runtime quantity (e.g., an Index)
107 : : * using the following generic helper:
108 : : * \code
109 : : * internal::cleanup_index_type<T>::type
110 : : * internal::cleanup_index_type<T,DynamicKey>::type
111 : : * \endcode
112 : : * where T can be a template instantiation of VariableAndFixedInt or numerous other integer-like representations.
113 : : * \c DynamicKey is either Dynamic (default) or DynamicIndex and used to identify true compile-time values.
114 : : *
115 : : * For convenience, you can also extract the compile-time value \c N using the following helper:
116 : : * \code
117 : : * internal::get_fixed_value<T,DefaultVal>::value
118 : : * \endcode
119 : : * that will give you \c N if T equals VariableAndFixedInt<N>, and \c DefaultVal if T does not embed any compile-time value (e.g., T==int).
120 : : *
121 : : * \sa fix<N>(int), class FixedInt
122 : : */
123 : : template<int N> class VariableAndFixedInt
124 : : {
125 : : public:
126 : : static const int value = N;
127 : : operator int() const { return m_value; }
128 : : VariableAndFixedInt(int val) { m_value = val; }
129 : : protected:
130 : : int m_value;
131 : : };
132 : :
133 : : template<typename T, int Default=Dynamic> struct get_fixed_value {
134 : : static const int value = Default;
135 : : };
136 : :
137 : : template<int N,int Default> struct get_fixed_value<FixedInt<N>,Default> {
138 : : static const int value = N;
139 : : };
140 : :
141 : : #if !EIGEN_HAS_CXX14
142 : : template<int N,int Default> struct get_fixed_value<FixedInt<N> (*)(),Default> {
143 : : static const int value = N;
144 : : };
145 : : #endif
146 : :
147 : : template<int N,int Default> struct get_fixed_value<VariableAndFixedInt<N>,Default> {
148 : : static const int value = N ;
149 : : };
150 : :
151 : : template<typename T, int N, int Default>
152 : : struct get_fixed_value<variable_if_dynamic<T,N>,Default> {
153 : : static const int value = N;
154 : : };
155 : :
156 : 612 : template<typename T> EIGEN_DEVICE_FUNC Index get_runtime_value(const T &x) { return x; }
157 : : #if !EIGEN_HAS_CXX14
158 : : template<int N> EIGEN_DEVICE_FUNC Index get_runtime_value(FixedInt<N> (*)()) { return N; }
159 : : #endif
160 : :
161 : : // Cleanup integer/FixedInt/VariableAndFixedInt/etc types:
162 : :
163 : : // By default, no cleanup:
164 : : template<typename T, int DynamicKey=Dynamic, typename EnableIf=void> struct cleanup_index_type { typedef T type; };
165 : :
166 : : // Convert any integral type (e.g., short, int, unsigned int, etc.) to Eigen::Index
167 : : template<typename T, int DynamicKey> struct cleanup_index_type<T,DynamicKey,typename internal::enable_if<internal::is_integral<T>::value>::type> { typedef Index type; };
168 : :
169 : : #if !EIGEN_HAS_CXX14
170 : : // In c++98/c++11, fix<N> is a pointer to function that we better cleanup to a true FixedInt<N>:
171 : : template<int N, int DynamicKey> struct cleanup_index_type<FixedInt<N> (*)(), DynamicKey> { typedef FixedInt<N> type; };
172 : : #endif
173 : :
174 : : // If VariableAndFixedInt does not match DynamicKey, then we turn it to a pure compile-time value:
175 : : template<int N, int DynamicKey> struct cleanup_index_type<VariableAndFixedInt<N>, DynamicKey> { typedef FixedInt<N> type; };
176 : : // If VariableAndFixedInt matches DynamicKey, then we turn it to a pure runtime-value (aka Index):
177 : : template<int DynamicKey> struct cleanup_index_type<VariableAndFixedInt<DynamicKey>, DynamicKey> { typedef Index type; };
178 : :
179 : : #if EIGEN_HAS_CXX11
180 : : template<int N, int DynamicKey> struct cleanup_index_type<std::integral_constant<int,N>, DynamicKey> { typedef FixedInt<N> type; };
181 : : #endif
182 : :
183 : : } // end namespace internal
184 : :
185 : : #ifndef EIGEN_PARSED_BY_DOXYGEN
186 : :
187 : : #if EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
188 : : template<int N>
189 : : static const internal::FixedInt<N> fix{};
190 : : #else
191 : : template<int N>
192 : : inline internal::FixedInt<N> fix() { return internal::FixedInt<N>(); }
193 : :
194 : : // The generic typename T is mandatory. Otherwise, a code like fix<N> could refer to either the function above or this next overload.
195 : : // This way a code like fix<N> can only refer to the previous function.
196 : : template<int N,typename T>
197 : : inline internal::VariableAndFixedInt<N> fix(T val) { return internal::VariableAndFixedInt<N>(internal::convert_index<int>(val)); }
198 : : #endif
199 : :
200 : : #else // EIGEN_PARSED_BY_DOXYGEN
201 : :
202 : : /** \var fix<N>()
203 : : * \ingroup Core_Module
204 : : *
205 : : * This \em identifier permits to construct an object embedding a compile-time integer \c N.
206 : : *
207 : : * \tparam N the compile-time integer value
208 : : *
209 : : * It is typically used in conjunction with the Eigen::seq and Eigen::seqN functions to pass compile-time values to them:
210 : : * \code
211 : : * seqN(10,fix<4>,fix<-3>) // <=> [10 7 4 1]
212 : : * \endcode
213 : : *
214 : : * See also the function fix(int) to pass both a compile-time and runtime value.
215 : : *
216 : : * In c++14, it is implemented as:
217 : : * \code
218 : : * template<int N> static const internal::FixedInt<N> fix{};
219 : : * \endcode
220 : : * where internal::FixedInt<N> is an internal template class similar to
221 : : * <a href="http://en.cppreference.com/w/cpp/types/integral_constant">\c std::integral_constant </a><tt> <int,N> </tt>
222 : : * Here, \c fix<N> is thus an object of type \c internal::FixedInt<N>.
223 : : *
224 : : * In c++98/11, it is implemented as a function:
225 : : * \code
226 : : * template<int N> inline internal::FixedInt<N> fix();
227 : : * \endcode
228 : : * Here internal::FixedInt<N> is thus a pointer to function.
229 : : *
230 : : * If for some reason you want a true object in c++98 then you can write: \code fix<N>() \endcode which is also valid in c++14.
231 : : *
232 : : * \sa fix<N>(int), seq, seqN
233 : : */
234 : : template<int N>
235 : : static const auto fix();
236 : :
237 : : /** \fn fix<N>(int)
238 : : * \ingroup Core_Module
239 : : *
240 : : * This function returns an object embedding both a compile-time integer \c N, and a fallback runtime value \a val.
241 : : *
242 : : * \tparam N the compile-time integer value
243 : : * \param val the fallback runtime integer value
244 : : *
245 : : * This function is a more general version of the \ref fix identifier/function that can be used in template code
246 : : * where the compile-time value could turn out to actually mean "undefined at compile-time". For positive integers
247 : : * such as a size or a dimension, this case is identified by Eigen::Dynamic, whereas runtime signed integers
248 : : * (e.g., an increment/stride) are identified as Eigen::DynamicIndex. In such a case, the runtime value \a val
249 : : * will be used as a fallback.
250 : : *
251 : : * A typical use case would be:
252 : : * \code
253 : : * template<typename Derived> void foo(const MatrixBase<Derived> &mat) {
254 : : * const int N = Derived::RowsAtCompileTime==Dynamic ? Dynamic : Derived::RowsAtCompileTime/2;
255 : : * const int n = mat.rows()/2;
256 : : * ... mat( seqN(0,fix<N>(n) ) ...;
257 : : * }
258 : : * \endcode
259 : : * In this example, the function Eigen::seqN knows that the second argument is expected to be a size.
260 : : * If the passed compile-time value N equals Eigen::Dynamic, then the proxy object returned by fix will be dissmissed, and converted to an Eigen::Index of value \c n.
261 : : * Otherwise, the runtime-value \c n will be dissmissed, and the returned ArithmeticSequence will be of the exact same type as <tt> seqN(0,fix<N>) </tt>.
262 : : *
263 : : * \sa fix, seqN, class ArithmeticSequence
264 : : */
265 : : template<int N>
266 : : static const auto fix(int val);
267 : :
268 : : #endif // EIGEN_PARSED_BY_DOXYGEN
269 : :
270 : : } // end namespace Eigen
271 : :
272 : : #endif // EIGEN_INTEGRAL_CONSTANT_H
|