xref: /aosp_15_r20/external/eigen/Eigen/src/Core/util/IntegralConstant.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2017 Gael Guennebaud <[email protected]>
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; }
FixedInt()56   FixedInt() {}
FixedInt(VariableAndFixedInt<N> other)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>():
operator()82   FixedInt operator() () const { return *this; }
83 
operator()84   VariableAndFixedInt<N> operator() (int val) const { return VariableAndFixedInt<N>(val); }
85 #else
FixedInt(FixedInt<N> (*)())86   FixedInt ( FixedInt<N> (*)() ) {}
87 #endif
88 
89 #if EIGEN_HAS_CXX11
FixedInt(std::integral_constant<int,N>)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; }
VariableAndFixedInt(int val)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 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
273