Meta.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr>
5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #ifndef EIGEN_META_H
12 #define EIGEN_META_H
13 
14 #include "../InternalHeaderCheck.h"
15 
16 #if defined(EIGEN_GPU_COMPILE_PHASE)
17 
18  #include <cfloat>
19 
20  #if defined(EIGEN_CUDA_ARCH)
21  #include <math_constants.h>
22  #endif
23 
24  #if defined(EIGEN_HIP_DEVICE_COMPILE)
26  #endif
27 
28 #endif
29 
30 // Define portable (u)int{32,64} types
31 #include <cstdint>
32 
33 namespace Eigen {
34 namespace numext {
43 
44 template <size_t Size>
46  typedef void signed_type;
47  typedef void unsigned_type;
48 };
49 template <>
53 };
54 template <>
58 };
59 template <>
63 };
64 template <>
68 };
69 }
70 }
71 
72 namespace Eigen {
73 
75 
83 
84 namespace internal {
85 
93 struct true_type { enum { value = 1 }; };
94 struct false_type { enum { value = 0 }; };
95 
96 template<bool Condition>
97 struct bool_constant;
98 
99 template<>
100 struct bool_constant<true> : true_type {};
101 
102 template<>
103 struct bool_constant<false> : false_type {};
104 
105 // Third-party libraries rely on these.
106 using std::conditional;
107 using std::remove_reference;
108 using std::remove_pointer;
109 using std::remove_const;
110 
111 template<typename T> struct remove_all { typedef T type; };
112 template<typename T> struct remove_all<const T> { typedef typename remove_all<T>::type type; };
113 template<typename T> struct remove_all<T const&> { typedef typename remove_all<T>::type type; };
114 template<typename T> struct remove_all<T&> { typedef typename remove_all<T>::type type; };
115 template<typename T> struct remove_all<T const*> { typedef typename remove_all<T>::type type; };
116 template<typename T> struct remove_all<T*> { typedef typename remove_all<T>::type type; };
117 
118 template<typename T>
120 
121 template<typename T> struct is_arithmetic { enum { value = false }; };
122 template<> struct is_arithmetic<float> { enum { value = true }; };
123 template<> struct is_arithmetic<double> { enum { value = true }; };
124 // GPU devices treat `long double` as `double`.
125 #ifndef EIGEN_GPU_COMPILE_PHASE
126 template<> struct is_arithmetic<long double> { enum { value = true }; };
127 #endif
128 template<> struct is_arithmetic<bool> { enum { value = true }; };
129 template<> struct is_arithmetic<char> { enum { value = true }; };
130 template<> struct is_arithmetic<signed char> { enum { value = true }; };
131 template<> struct is_arithmetic<unsigned char> { enum { value = true }; };
132 template<> struct is_arithmetic<signed short> { enum { value = true }; };
133 template<> struct is_arithmetic<unsigned short>{ enum { value = true }; };
134 template<> struct is_arithmetic<signed int> { enum { value = true }; };
135 template<> struct is_arithmetic<unsigned int> { enum { value = true }; };
136 template<> struct is_arithmetic<signed long> { enum { value = true }; };
137 template<> struct is_arithmetic<unsigned long> { enum { value = true }; };
138 
139 template<typename T, typename U> struct is_same { enum { value = 0 }; };
140 template<typename T> struct is_same<T,T> { enum { value = 1 }; };
141 
142 template< class T >
143 struct is_void : is_same<void, std::remove_const_t<T>> {};
144 
153 #if EIGEN_COMP_CXXVER >= 17
154 using std::void_t;
155 #else
156 template<typename...>
157 using void_t = void;
158 #endif
159 
160 template<> struct is_arithmetic<signed long long> { enum { value = true }; };
161 template<> struct is_arithmetic<unsigned long long> { enum { value = true }; };
162 using std::is_integral;
163 
164 using std::make_unsigned;
165 
166 template <typename T> struct is_const { enum { value = 0 }; };
167 template <typename T> struct is_const<T const> { enum { value = 1 }; };
168 
169 template<typename T> struct add_const_on_value_type { typedef const T type; };
170 template<typename T> struct add_const_on_value_type<T&> { typedef T const& type; };
171 template<typename T> struct add_const_on_value_type<T*> { typedef T const* type; };
172 template<typename T> struct add_const_on_value_type<T* const> { typedef T const* const type; };
173 template<typename T> struct add_const_on_value_type<T const* const> { typedef T const* const type; };
174 
175 template<typename T>
177 
178 using std::is_convertible;
179 
183 class noncopyable
184 {
185  EIGEN_DEVICE_FUNC noncopyable(const noncopyable&);
186  EIGEN_DEVICE_FUNC const noncopyable& operator=(const noncopyable&);
187 protected:
188  EIGEN_DEVICE_FUNC noncopyable() {}
189  EIGEN_DEVICE_FUNC ~noncopyable() {}
190 };
191 
206 template<typename T, typename EnableIf = void> struct array_size {
207  enum { value = Dynamic };
208 };
209 
210 template<typename T> struct array_size<T, std::enable_if_t<((T::SizeAtCompileTime&0)==0)>> {
211  enum { value = T::SizeAtCompileTime };
212 };
213 
214 template<typename T, int N> struct array_size<const T (&)[N]> {
215  enum { value = N };
216 };
217 template<typename T, int N> struct array_size<T (&)[N]> {
218  enum { value = N };
219 };
220 
221 template<typename T, std::size_t N> struct array_size<const std::array<T,N> > {
222  enum { value = N };
223 };
224 template<typename T, std::size_t N> struct array_size<std::array<T,N> > {
225  enum { value = N };
226 };
227 
228 
239 #if EIGEN_COMP_CXXVER < 20 || EIGEN_GNUC_STRICT_LESS_THAN(10,0,0)
240 template <typename T>
242  using R = std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(x.size())>>;
243  return static_cast<R>(x.size());
244 }
245 
246 template<typename T, std::ptrdiff_t N>
247 EIGEN_CONSTEXPR std::ptrdiff_t index_list_size(const T (&)[N]) { return N; }
248 #else
249 template <typename T>
251  using std::ssize;
252  return ssize(std::forward<T>(x));
253 }
254 #endif // EIGEN_COMP_CXXVER
255 
266 #if EIGEN_HAS_STD_INVOKE_RESULT
267 template<typename T> struct result_of;
268 
269 template<typename F, typename... ArgTypes>
270 struct result_of<F(ArgTypes...)> {
271  typedef typename std::invoke_result<F, ArgTypes...>::type type1;
272  typedef remove_all_t<type1> type;
273 };
274 
275 template<typename F, typename... ArgTypes>
276 struct invoke_result {
277  typedef typename std::invoke_result<F, ArgTypes...>::type type1;
278  typedef remove_all_t<type1> type;
279 };
280 #else
281 template<typename T> struct result_of {
282  typedef typename std::result_of<T>::type type1;
283  typedef remove_all_t<type1> type;
284 };
285 
286 template<typename F, typename... ArgTypes>
287 struct invoke_result {
288  typedef typename result_of<F(ArgTypes...)>::type type1;
289  typedef remove_all_t<type1> type;
290 };
291 #endif
292 
293 // Reduces a sequence of bools to true if all are true, false otherwise.
294 template<bool... values>
295 using reduce_all = std::is_same<std::integer_sequence<bool, values..., true>,
296  std::integer_sequence<bool, true, values...> >;
297 
298 // Reduces a sequence of bools to true if any are true, false if all false.
299 template<bool... values>
300 using reduce_any = std::integral_constant<bool,
301  !std::is_same<std::integer_sequence<bool, values..., false>, std::integer_sequence<bool, false, values...> >::value>;
302 
303 struct meta_yes { char a[1]; };
304 struct meta_no { char a[2]; };
305 
306 // Check whether T::ReturnType does exist
307 template <typename T>
308 struct has_ReturnType
309 {
310  template <typename C> static meta_yes testFunctor(C const *, typename C::ReturnType const * = 0);
311  template <typename C> static meta_no testFunctor(...);
312 
313  enum { value = sizeof(testFunctor<T>(static_cast<T*>(0))) == sizeof(meta_yes) };
314 };
315 
316 template<typename T> const T* return_ptr();
317 
318 template <typename T, typename IndexType=Index>
319 struct has_nullary_operator
320 {
321  template <typename C> static meta_yes testFunctor(C const *,std::enable_if_t<(sizeof(return_ptr<C>()->operator()())>0)> * = 0);
322  static meta_no testFunctor(...);
323 
324  enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
325 };
326 
327 template <typename T, typename IndexType=Index>
328 struct has_unary_operator
329 {
330  template <typename C> static meta_yes testFunctor(C const *,std::enable_if_t<(sizeof(return_ptr<C>()->operator()(IndexType(0)))>0)> * = 0);
331  static meta_no testFunctor(...);
332 
333  enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
334 };
335 
336 template <typename T, typename IndexType=Index>
337 struct has_binary_operator
338 {
339  template <typename C> static meta_yes testFunctor(C const *,std::enable_if_t<(sizeof(return_ptr<C>()->operator()(IndexType(0),IndexType(0)))>0)> * = 0);
340  static meta_no testFunctor(...);
341 
342  enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
343 };
344 
348 template<int Y,
349  int InfX = 0,
350  int SupX = ((Y==1) ? 1 : Y/2),
351  bool Done = ((SupX - InfX) <= 1 || ((SupX * SupX <= Y) && ((SupX + 1) * (SupX + 1) > Y)))>
352 class meta_sqrt
353 {
354  enum {
355  MidX = (InfX+SupX)/2,
356  TakeInf = MidX*MidX > Y ? 1 : 0,
357  NewInf = int(TakeInf) ? InfX : int(MidX),
358  NewSup = int(TakeInf) ? int(MidX) : SupX
359  };
360  public:
361  enum { ret = meta_sqrt<Y,NewInf,NewSup>::ret };
362 };
363 
364 template<int Y, int InfX, int SupX>
365 class meta_sqrt<Y, InfX, SupX, true> { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
366 
367 
371 template<int A, int B, int K=1, bool Done = ((A*K)%B)==0, bool Big=(A>=B)>
372 struct meta_least_common_multiple
373 {
374  enum { ret = meta_least_common_multiple<A,B,K+1>::ret };
375 };
376 template<int A, int B, int K, bool Done>
377 struct meta_least_common_multiple<A,B,K,Done,false>
378 {
379  enum { ret = meta_least_common_multiple<B,A,K>::ret };
380 };
381 template<int A, int B, int K>
382 struct meta_least_common_multiple<A,B,K,true,true>
383 {
384  enum { ret = A*K };
385 };
386 
387 
389 template<typename T, typename U> struct scalar_product_traits
390 {
391  enum { Defined = 0 };
392 };
393 
394 // FIXME quick workaround around current limitation of result_of
395 // template<typename Scalar, typename ArgType0, typename ArgType1>
396 // struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
397 // typedef typename scalar_product_traits<remove_all_t<ArgType0>, remove_all_t<ArgType1>>::ReturnType type;
398 // };
399 
403 template<unsigned Len, unsigned Align>
404 struct aligned_storage {
405  struct type {
406  EIGEN_ALIGN_TO_BOUNDARY(Align) unsigned char data[Len];
407  };
408 };
409 
410 } // end namespace internal
411 
412 template<typename T> struct NumTraits;
413 
414 namespace numext {
415 
416 #if defined(EIGEN_GPU_COMPILE_PHASE)
417 template<typename T> EIGEN_DEVICE_FUNC void swap(T &a, T &b) { T tmp = b; b = a; a = tmp; }
418 #else
419 template<typename T> EIGEN_STRONG_INLINE void swap(T &a, T &b) { std::swap(a,b); }
420 #endif
421 
422 using std::numeric_limits;
423 
424 // Integer division with rounding up.
425 // T is assumed to be an integer type with a>=0, and b>0
426 template<typename T>
428 T div_ceil(const T &a, const T &b)
429 {
430  return (a+b-1) / b;
431 }
432 
433 // Handle integer comparisons of different signedness.
434 template <typename X, typename Y, bool XIsInteger = NumTraits<X>::IsInteger, bool XIsSigned = NumTraits<X>::IsSigned,
435  bool YIsInteger = NumTraits<Y>::IsInteger, bool YIsSigned = NumTraits<Y>::IsSigned>
437  static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) { return x == y; }
438 };
439 template <typename X, typename Y>
440 struct equal_strict_impl<X, Y, true, false, true, true> {
441  // X is an unsigned integer
442  // Y is a signed integer
443  // if Y is non-negative, it may be represented exactly as its unsigned counterpart.
444  using UnsignedY = typename internal::make_unsigned<Y>::type;
445  static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
446  return y < Y(0) ? false : (x == static_cast<UnsignedY>(y));
447  }
448 };
449 template <typename X, typename Y>
450 struct equal_strict_impl<X, Y, true, true, true, false> {
451  // X is a signed integer
452  // Y is an unsigned integer
453  static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
455  }
456 };
457 
458 // The aim of the following functions is to bypass -Wfloat-equal warnings
459 // when we really want a strict equality comparison on floating points.
460 template<typename X, typename Y> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const X& x, const Y& y) { return equal_strict_impl<X, Y>::run(x, y); }
461 
462 #if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
463 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
464 bool equal_strict(const float& x,const float& y) { return std::equal_to<float>()(x,y); }
465 
466 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
467 bool equal_strict(const double& x,const double& y) { return std::equal_to<double>()(x,y); }
468 #endif
469 
474 template<typename X> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
475 bool is_exactly_zero(const X& x) { return equal_strict(x, typename NumTraits<X>::Literal{0}); }
476 
481 template<typename X> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
482 bool is_exactly_one(const X& x) { return equal_strict(x, typename NumTraits<X>::Literal{1}); }
483 
484 template<typename X, typename Y> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
485 bool not_equal_strict(const X& x,const Y& y) { return !equal_strict_impl<X, Y>::run(x, y); }
486 
487 #if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
488 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
489 bool not_equal_strict(const float& x,const float& y) { return std::not_equal_to<float>()(x,y); }
490 
491 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
492 bool not_equal_strict(const double& x,const double& y) { return std::not_equal_to<double>()(x,y); }
493 #endif
494 
495 } // end namespace numext
496 
497 namespace internal {
498 
499 template<typename Scalar>
500 struct is_identically_zero_impl {
501  static inline bool run(const Scalar& s) {
502  return numext::is_exactly_zero(s);
503  }
504 };
505 
506 template<typename Scalar> EIGEN_STRONG_INLINE
507 bool is_identically_zero(const Scalar& s) { return is_identically_zero_impl<Scalar>::run(s); }
508 
511 template<typename A>
512 constexpr bool is_int_or_enum_v = std::is_enum<A>::value || std::is_integral<A>::value;
513 
515 template<typename A, typename B>
516 inline constexpr int plain_enum_min(A a, B b) {
517  static_assert(is_int_or_enum_v<A>, "Argument a must be an integer or enum");
518  static_assert(is_int_or_enum_v<B>, "Argument b must be an integer or enum");
519  return ((int) a <= (int) b) ? (int) a : (int) b;
520 }
521 
523 template<typename A, typename B>
524 inline constexpr int plain_enum_max(A a, B b) {
525  static_assert(is_int_or_enum_v<A>, "Argument a must be an integer or enum");
526  static_assert(is_int_or_enum_v<B>, "Argument b must be an integer or enum");
527  return ((int) a >= (int) b) ? (int) a : (int) b;
528 }
529 
536 template<typename A, typename B>
537 inline constexpr int min_size_prefer_dynamic(A a, B b) {
538  static_assert(is_int_or_enum_v<A>, "Argument a must be an integer or enum");
539  static_assert(is_int_or_enum_v<B>, "Argument b must be an integer or enum");
540  if ((int) a == 0 || (int) b == 0) return 0;
541  if ((int) a == 1 || (int) b == 1) return 1;
542  if ((int) a == Dynamic || (int) b == Dynamic) return Dynamic;
543  return plain_enum_min(a, b);
544 }
545 
552 template<typename A, typename B>
553 inline constexpr int min_size_prefer_fixed(A a, B b) {
554  static_assert(is_int_or_enum_v<A>, "Argument a must be an integer or enum");
555  static_assert(is_int_or_enum_v<B>, "Argument b must be an integer or enum");
556  if ((int) a == 0 || (int) b == 0) return 0;
557  if ((int) a == 1 || (int) b == 1) return 1;
558  if ((int) a == Dynamic && (int) b == Dynamic) return Dynamic;
559  if ((int) a == Dynamic) return (int) b;
560  if ((int) b == Dynamic) return (int) a;
561  return plain_enum_min(a, b);
562 }
563 
565 template<typename A, typename B>
566 inline constexpr int max_size_prefer_dynamic(A a, B b) {
567  static_assert(is_int_or_enum_v<A>, "Argument a must be an integer or enum");
568  static_assert(is_int_or_enum_v<B>, "Argument b must be an integer or enum");
569  if ((int) a == Dynamic || (int) b == Dynamic) return Dynamic;
570  return plain_enum_max(a, b);
571 }
572 
574 inline constexpr bool logical_xor(bool a, bool b) {
575  return a != b;
576 }
577 
579 inline constexpr bool check_implication(bool a, bool b) {
580  return !a || b;
581 }
582 
584 #if EIGEN_COMP_CXXVER >= 20
586 #else
587 constexpr bool is_constant_evaluated() { return false; }
588 #endif
589 
590 } // end namespace internal
591 
592 } // end namespace Eigen
593 
594 #endif // EIGEN_META_H
Array< int, 3, 1 > b
MatrixXcf A
#define EIGEN_ALIGN_TO_BOUNDARY(n)
MatrixXf B
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE
Definition: Macros.h:34
#define EIGEN_CONSTEXPR
Definition: Macros.h:747
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:883
int data[]
Eigen::Triplet< double > T
constexpr int plain_enum_min(A a, B b)
Definition: Meta.h:516
constexpr int plain_enum_max(A a, B b)
Definition: Meta.h:524
const Scalar & y
std::integral_constant< bool, !std::is_same< std::integer_sequence< bool, values..., false >, std::integer_sequence< bool, false, values... > >::value > reduce_any
Definition: Meta.h:301
constexpr bool is_int_or_enum_v
Definition: Meta.h:512
constexpr bool check_implication(bool a, bool b)
Definition: Meta.h:579
constexpr int min_size_prefer_fixed(A a, B b)
Definition: Meta.h:553
void void_t
Definition: Meta.h:157
bool is_identically_zero(const Scalar &s)
Definition: Meta.h:507
constexpr bool logical_xor(bool a, bool b)
Definition: Meta.h:574
std::is_same< std::integer_sequence< bool, values..., true >, std::integer_sequence< bool, true, values... > > reduce_all
Definition: Meta.h:296
typename remove_all< T >::type remove_all_t
Definition: Meta.h:119
EIGEN_CONSTEXPR auto index_list_size(const T &x)
Definition: Meta.h:241
constexpr bool is_constant_evaluated()
Definition: Meta.h:587
const T * return_ptr()
void swap(scoped_array< T > &a, scoped_array< T > &b)
Definition: Memory.h:788
constexpr int max_size_prefer_dynamic(A a, B b)
Definition: Meta.h:566
typename add_const_on_value_type< T >::type add_const_on_value_type_t
Definition: Meta.h:176
constexpr int min_size_prefer_dynamic(A a, B b)
Definition: Meta.h:537
std::int32_t int32_t
Definition: Meta.h:40
std::int8_t int8_t
Definition: Meta.h:36
std::uint8_t uint8_t
Definition: Meta.h:35
void swap(T &a, T &b)
Definition: Meta.h:419
bool is_exactly_one(const X &x)
Definition: Meta.h:482
std::int16_t int16_t
Definition: Meta.h:38
std::int64_t int64_t
Definition: Meta.h:42
bool not_equal_strict(const double &x, const double &y)
Definition: Meta.h:492
bool equal_strict(const double &x, const double &y)
Definition: Meta.h:467
std::uint16_t uint16_t
Definition: Meta.h:37
T div_ceil(const T &a, const T &b)
Definition: Meta.h:428
std::uint32_t uint32_t
Definition: Meta.h:39
std::uint64_t uint64_t
Definition: Meta.h:41
bool is_exactly_zero(const X &x)
Definition: Meta.h:475
: InteropHeaders
Definition: Core:139
std::array< T, N > array
Definition: EmulateArray.h:256
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex
Definition: Meta.h:74
const int Dynamic
Definition: Constants.h:24
Definition: BFloat16.h:222
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:231
typename internal::make_unsigned< Y >::type UnsignedY
Definition: Meta.h:444
static bool run(const X &x, const Y &y)
Definition: Meta.h:437