aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Core/util/IntegralConstant.h
blob: 945d426ea804c4788ff19a5c0507799f87edf381 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2017 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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_INTEGRAL_CONSTANT_H
#define EIGEN_INTEGRAL_CONSTANT_H

namespace Eigen {

namespace internal {

template<int N> class FixedInt;
template<int N> class VariableAndFixedInt;

/** \internal
  * \class FixedInt
  *
  * This class embeds a compile-time integer \c N.
  *
  * It is similar to c++11 std::integral_constant<int,N> but with some additional features
  * such as:
  *  - implicit conversion to int
  *  - arithmetic and some bitwise operators: -, +, *, /, %, &, |
  *  - c++98/14 compatibility with fix<N> and fix<N>() syntax to define integral constants.
  *
  * It is strongly discouraged to directly deal with this class FixedInt. Instances are expcected to
  * be created by the user using Eigen::fix<N> or Eigen::fix<N>(). In C++98-11, the former syntax does
  * not create a FixedInt<N> instance but rather a point to function that needs to be \em cleaned-up
  * using the generic helper:
  * \code
  * internal::cleanup_index_type<T>::type
  * internal::cleanup_index_type<T,DynamicKey>::type
  * \endcode
  * where T can a FixedInt<N>, a pointer to function FixedInt<N> (*)(), or numerous other integer-like representations.
  * \c DynamicKey is either Dynamic (default) or DynamicIndex and used to identify true compile-time values.
  *
  * For convenience, you can extract the compile-time value \c N in a generic way using the following helper:
  * \code
  * internal::get_fixed_value<T,DefaultVal>::value
  * \endcode
  * 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).
  *
  * \sa fix<N>, class VariableAndFixedInt
  */
template<int N> class FixedInt
{
public:
  static const int value = N;
  EIGEN_CONSTEXPR operator int() const { return value; }
  FixedInt() {}
  FixedInt( VariableAndFixedInt<N> other) {
    #ifndef EIGEN_INTERNAL_DEBUGGING
    EIGEN_UNUSED_VARIABLE(other);
    #endif
    eigen_internal_assert(int(other)==N);
  }

  FixedInt<-N> operator-() const { return FixedInt<-N>(); }
  template<int M>
  FixedInt<N+M> operator+( FixedInt<M>) const { return FixedInt<N+M>(); }
  template<int M>
  FixedInt<N-M> operator-( FixedInt<M>) const { return FixedInt<N-M>(); }
  template<int M>
  FixedInt<N*M> operator*( FixedInt<M>) const { return FixedInt<N*M>(); }
  template<int M>
  FixedInt<N/M> operator/( FixedInt<M>) const { return FixedInt<N/M>(); }
  template<int M>
  FixedInt<N%M> operator%( FixedInt<M>) const { return FixedInt<N%M>(); }
  template<int M>
  FixedInt<N|M> operator|( FixedInt<M>) const { return FixedInt<N|M>(); }
  template<int M>
  FixedInt<N&M> operator&( FixedInt<M>) const { return FixedInt<N&M>(); }

#if EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
  // Needed in C++14 to allow fix<N>():
  FixedInt operator() () const { return *this; }

  VariableAndFixedInt<N> operator() (int val) const { return VariableAndFixedInt<N>(val); }
#else
  FixedInt ( FixedInt<N> (*)() ) {}
#endif

#if EIGEN_HAS_CXX11
  FixedInt(std::integral_constant<int,N>) {}
#endif
};

/** \internal
  * \class VariableAndFixedInt
  *
  * This class embeds both a compile-time integer \c N and a runtime integer.
  * Both values are supposed to be equal unless the compile-time value \c N has a special
  * value meaning that the runtime-value should be used. Depending on the context, this special
  * value can be either Eigen::Dynamic (for positive quantities) or Eigen::DynamicIndex (for
  * quantities that can be negative).
  *
  * It is the return-type of the function Eigen::fix<N>(int), and most of the time this is the only
  * way it is used. It is strongly discouraged to directly deal with instances of VariableAndFixedInt.
  * Indeed, in order to write generic code, it is the responsibility of the callee to properly convert
  * it to either a true compile-time quantity (i.e. a FixedInt<N>), or to a runtime quantity (e.g., an Index)
  * using the following generic helper:
  * \code
  * internal::cleanup_index_type<T>::type
  * internal::cleanup_index_type<T,DynamicKey>::type
  * \endcode
  * where T can be a template instantiation of VariableAndFixedInt or numerous other integer-like representations.
  * \c DynamicKey is either Dynamic (default) or DynamicIndex and used to identify true compile-time values.
  *
  * For convenience, you can also extract the compile-time value \c N using the following helper:
  * \code
  * internal::get_fixed_value<T,DefaultVal>::value
  * \endcode
  * 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).
  *
  * \sa fix<N>(int), class FixedInt
  */
template<int N> class VariableAndFixedInt
{
public:
  static const int value = N;
  operator int() const { return m_value; }
  VariableAndFixedInt(int val) { m_value = val; }
protected:
  int m_value;
};

template<typename T, int Default=Dynamic> struct get_fixed_value {
  static const int value = Default;
};

template<int N,int Default> struct get_fixed_value<FixedInt<N>,Default> {
  static const int value = N;
};

#if !EIGEN_HAS_CXX14
template<int N,int Default> struct get_fixed_value<FixedInt<N> (*)(),Default> {
  static const int value = N;
};
#endif

template<int N,int Default> struct get_fixed_value<VariableAndFixedInt<N>,Default> {
  static const int value = N ;
};

template<typename T, int N, int Default>
struct get_fixed_value<variable_if_dynamic<T,N>,Default> {
  static const int value = N;
};

template<typename T> EIGEN_DEVICE_FUNC Index get_runtime_value(const T &x) { return x; }
#if !EIGEN_HAS_CXX14
template<int N> EIGEN_DEVICE_FUNC Index get_runtime_value(FixedInt<N> (*)()) { return N; }
#endif

// Cleanup integer/FixedInt/VariableAndFixedInt/etc types:

// By default, no cleanup:
template<typename T, int DynamicKey=Dynamic, typename EnableIf=void> struct cleanup_index_type { typedef T type; };

// Convert any integral type (e.g., short, int, unsigned int, etc.) to Eigen::Index
template<typename T, int DynamicKey> struct cleanup_index_type<T,DynamicKey,typename internal::enable_if<internal::is_integral<T>::value>::type> { typedef Index type; };

#if !EIGEN_HAS_CXX14
// In c++98/c++11, fix<N> is a pointer to function that we better cleanup to a true FixedInt<N>:
template<int N, int DynamicKey> struct cleanup_index_type<FixedInt<N> (*)(), DynamicKey> { typedef FixedInt<N> type; };
#endif

// If VariableAndFixedInt does not match DynamicKey, then we turn it to a pure compile-time value:
template<int N, int DynamicKey> struct cleanup_index_type<VariableAndFixedInt<N>, DynamicKey> { typedef FixedInt<N> type; };
// If VariableAndFixedInt matches DynamicKey, then we turn it to a pure runtime-value (aka Index):
template<int DynamicKey> struct cleanup_index_type<VariableAndFixedInt<DynamicKey>, DynamicKey> { typedef Index type; };

#if EIGEN_HAS_CXX11
template<int N, int DynamicKey> struct cleanup_index_type<std::integral_constant<int,N>, DynamicKey> { typedef FixedInt<N> type; };
#endif

} // end namespace internal

#ifndef EIGEN_PARSED_BY_DOXYGEN

#if EIGEN_HAS_CXX14_VARIABLE_TEMPLATES
template<int N>
static const internal::FixedInt<N> fix{};
#else
template<int N>
inline internal::FixedInt<N> fix() { return internal::FixedInt<N>(); }

// The generic typename T is mandatory. Otherwise, a code like fix<N> could refer to either the function above or this next overload.
// This way a code like fix<N> can only refer to the previous function.
template<int N,typename T>
inline internal::VariableAndFixedInt<N> fix(T val) { return internal::VariableAndFixedInt<N>(internal::convert_index<int>(val)); }
#endif

#else // EIGEN_PARSED_BY_DOXYGEN

/** \var fix<N>()
  * \ingroup Core_Module
  *
  * This \em identifier permits to construct an object embedding a compile-time integer \c N.
  *
  * \tparam N the compile-time integer value
  *
  * It is typically used in conjunction with the Eigen::seq and Eigen::seqN functions to pass compile-time values to them:
  * \code
  * seqN(10,fix<4>,fix<-3>)   // <=> [10 7 4 1]
  * \endcode
  *
  * See also the function fix(int) to pass both a compile-time and runtime value.
  *
  * In c++14, it is implemented as:
  * \code
  * template<int N> static const internal::FixedInt<N> fix{};
  * \endcode
  * where internal::FixedInt<N> is an internal template class similar to
  * <a href="http://en.cppreference.com/w/cpp/types/integral_constant">\c std::integral_constant </a><tt> <int,N> </tt>
  * Here, \c fix<N> is thus an object of type \c internal::FixedInt<N>.
  *
  * In c++98/11, it is implemented as a function:
  * \code
  * template<int N> inline internal::FixedInt<N> fix();
  * \endcode
  * Here internal::FixedInt<N> is thus a pointer to function.
  *
  * 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.
  *
  * \sa fix<N>(int), seq, seqN
  */
template<int N>
static const auto fix();

/** \fn fix<N>(int)
  * \ingroup Core_Module
  *
  * This function returns an object embedding both a compile-time integer \c N, and a fallback runtime value \a val.
  *
  * \tparam N the compile-time integer value
  * \param  val the fallback runtime integer value
  *
  * This function is a more general version of the \ref fix identifier/function that can be used in template code
  * where the compile-time value could turn out to actually mean "undefined at compile-time". For positive integers
  * such as a size or a dimension, this case is identified by Eigen::Dynamic, whereas runtime signed integers
  * (e.g., an increment/stride) are identified as Eigen::DynamicIndex. In such a case, the runtime value \a val
  * will be used as a fallback.
  *
  * A typical use case would be:
  * \code
  * template<typename Derived> void foo(const MatrixBase<Derived> &mat) {
  *   const int N = Derived::RowsAtCompileTime==Dynamic ? Dynamic : Derived::RowsAtCompileTime/2;
  *   const int n = mat.rows()/2;
  *   ... mat( seqN(0,fix<N>(n) ) ...;
  * }
  * \endcode
  * In this example, the function Eigen::seqN knows that the second argument is expected to be a size.
  * 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.
  * 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>.
  *
  * \sa fix, seqN, class ArithmeticSequence
  */
template<int N>
static const auto fix(int val);

#endif // EIGEN_PARSED_BY_DOXYGEN

} // end namespace Eigen

#endif // EIGEN_INTEGRAL_CONSTANT_H