$darkmode
Eigen  5.0.1-dev
Meta.h
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 // IWYU pragma: private
15 #include "../InternalHeaderCheck.h"
16 
17 #if defined(EIGEN_GPU_COMPILE_PHASE)
18 
19 #include <cfloat>
20 
21 #if defined(EIGEN_CUDA_ARCH)
22 #include <math_constants.h>
23 #endif
24 
25 #if defined(EIGEN_HIP_DEVICE_COMPILE)
26 #include "Eigen/src/Core/arch/HIP/hcc/math_constants.h"
27 #endif
28 
29 #endif
30 
31 // Define portable (u)int{32,64} types
32 #include <cstdint>
33 
34 namespace Eigen {
35 namespace numext {
36 typedef std::uint8_t uint8_t;
37 typedef std::int8_t int8_t;
38 typedef std::uint16_t uint16_t;
39 typedef std::int16_t int16_t;
40 typedef std::uint32_t uint32_t;
41 typedef std::int32_t int32_t;
42 typedef std::uint64_t uint64_t;
43 typedef std::int64_t int64_t;
44 
45 template <size_t Size>
46 struct get_integer_by_size {
47  typedef void signed_type;
48  typedef void unsigned_type;
49 };
50 template <>
51 struct get_integer_by_size<1> {
52  typedef int8_t signed_type;
53  typedef uint8_t unsigned_type;
54 };
55 template <>
56 struct get_integer_by_size<2> {
57  typedef int16_t signed_type;
58  typedef uint16_t unsigned_type;
59 };
60 template <>
61 struct get_integer_by_size<4> {
62  typedef int32_t signed_type;
63  typedef uint32_t unsigned_type;
64 };
65 template <>
66 struct get_integer_by_size<8> {
67  typedef int64_t signed_type;
68  typedef uint64_t unsigned_type;
69 };
70 } // namespace numext
71 } // namespace Eigen
72 
73 namespace Eigen {
74 
75 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
76 
82 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
83 
84 namespace internal {
85 
93 using std::false_type;
94 using std::true_type;
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_const;
108 using std::remove_pointer;
109 using std::remove_reference;
110 
111 template <typename T>
112 struct remove_all {
113  typedef T type;
114 };
115 template <typename T>
116 struct remove_all<const T> {
117  typedef typename remove_all<T>::type type;
118 };
119 template <typename T>
120 struct remove_all<T const&> {
121  typedef typename remove_all<T>::type type;
122 };
123 template <typename T>
124 struct remove_all<T&> {
125  typedef typename remove_all<T>::type type;
126 };
127 template <typename T>
128 struct remove_all<T const*> {
129  typedef typename remove_all<T>::type type;
130 };
131 template <typename T>
132 struct remove_all<T*> {
133  typedef typename remove_all<T>::type type;
134 };
135 
136 template <typename T>
137 using remove_all_t = typename remove_all<T>::type;
138 
139 template <typename T>
140 struct is_arithmetic {
141  enum { value = false };
142 };
143 template <>
144 struct is_arithmetic<float> {
145  enum { value = true };
146 };
147 template <>
148 struct is_arithmetic<double> {
149  enum { value = true };
150 };
151 // GPU devices treat `long double` as `double`.
152 #ifndef EIGEN_GPU_COMPILE_PHASE
153 template <>
154 struct is_arithmetic<long double> {
155  enum { value = true };
156 };
157 #endif
158 template <>
159 struct is_arithmetic<bool> {
160  enum { value = true };
161 };
162 template <>
163 struct is_arithmetic<char> {
164  enum { value = true };
165 };
166 template <>
167 struct is_arithmetic<signed char> {
168  enum { value = true };
169 };
170 template <>
171 struct is_arithmetic<unsigned char> {
172  enum { value = true };
173 };
174 template <>
175 struct is_arithmetic<signed short> {
176  enum { value = true };
177 };
178 template <>
179 struct is_arithmetic<unsigned short> {
180  enum { value = true };
181 };
182 template <>
183 struct is_arithmetic<signed int> {
184  enum { value = true };
185 };
186 template <>
187 struct is_arithmetic<unsigned int> {
188  enum { value = true };
189 };
190 template <>
191 struct is_arithmetic<signed long> {
192  enum { value = true };
193 };
194 template <>
195 struct is_arithmetic<unsigned long> {
196  enum { value = true };
197 };
198 
199 template <typename T, typename U>
200 struct is_same {
201  enum { value = 0 };
202 };
203 template <typename T>
204 struct is_same<T, T> {
205  enum { value = 1 };
206 };
207 
208 template <class T>
209 struct is_void : is_same<void, std::remove_const_t<T>> {};
210 
219 #if EIGEN_COMP_CXXVER >= 17 && defined(__cpp_lib_void_t) && __cpp_lib_void_t >= 201411L
220 using std::void_t;
221 #else
222 template <typename...>
223 using void_t = void;
224 #endif
225 
226 template <>
227 struct is_arithmetic<signed long long> {
228  enum { value = true };
229 };
230 template <>
231 struct is_arithmetic<unsigned long long> {
232  enum { value = true };
233 };
234 using std::is_integral;
235 
236 using std::make_unsigned;
237 
238 template <typename T>
239 struct is_const {
240  enum { value = 0 };
241 };
242 template <typename T>
243 struct is_const<T const> {
244  enum { value = 1 };
245 };
246 
247 template <typename T>
248 struct add_const_on_value_type {
249  typedef const T type;
250 };
251 template <typename T>
252 struct add_const_on_value_type<T&> {
253  typedef T const& type;
254 };
255 template <typename T>
256 struct add_const_on_value_type<T*> {
257  typedef T const* type;
258 };
259 template <typename T>
260 struct add_const_on_value_type<T* const> {
261  typedef T const* const type;
262 };
263 template <typename T>
264 struct add_const_on_value_type<T const* const> {
265  typedef T const* const type;
266 };
267 
268 template <typename T>
269 using add_const_on_value_type_t = typename add_const_on_value_type<T>::type;
270 
271 using std::is_convertible;
272 
276 class noncopyable {
277  EIGEN_DEVICE_FUNC noncopyable(const noncopyable&);
278  EIGEN_DEVICE_FUNC const noncopyable& operator=(const noncopyable&);
279 
280  protected:
281  EIGEN_DEVICE_FUNC noncopyable() {}
282  EIGEN_DEVICE_FUNC ~noncopyable() {}
283 };
284 
299 template <typename T, typename EnableIf = void>
300 struct array_size {
301  static constexpr Index value = Dynamic;
302 };
303 
304 template <typename T>
305 struct array_size<T, std::enable_if_t<((T::SizeAtCompileTime & 0) == 0)>> {
306  static constexpr Index value = T::SizeAtCompileTime;
307 };
308 
309 template <typename T, int N>
310 struct array_size<const T (&)[N]> {
311  static constexpr Index value = N;
312 };
313 template <typename T, int N>
314 struct array_size<T (&)[N]> {
315  static constexpr Index value = N;
316 };
317 
318 template <typename T, std::size_t N>
319 struct array_size<const std::array<T, N>> {
320  static constexpr Index value = N;
321 };
322 template <typename T, std::size_t N>
323 struct array_size<std::array<T, N>> {
324  static constexpr Index value = N;
325 };
326 
337 #if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_ssize) && __cpp_lib_ssize >= 201902L
338 
339 template <typename T>
340 constexpr auto index_list_size(T&& x) {
341  using std::ssize;
342  return ssize(std::forward<T>(x));
343 }
344 
345 #else
346 
347 template <typename T>
348 constexpr auto index_list_size(const T& x) {
349  using R = std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(x.size())>>;
350  return static_cast<R>(x.size());
351 }
352 
353 template <typename T, std::ptrdiff_t N>
354 constexpr std::ptrdiff_t index_list_size(const T (&)[N]) {
355  return N;
356 }
357 #endif
358 
369 #if EIGEN_HAS_STD_INVOKE_RESULT
370 template <typename T>
371 struct result_of;
372 
373 template <typename F, typename... ArgTypes>
374 struct result_of<F(ArgTypes...)> {
375  typedef typename std::invoke_result<F, ArgTypes...>::type type1;
376  typedef remove_all_t<type1> type;
377 };
378 
379 template <typename F, typename... ArgTypes>
380 struct invoke_result {
381  typedef typename std::invoke_result<F, ArgTypes...>::type type1;
382  typedef remove_all_t<type1> type;
383 };
384 #else
385 template <typename T>
386 struct result_of {
387  typedef typename std::result_of<T>::type type1;
388  typedef remove_all_t<type1> type;
389 };
390 
391 template <typename F, typename... ArgTypes>
392 struct invoke_result {
393  typedef typename result_of<F(ArgTypes...)>::type type1;
394  typedef remove_all_t<type1> type;
395 };
396 #endif
397 
398 // Reduces a sequence of bools to true if all are true, false otherwise.
399 template <bool... values>
400 using reduce_all =
401  std::is_same<std::integer_sequence<bool, values..., true>, std::integer_sequence<bool, true, values...>>;
402 
403 // Reduces a sequence of bools to true if any are true, false if all false.
404 template <bool... values>
405 using reduce_any = std::integral_constant<bool, !std::is_same<std::integer_sequence<bool, values..., false>,
406  std::integer_sequence<bool, false, values...>>::value>;
407 
408 struct meta_yes {
409  char a[1];
410 };
411 struct meta_no {
412  char a[2];
413 };
414 
415 // Check whether T::ReturnType does exist
416 template <typename T>
417 struct has_ReturnType {
418  template <typename C>
419  static meta_yes testFunctor(C const*, typename C::ReturnType const* = 0);
420  template <typename C>
421  static meta_no testFunctor(...);
422 
423  enum { value = sizeof(testFunctor<T>(static_cast<T*>(0))) == sizeof(meta_yes) };
424 };
425 
426 template <typename T>
427 const T* return_ptr();
428 
429 template <typename T, typename IndexType = Index>
430 struct has_nullary_operator {
431  template <typename C>
432  static meta_yes testFunctor(C const*, std::enable_if_t<(sizeof(return_ptr<C>()->operator()()) > 0)>* = 0);
433  static meta_no testFunctor(...);
434 
435  enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
436 };
437 
438 template <typename T, typename IndexType = Index>
439 struct has_unary_operator {
440  template <typename C>
441  static meta_yes testFunctor(C const*, std::enable_if_t<(sizeof(return_ptr<C>()->operator()(IndexType(0))) > 0)>* = 0);
442  static meta_no testFunctor(...);
443 
444  enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
445 };
446 
447 template <typename T, typename IndexType = Index>
448 struct has_binary_operator {
449  template <typename C>
450  static meta_yes testFunctor(
451  C const*, std::enable_if_t<(sizeof(return_ptr<C>()->operator()(IndexType(0), IndexType(0))) > 0)>* = 0);
452  static meta_no testFunctor(...);
453 
454  enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
455 };
456 
460 template <int Y, int InfX = 0, int SupX = ((Y == 1) ? 1 : Y / 2),
461  bool Done = ((SupX - InfX) <= 1 || ((SupX * SupX <= Y) && ((SupX + 1) * (SupX + 1) > Y)))>
462 class meta_sqrt {
463  enum {
464  MidX = (InfX + SupX) / 2,
465  TakeInf = MidX * MidX > Y ? 1 : 0,
466  NewInf = int(TakeInf) ? InfX : int(MidX),
467  NewSup = int(TakeInf) ? int(MidX) : SupX
468  };
469 
470  public:
471  enum { ret = meta_sqrt<Y, NewInf, NewSup>::ret };
472 };
473 
474 template <int Y, int InfX, int SupX>
475 class meta_sqrt<Y, InfX, SupX, true> {
476  public:
477  enum { ret = (SupX * SupX <= Y) ? SupX : InfX };
478 };
479 
483 template <int A, int B, int K = 1, bool Done = ((A * K) % B) == 0, bool Big = (A >= B)>
484 struct meta_least_common_multiple {
485  enum { ret = meta_least_common_multiple<A, B, K + 1>::ret };
486 };
487 template <int A, int B, int K, bool Done>
488 struct meta_least_common_multiple<A, B, K, Done, false> {
489  enum { ret = meta_least_common_multiple<B, A, K>::ret };
490 };
491 template <int A, int B, int K>
492 struct meta_least_common_multiple<A, B, K, true, true> {
493  enum { ret = A * K };
494 };
495 
497 template <typename T, typename U>
498 struct scalar_product_traits {
499  enum { Defined = 0 };
500 };
501 
502 // FIXME quick workaround around current limitation of result_of
503 // template<typename Scalar, typename ArgType0, typename ArgType1>
504 // struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
505 // typedef typename scalar_product_traits<remove_all_t<ArgType0>, remove_all_t<ArgType1>>::ReturnType type;
506 // };
507 
511 template <unsigned Len, unsigned Align>
512 struct aligned_storage {
513  struct type {
514  EIGEN_ALIGN_TO_BOUNDARY(Align) unsigned char data[Len];
515  };
516 };
517 
518 } // end namespace internal
519 
520 template <typename T>
521 struct NumTraits;
522 
523 namespace numext {
524 
525 #if defined(EIGEN_GPU_COMPILE_PHASE)
526 template <typename T>
527 EIGEN_DEVICE_FUNC void swap(T& a, T& b) {
528  T tmp = b;
529  b = a;
530  a = tmp;
531 }
532 #else
533 template <typename T>
534 EIGEN_STRONG_INLINE void swap(T& a, T& b) {
535  std::swap(a, b);
536 }
537 #endif
538 
539 using std::numeric_limits;
540 
541 // Handle integer comparisons of different signedness.
542 template <typename X, typename Y, bool XIsInteger = NumTraits<X>::IsInteger, bool XIsSigned = NumTraits<X>::IsSigned,
543  bool YIsInteger = NumTraits<Y>::IsInteger, bool YIsSigned = NumTraits<Y>::IsSigned>
544 struct equal_strict_impl {
545  static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) { return x == y; }
546 };
547 template <typename X, typename Y>
548 struct equal_strict_impl<X, Y, true, false, true, true> {
549  // X is an unsigned integer
550  // Y is a signed integer
551  // if Y is non-negative, it may be represented exactly as its unsigned counterpart.
552  using UnsignedY = typename internal::make_unsigned<Y>::type;
553  static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
554  return y < Y(0) ? false : (x == static_cast<UnsignedY>(y));
555  }
556 };
557 template <typename X, typename Y>
558 struct equal_strict_impl<X, Y, true, true, true, false> {
559  // X is a signed integer
560  // Y is an unsigned integer
561  static EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool run(const X& x, const Y& y) {
562  return equal_strict_impl<Y, X>::run(y, x);
563  }
564 };
565 
566 // The aim of the following functions is to bypass -Wfloat-equal warnings
567 // when we really want a strict equality comparison on floating points.
568 template <typename X, typename Y>
569 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const X& x, const Y& y) {
570  return equal_strict_impl<X, Y>::run(x, y);
571 }
572 
573 #if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
574 template <>
575 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const float& x, const float& y) {
576  return std::equal_to<float>()(x, y);
577 }
578 
579 template <>
580 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool equal_strict(const double& x, const double& y) {
581  return std::equal_to<double>()(x, y);
582 }
583 #endif
584 
589 template <typename X>
590 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_zero(const X& x) {
591  return equal_strict(x, typename NumTraits<X>::Literal{0});
592 }
593 
598 template <typename X>
599 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool is_exactly_one(const X& x) {
600  return equal_strict(x, typename NumTraits<X>::Literal{1});
601 }
602 
603 template <typename X, typename Y>
604 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const X& x, const Y& y) {
605  return !equal_strict_impl<X, Y>::run(x, y);
606 }
607 
608 #if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
609 template <>
610 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const float& x, const float& y) {
611  return std::not_equal_to<float>()(x, y);
612 }
613 
614 template <>
615 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool not_equal_strict(const double& x, const double& y) {
616  return std::not_equal_to<double>()(x, y);
617 }
618 #endif
619 
620 } // end namespace numext
621 
622 namespace internal {
623 
624 template <typename Scalar>
625 struct is_identically_zero_impl {
626  static inline bool run(const Scalar& s) { return numext::is_exactly_zero(s); }
627 };
628 
629 template <typename Scalar>
630 EIGEN_STRONG_INLINE bool is_identically_zero(const Scalar& s) {
631  return is_identically_zero_impl<Scalar>::run(s);
632 }
633 
636 template <typename A>
637 constexpr bool is_int_or_enum_v = std::is_enum<A>::value || std::is_integral<A>::value;
638 
639 template <typename A, typename B>
640 constexpr void plain_enum_asserts(A, B) {
641  static_assert(is_int_or_enum_v<A>, "Argument a must be an integer or enum");
642  static_assert(is_int_or_enum_v<B>, "Argument b must be an integer or enum");
643 }
644 
646 template <typename A, typename B>
647 constexpr int plain_enum_min(A a, B b) {
648  plain_enum_asserts(a, b);
649  return ((int)a <= (int)b) ? (int)a : (int)b;
650 }
651 
653 template <typename A, typename B>
654 constexpr int plain_enum_max(A a, B b) {
655  plain_enum_asserts(a, b);
656  return ((int)a >= (int)b) ? (int)a : (int)b;
657 }
658 
665 template <typename A, typename B>
666 constexpr int min_size_prefer_dynamic(A a, B b) {
667  plain_enum_asserts(a, b);
668  if ((int)a == 0 || (int)b == 0) return 0;
669  if ((int)a == 1 || (int)b == 1) return 1;
670  if ((int)a == Dynamic || (int)b == Dynamic) return Dynamic;
671  return plain_enum_min(a, b);
672 }
673 
680 template <typename A, typename B>
681 constexpr int min_size_prefer_fixed(A a, B b) {
682  plain_enum_asserts(a, b);
683  if ((int)a == 0 || (int)b == 0) return 0;
684  if ((int)a == 1 || (int)b == 1) return 1;
685  if ((int)a == Dynamic && (int)b == Dynamic) return Dynamic;
686  if ((int)a == Dynamic) return (int)b;
687  if ((int)b == Dynamic) return (int)a;
688  return plain_enum_min(a, b);
689 }
690 
692 template <typename A, typename B>
693 constexpr int max_size_prefer_dynamic(A a, B b) {
694  plain_enum_asserts(a, b);
695  if ((int)a == Dynamic || (int)b == Dynamic) return Dynamic;
696  return plain_enum_max(a, b);
697 }
698 
699 template <typename A, typename B>
700 inline constexpr int size_prefer_fixed(A a, B b) {
701  plain_enum_asserts(a, b);
702  return int(a) == Dynamic ? int(b) : int(a);
703 }
704 
705 template <typename A, typename B>
706 inline constexpr bool enum_eq_not_dynamic(A a, B b) {
707  plain_enum_asserts(a, b);
708  if ((int)a == Dynamic || (int)b == Dynamic) return false;
709  return (int)a == (int)b;
710 }
711 
712 template <typename A, typename B>
713 constexpr bool enum_lt_not_dynamic(A a, B b) {
714  plain_enum_asserts(a, b);
715  if ((int)a == Dynamic || (int)b == Dynamic) return false;
716  return (int)a < (int)b;
717 }
718 
719 template <typename A, typename B>
720 constexpr bool enum_le_not_dynamic(A a, B b) {
721  plain_enum_asserts(a, b);
722  if ((int)a == Dynamic || (int)b == Dynamic) return false;
723  return (int)a <= (int)b;
724 }
725 
726 template <typename A, typename B>
727 constexpr bool enum_gt_not_dynamic(A a, B b) {
728  plain_enum_asserts(a, b);
729  if ((int)a == Dynamic || (int)b == Dynamic) return false;
730  return (int)a > (int)b;
731 }
732 
733 template <typename A, typename B>
734 constexpr bool enum_ge_not_dynamic(A a, B b) {
735  plain_enum_asserts(a, b);
736  if ((int)a == Dynamic || (int)b == Dynamic) return false;
737  return (int)a >= (int)b;
738 }
739 
741 constexpr bool logical_xor(bool a, bool b) { return a != b; }
742 
744 constexpr bool check_implication(bool a, bool b) { return !a || b; }
745 
747 #if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L
748 using std::is_constant_evaluated;
749 #else
750 constexpr bool is_constant_evaluated() { return false; }
751 #endif
752 
753 template <typename Scalar>
754 using make_complex_t = std::conditional_t<NumTraits<Scalar>::IsComplex, Scalar, std::complex<Scalar>>;
755 
756 } // end namespace internal
757 
758 } // end namespace Eigen
759 
760 #endif // EIGEN_META_H
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
Definition: BFloat16.h:231
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
std::enable_if_t< std::is_base_of< DenseBase< std::decay_t< DerivedA > >, std::decay_t< DerivedA > >::value &&std::is_base_of< DenseBase< std::decay_t< DerivedB > >, std::decay_t< DerivedB > >::value, void > swap(DerivedA &&a, DerivedB &&b)
Definition: DenseBase.h:667
const int Dynamic
Definition: Constants.h:25