xref: /aosp_15_r20/external/eigen/Eigen/src/Core/util/Meta.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2015 Gael Guennebaud <[email protected]>
5 // Copyright (C) 2006-2008 Benoit Jacob <[email protected]>
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 #if defined(EIGEN_GPU_COMPILE_PHASE)
15 
16  #include <cfloat>
17 
18  #if defined(EIGEN_CUDA_ARCH)
19   #include <math_constants.h>
20  #endif
21 
22  #if defined(EIGEN_HIP_DEVICE_COMPILE)
23   #include "Eigen/src/Core/arch/HIP/hcc/math_constants.h"
24   #endif
25 
26 #endif
27 
28 // Recent versions of ICC require <cstdint> for pointer types below.
29 #define EIGEN_ICC_NEEDS_CSTDINT (EIGEN_COMP_ICC>=1600 && EIGEN_COMP_CXXVER >= 11)
30 
31 // Define portable (u)int{32,64} types
32 #if EIGEN_HAS_CXX11 || EIGEN_ICC_NEEDS_CSTDINT
33 #include <cstdint>
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 }
46 #else
47 // Without c++11, all compilers able to compile Eigen also
48 // provide the C99 stdint.h header file.
49 #include <stdint.h>
50 namespace Eigen {
51 namespace numext {
52 typedef ::uint8_t  uint8_t;
53 typedef ::int8_t   int8_t;
54 typedef ::uint16_t uint16_t;
55 typedef ::int16_t  int16_t;
56 typedef ::uint32_t uint32_t;
57 typedef ::int32_t  int32_t;
58 typedef ::uint64_t uint64_t;
59 typedef ::int64_t  int64_t;
60 }
61 }
62 #endif
63 
64 namespace Eigen {
65 
66 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex;
67 
68 /**
69  * \brief The Index type as used for the API.
70  * \details To change this, \c \#define the preprocessor symbol \c EIGEN_DEFAULT_DENSE_INDEX_TYPE.
71  * \sa \blank \ref TopicPreprocessorDirectives, StorageIndex.
72  */
73 
74 typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE Index;
75 
76 namespace internal {
77 
78 /** \internal
79   * \file Meta.h
80   * This file contains generic metaprogramming classes which are not specifically related to Eigen.
81   * \note In case you wonder, yes we're aware that Boost already provides all these features,
82   * we however don't want to add a dependency to Boost.
83   */
84 
85 // Only recent versions of ICC complain about using ptrdiff_t to hold pointers,
86 // and older versions do not provide *intptr_t types.
87 #if EIGEN_ICC_NEEDS_CSTDINT
88 typedef std::intptr_t  IntPtr;
89 typedef std::uintptr_t UIntPtr;
90 #else
91 typedef std::ptrdiff_t IntPtr;
92 typedef std::size_t UIntPtr;
93 #endif
94 #undef EIGEN_ICC_NEEDS_CSTDINT
95 
96 struct true_type {  enum { value = 1 }; };
97 struct false_type { enum { value = 0 }; };
98 
99 template<bool Condition>
100 struct bool_constant;
101 
102 template<>
103 struct bool_constant<true> : true_type {};
104 
105 template<>
106 struct bool_constant<false> : false_type {};
107 
108 template<bool Condition, typename Then, typename Else>
109 struct conditional { typedef Then type; };
110 
111 template<typename Then, typename Else>
112 struct conditional <false, Then, Else> { typedef Else type; };
113 
114 template<typename T> struct remove_reference { typedef T type; };
115 template<typename T> struct remove_reference<T&> { typedef T type; };
116 
117 template<typename T> struct remove_pointer { typedef T type; };
118 template<typename T> struct remove_pointer<T*> { typedef T type; };
119 template<typename T> struct remove_pointer<T*const> { typedef T type; };
120 
121 template <class T> struct remove_const { typedef T type; };
122 template <class T> struct remove_const<const T> { typedef T type; };
123 template <class T> struct remove_const<const T[]> { typedef T type[]; };
124 template <class T, unsigned int Size> struct remove_const<const T[Size]> { typedef T type[Size]; };
125 
126 template<typename T> struct remove_all { typedef T type; };
127 template<typename T> struct remove_all<const T>   { typedef typename remove_all<T>::type type; };
128 template<typename T> struct remove_all<T const&>  { typedef typename remove_all<T>::type type; };
129 template<typename T> struct remove_all<T&>        { typedef typename remove_all<T>::type type; };
130 template<typename T> struct remove_all<T const*>  { typedef typename remove_all<T>::type type; };
131 template<typename T> struct remove_all<T*>        { typedef typename remove_all<T>::type type; };
132 
133 template<typename T> struct is_arithmetic      { enum { value = false }; };
134 template<> struct is_arithmetic<float>         { enum { value = true }; };
135 template<> struct is_arithmetic<double>        { enum { value = true }; };
136 template<> struct is_arithmetic<long double>   { enum { value = true }; };
137 template<> struct is_arithmetic<bool>          { enum { value = true }; };
138 template<> struct is_arithmetic<char>          { enum { value = true }; };
139 template<> struct is_arithmetic<signed char>   { enum { value = true }; };
140 template<> struct is_arithmetic<unsigned char> { enum { value = true }; };
141 template<> struct is_arithmetic<signed short>  { enum { value = true }; };
142 template<> struct is_arithmetic<unsigned short>{ enum { value = true }; };
143 template<> struct is_arithmetic<signed int>    { enum { value = true }; };
144 template<> struct is_arithmetic<unsigned int>  { enum { value = true }; };
145 template<> struct is_arithmetic<signed long>   { enum { value = true }; };
146 template<> struct is_arithmetic<unsigned long> { enum { value = true }; };
147 
148 template<typename T, typename U> struct is_same { enum { value = 0 }; };
149 template<typename T> struct is_same<T,T> { enum { value = 1 }; };
150 
151 template< class T >
152 struct is_void : is_same<void, typename remove_const<T>::type> {};
153 
154 #if EIGEN_HAS_CXX11
155 template<> struct is_arithmetic<signed long long>   { enum { value = true }; };
156 template<> struct is_arithmetic<unsigned long long> { enum { value = true }; };
157 using std::is_integral;
158 #else
159 template<typename T> struct is_integral               { enum { value = false }; };
160 template<> struct is_integral<bool>                   { enum { value = true }; };
161 template<> struct is_integral<char>                   { enum { value = true }; };
162 template<> struct is_integral<signed char>            { enum { value = true }; };
163 template<> struct is_integral<unsigned char>          { enum { value = true }; };
164 template<> struct is_integral<signed short>           { enum { value = true }; };
165 template<> struct is_integral<unsigned short>         { enum { value = true }; };
166 template<> struct is_integral<signed int>             { enum { value = true }; };
167 template<> struct is_integral<unsigned int>           { enum { value = true }; };
168 template<> struct is_integral<signed long>            { enum { value = true }; };
169 template<> struct is_integral<unsigned long>          { enum { value = true }; };
170 #if EIGEN_COMP_MSVC
171 template<> struct is_integral<signed __int64>         { enum { value = true }; };
172 template<> struct is_integral<unsigned __int64>       { enum { value = true }; };
173 #endif
174 #endif
175 
176 #if EIGEN_HAS_CXX11
177 using std::make_unsigned;
178 #else
179 // TODO: Possibly improve this implementation of make_unsigned.
180 // It is currently used only by
181 // template<typename Scalar> struct random_default_impl<Scalar, false, true>.
182 template<typename> struct make_unsigned;
183 template<> struct make_unsigned<char>             { typedef unsigned char type; };
184 template<> struct make_unsigned<signed char>      { typedef unsigned char type; };
185 template<> struct make_unsigned<unsigned char>    { typedef unsigned char type; };
186 template<> struct make_unsigned<signed short>     { typedef unsigned short type; };
187 template<> struct make_unsigned<unsigned short>   { typedef unsigned short type; };
188 template<> struct make_unsigned<signed int>       { typedef unsigned int type; };
189 template<> struct make_unsigned<unsigned int>     { typedef unsigned int type; };
190 template<> struct make_unsigned<signed long>      { typedef unsigned long type; };
191 template<> struct make_unsigned<unsigned long>    { typedef unsigned long type; };
192 #if EIGEN_COMP_MSVC
193 template<> struct make_unsigned<signed __int64>   { typedef unsigned __int64 type; };
194 template<> struct make_unsigned<unsigned __int64> { typedef unsigned __int64 type; };
195 #endif
196 
197 // Some platforms define int64_t as `long long` even for C++03, where
198 // `long long` is not guaranteed by the standard. In this case we are missing
199 // the definition for make_unsigned. If we just define it, we run into issues
200 // where `long long` doesn't exist in some compilers for C++03. We therefore add
201 // the specialization for these platforms only.
202 #if EIGEN_OS_MAC || EIGEN_COMP_MINGW
203 template<> struct make_unsigned<unsigned long long> { typedef unsigned long long type; };
204 template<> struct make_unsigned<long long>          { typedef unsigned long long type; };
205 #endif
206 #endif
207 
208 template <typename T> struct add_const { typedef const T type; };
209 template <typename T> struct add_const<T&> { typedef T& type; };
210 
211 template <typename T> struct is_const { enum { value = 0 }; };
212 template <typename T> struct is_const<T const> { enum { value = 1 }; };
213 
214 template<typename T> struct add_const_on_value_type            { typedef const T type;  };
215 template<typename T> struct add_const_on_value_type<T&>        { typedef T const& type; };
216 template<typename T> struct add_const_on_value_type<T*>        { typedef T const* type; };
217 template<typename T> struct add_const_on_value_type<T* const>  { typedef T const* const type; };
218 template<typename T> struct add_const_on_value_type<T const* const>  { typedef T const* const type; };
219 
220 #if EIGEN_HAS_CXX11
221 
222 using std::is_convertible;
223 
224 #else
225 
226 template<typename From, typename To>
227 struct is_convertible_impl
228 {
229 private:
230   struct any_conversion
231   {
232     template <typename T> any_conversion(const volatile T&);
233     template <typename T> any_conversion(T&);
234   };
235   struct yes {int a[1];};
236   struct no  {int a[2];};
237 
238   template<typename T>
239   static yes test(T, int);
240 
241   template<typename T>
242   static no  test(any_conversion, ...);
243 
244 public:
245   static typename internal::remove_reference<From>::type* ms_from;
246 #ifdef __INTEL_COMPILER
247   #pragma warning push
248   #pragma warning ( disable : 2259 )
249 #endif
250   enum { value = sizeof(test<To>(*ms_from, 0))==sizeof(yes) };
251 #ifdef __INTEL_COMPILER
252   #pragma warning pop
253 #endif
254 };
255 
256 template<typename From, typename To>
257 struct is_convertible
258 {
259   enum { value = is_convertible_impl<From,To>::value };
260 };
261 
262 template<typename T>
263 struct is_convertible<T,T&> { enum { value = false }; };
264 
265 template<typename T>
266 struct is_convertible<const T,const T&> { enum { value = true }; };
267 
268 #endif
269 
270 /** \internal Allows to enable/disable an overload
271   * according to a compile time condition.
272   */
273 template<bool Condition, typename T=void> struct enable_if;
274 
275 template<typename T> struct enable_if<true,T>
276 { typedef T type; };
277 
278 #if defined(EIGEN_GPU_COMPILE_PHASE) && !EIGEN_HAS_CXX11
279 #if !defined(__FLT_EPSILON__)
280 #define __FLT_EPSILON__ FLT_EPSILON
281 #define __DBL_EPSILON__ DBL_EPSILON
282 #endif
283 
284 namespace device {
285 
286 template<typename T> struct numeric_limits
287 {
288   EIGEN_DEVICE_FUNC
289   static EIGEN_CONSTEXPR T epsilon() { return 0; }
290   static T (max)() { assert(false && "Highest not supported for this type"); }
291   static T (min)() { assert(false && "Lowest not supported for this type"); }
292   static T infinity() { assert(false && "Infinity not supported for this type"); }
293   static T quiet_NaN() { assert(false && "quiet_NaN not supported for this type"); }
294 };
295 template<> struct numeric_limits<float>
296 {
297   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
298   static float epsilon() { return __FLT_EPSILON__; }
299   EIGEN_DEVICE_FUNC
300   static float (max)() {
301   #if defined(EIGEN_CUDA_ARCH)
302     return CUDART_MAX_NORMAL_F;
303   #else
304     return HIPRT_MAX_NORMAL_F;
305   #endif
306   }
307   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
308   static float (min)() { return FLT_MIN; }
309   EIGEN_DEVICE_FUNC
310   static float infinity() {
311   #if defined(EIGEN_CUDA_ARCH)
312     return CUDART_INF_F;
313   #else
314     return HIPRT_INF_F;
315   #endif
316   }
317   EIGEN_DEVICE_FUNC
318   static float quiet_NaN() {
319   #if defined(EIGEN_CUDA_ARCH)
320     return CUDART_NAN_F;
321   #else
322     return HIPRT_NAN_F;
323   #endif
324   }
325 };
326 template<> struct numeric_limits<double>
327 {
328   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
329   static double epsilon() { return __DBL_EPSILON__; }
330   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
331   static double (max)() { return DBL_MAX; }
332   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
333   static double (min)() { return DBL_MIN; }
334   EIGEN_DEVICE_FUNC
335   static double infinity() {
336   #if defined(EIGEN_CUDA_ARCH)
337     return CUDART_INF;
338   #else
339     return HIPRT_INF;
340   #endif
341   }
342   EIGEN_DEVICE_FUNC
343   static double quiet_NaN() {
344   #if defined(EIGEN_CUDA_ARCH)
345     return CUDART_NAN;
346   #else
347     return HIPRT_NAN;
348   #endif
349   }
350 };
351 template<> struct numeric_limits<int>
352 {
353   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
354   static int epsilon() { return 0; }
355   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
356   static int (max)() { return INT_MAX; }
357   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
358   static int (min)() { return INT_MIN; }
359 };
360 template<> struct numeric_limits<unsigned int>
361 {
362   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
363   static unsigned int epsilon() { return 0; }
364   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
365   static unsigned int (max)() { return UINT_MAX; }
366   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
367   static unsigned int (min)() { return 0; }
368 };
369 template<> struct numeric_limits<long>
370 {
371   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
372   static long epsilon() { return 0; }
373   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
374   static long (max)() { return LONG_MAX; }
375   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
376   static long (min)() { return LONG_MIN; }
377 };
378 template<> struct numeric_limits<unsigned long>
379 {
380   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
381   static unsigned long epsilon() { return 0; }
382   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
383   static unsigned long (max)() { return ULONG_MAX; }
384   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
385   static unsigned long (min)() { return 0; }
386 };
387 template<> struct numeric_limits<long long>
388 {
389   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
390   static long long epsilon() { return 0; }
391   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
392   static long long (max)() { return LLONG_MAX; }
393   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
394   static long long (min)() { return LLONG_MIN; }
395 };
396 template<> struct numeric_limits<unsigned long long>
397 {
398   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
399   static unsigned long long epsilon() { return 0; }
400   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
401   static unsigned long long (max)() { return ULLONG_MAX; }
402   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
403   static unsigned long long (min)() { return 0; }
404 };
405 template<> struct numeric_limits<bool>
406 {
407   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
408   static bool epsilon() { return false; }
409   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
410   static bool (max)() { return true; }
411   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
412   static bool (min)() { return false; }
413 };
414 
415 }
416 
417 #endif // defined(EIGEN_GPU_COMPILE_PHASE) && !EIGEN_HAS_CXX11
418 
419 /** \internal
420   * A base class do disable default copy ctor and copy assignment operator.
421   */
422 class noncopyable
423 {
424   EIGEN_DEVICE_FUNC noncopyable(const noncopyable&);
425   EIGEN_DEVICE_FUNC const noncopyable& operator=(const noncopyable&);
426 protected:
427   EIGEN_DEVICE_FUNC noncopyable() {}
428   EIGEN_DEVICE_FUNC ~noncopyable() {}
429 };
430 
431 /** \internal
432   * Provides access to the number of elements in the object of as a compile-time constant expression.
433   * It "returns" Eigen::Dynamic if the size cannot be resolved at compile-time (default).
434   *
435   * Similar to std::tuple_size, but more general.
436   *
437   * It currently supports:
438   *  - any types T defining T::SizeAtCompileTime
439   *  - plain C arrays as T[N]
440   *  - std::array (c++11)
441   *  - some internal types such as SingleRange and AllRange
442   *
443   * The second template parameter eases SFINAE-based specializations.
444   */
445 template<typename T, typename EnableIf = void> struct array_size {
446   enum { value = Dynamic };
447 };
448 
449 template<typename T> struct array_size<T,typename internal::enable_if<((T::SizeAtCompileTime&0)==0)>::type> {
450   enum { value = T::SizeAtCompileTime };
451 };
452 
453 template<typename T, int N> struct array_size<const T (&)[N]> {
454   enum { value = N };
455 };
456 template<typename T, int N> struct array_size<T (&)[N]> {
457   enum { value = N };
458 };
459 
460 #if EIGEN_HAS_CXX11
461 template<typename T, std::size_t N> struct array_size<const std::array<T,N> > {
462   enum { value = N };
463 };
464 template<typename T, std::size_t N> struct array_size<std::array<T,N> > {
465   enum { value = N };
466 };
467 #endif
468 
469 /** \internal
470   * Analogue of the std::size free function.
471   * It returns the size of the container or view \a x of type \c T
472   *
473   * It currently supports:
474   *  - any types T defining a member T::size() const
475   *  - plain C arrays as T[N]
476   *
477   */
478 template<typename T>
479 EIGEN_CONSTEXPR Index size(const T& x) { return x.size(); }
480 
481 template<typename T,std::size_t N>
482 EIGEN_CONSTEXPR Index size(const T (&) [N]) { return N; }
483 
484 /** \internal
485   * Convenient struct to get the result type of a nullary, unary, binary, or
486   * ternary functor.
487   *
488   * Pre C++11:
489   * Supports both a Func::result_type member and templated
490   * Func::result<Func(ArgTypes...)>::type member.
491   *
492   * If none of these members is provided, then the type of the first
493   * argument is returned.
494   *
495   * Post C++11:
496   * This uses std::result_of. However, note the `type` member removes
497   * const and converts references/pointers to their corresponding value type.
498   */
499 #if EIGEN_HAS_STD_INVOKE_RESULT
500 template<typename T> struct result_of;
501 
502 template<typename F, typename... ArgTypes>
503 struct result_of<F(ArgTypes...)> {
504   typedef typename std::invoke_result<F, ArgTypes...>::type type1;
505   typedef typename remove_all<type1>::type type;
506 };
507 #elif EIGEN_HAS_STD_RESULT_OF
508 template<typename T> struct result_of {
509   typedef typename std::result_of<T>::type type1;
510   typedef typename remove_all<type1>::type type;
511 };
512 #else
513 template<typename T> struct result_of { };
514 
515 struct has_none {int a[1];};
516 struct has_std_result_type {int a[2];};
517 struct has_tr1_result {int a[3];};
518 
519 template<typename Func, int SizeOf>
520 struct nullary_result_of_select {};
521 
522 template<typename Func>
523 struct nullary_result_of_select<Func, sizeof(has_std_result_type)> {typedef typename Func::result_type type;};
524 
525 template<typename Func>
526 struct nullary_result_of_select<Func, sizeof(has_tr1_result)> {typedef typename Func::template result<Func()>::type type;};
527 
528 template<typename Func>
529 struct result_of<Func()> {
530     template<typename T>
531     static has_std_result_type    testFunctor(T const *, typename T::result_type const * = 0);
532     template<typename T>
533     static has_tr1_result         testFunctor(T const *, typename T::template result<T()>::type const * = 0);
534     static has_none               testFunctor(...);
535 
536     // note that the following indirection is needed for gcc-3.3
537     enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
538     typedef typename nullary_result_of_select<Func, FunctorType>::type type;
539 };
540 
541 template<typename Func, typename ArgType, int SizeOf=sizeof(has_none)>
542 struct unary_result_of_select {typedef typename internal::remove_all<ArgType>::type type;};
543 
544 template<typename Func, typename ArgType>
545 struct unary_result_of_select<Func, ArgType, sizeof(has_std_result_type)> {typedef typename Func::result_type type;};
546 
547 template<typename Func, typename ArgType>
548 struct unary_result_of_select<Func, ArgType, sizeof(has_tr1_result)> {typedef typename Func::template result<Func(ArgType)>::type type;};
549 
550 template<typename Func, typename ArgType>
551 struct result_of<Func(ArgType)> {
552     template<typename T>
553     static has_std_result_type    testFunctor(T const *, typename T::result_type const * = 0);
554     template<typename T>
555     static has_tr1_result         testFunctor(T const *, typename T::template result<T(ArgType)>::type const * = 0);
556     static has_none               testFunctor(...);
557 
558     // note that the following indirection is needed for gcc-3.3
559     enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
560     typedef typename unary_result_of_select<Func, ArgType, FunctorType>::type type;
561 };
562 
563 template<typename Func, typename ArgType0, typename ArgType1, int SizeOf=sizeof(has_none)>
564 struct binary_result_of_select {typedef typename internal::remove_all<ArgType0>::type type;};
565 
566 template<typename Func, typename ArgType0, typename ArgType1>
567 struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_std_result_type)>
568 {typedef typename Func::result_type type;};
569 
570 template<typename Func, typename ArgType0, typename ArgType1>
571 struct binary_result_of_select<Func, ArgType0, ArgType1, sizeof(has_tr1_result)>
572 {typedef typename Func::template result<Func(ArgType0,ArgType1)>::type type;};
573 
574 template<typename Func, typename ArgType0, typename ArgType1>
575 struct result_of<Func(ArgType0,ArgType1)> {
576     template<typename T>
577     static has_std_result_type    testFunctor(T const *, typename T::result_type const * = 0);
578     template<typename T>
579     static has_tr1_result         testFunctor(T const *, typename T::template result<T(ArgType0,ArgType1)>::type const * = 0);
580     static has_none               testFunctor(...);
581 
582     // note that the following indirection is needed for gcc-3.3
583     enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
584     typedef typename binary_result_of_select<Func, ArgType0, ArgType1, FunctorType>::type type;
585 };
586 
587 template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2, int SizeOf=sizeof(has_none)>
588 struct ternary_result_of_select {typedef typename internal::remove_all<ArgType0>::type type;};
589 
590 template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2>
591 struct ternary_result_of_select<Func, ArgType0, ArgType1, ArgType2, sizeof(has_std_result_type)>
592 {typedef typename Func::result_type type;};
593 
594 template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2>
595 struct ternary_result_of_select<Func, ArgType0, ArgType1, ArgType2, sizeof(has_tr1_result)>
596 {typedef typename Func::template result<Func(ArgType0,ArgType1,ArgType2)>::type type;};
597 
598 template<typename Func, typename ArgType0, typename ArgType1, typename ArgType2>
599 struct result_of<Func(ArgType0,ArgType1,ArgType2)> {
600     template<typename T>
601     static has_std_result_type    testFunctor(T const *, typename T::result_type const * = 0);
602     template<typename T>
603     static has_tr1_result         testFunctor(T const *, typename T::template result<T(ArgType0,ArgType1,ArgType2)>::type const * = 0);
604     static has_none               testFunctor(...);
605 
606     // note that the following indirection is needed for gcc-3.3
607     enum {FunctorType = sizeof(testFunctor(static_cast<Func*>(0)))};
608     typedef typename ternary_result_of_select<Func, ArgType0, ArgType1, ArgType2, FunctorType>::type type;
609 };
610 
611 #endif
612 
613 #if EIGEN_HAS_STD_INVOKE_RESULT
614 template<typename F, typename... ArgTypes>
615 struct invoke_result {
616   typedef typename std::invoke_result<F, ArgTypes...>::type type1;
617   typedef typename remove_all<type1>::type type;
618 };
619 #elif EIGEN_HAS_CXX11
620 template<typename F, typename... ArgTypes>
621 struct invoke_result {
622   typedef typename result_of<F(ArgTypes...)>::type type1;
623   typedef typename remove_all<type1>::type type;
624 };
625 #else
626 template<typename F, typename ArgType0 = void, typename ArgType1 = void, typename ArgType2 = void>
627 struct invoke_result {
628   typedef typename result_of<F(ArgType0, ArgType1, ArgType2)>::type type1;
629   typedef typename remove_all<type1>::type type;
630 };
631 
632 template<typename F>
633 struct invoke_result<F, void, void, void> {
634   typedef typename result_of<F()>::type type1;
635   typedef typename remove_all<type1>::type type;
636 };
637 
638 template<typename F, typename ArgType0>
639 struct invoke_result<F, ArgType0, void, void> {
640   typedef typename result_of<F(ArgType0)>::type type1;
641   typedef typename remove_all<type1>::type type;
642 };
643 
644 template<typename F, typename ArgType0, typename ArgType1>
645 struct invoke_result<F, ArgType0, ArgType1, void> {
646   typedef typename result_of<F(ArgType0, ArgType1)>::type type1;
647   typedef typename remove_all<type1>::type type;
648 };
649 #endif
650 
651 struct meta_yes { char a[1]; };
652 struct meta_no  { char a[2]; };
653 
654 // Check whether T::ReturnType does exist
655 template <typename T>
656 struct has_ReturnType
657 {
658   template <typename C> static meta_yes testFunctor(C const *, typename C::ReturnType const * = 0);
659   template <typename C> static meta_no  testFunctor(...);
660 
661   enum { value = sizeof(testFunctor<T>(static_cast<T*>(0))) == sizeof(meta_yes) };
662 };
663 
664 template<typename T> const T* return_ptr();
665 
666 template <typename T, typename IndexType=Index>
667 struct has_nullary_operator
668 {
669   template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ptr<C>()->operator()())>0)>::type * = 0);
670   static meta_no testFunctor(...);
671 
672   enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
673 };
674 
675 template <typename T, typename IndexType=Index>
676 struct has_unary_operator
677 {
678   template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ptr<C>()->operator()(IndexType(0)))>0)>::type * = 0);
679   static meta_no testFunctor(...);
680 
681   enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
682 };
683 
684 template <typename T, typename IndexType=Index>
685 struct has_binary_operator
686 {
687   template <typename C> static meta_yes testFunctor(C const *,typename enable_if<(sizeof(return_ptr<C>()->operator()(IndexType(0),IndexType(0)))>0)>::type * = 0);
688   static meta_no testFunctor(...);
689 
690   enum { value = sizeof(testFunctor(static_cast<T*>(0))) == sizeof(meta_yes) };
691 };
692 
693 /** \internal In short, it computes int(sqrt(\a Y)) with \a Y an integer.
694   * Usage example: \code meta_sqrt<1023>::ret \endcode
695   */
696 template<int Y,
697          int InfX = 0,
698          int SupX = ((Y==1) ? 1 : Y/2),
699          bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
700                                 // use ?: instead of || just to shut up a stupid gcc 4.3 warning
701 class meta_sqrt
702 {
703     enum {
704       MidX = (InfX+SupX)/2,
705       TakeInf = MidX*MidX > Y ? 1 : 0,
706       NewInf = int(TakeInf) ? InfX : int(MidX),
707       NewSup = int(TakeInf) ? int(MidX) : SupX
708     };
709   public:
710     enum { ret = meta_sqrt<Y,NewInf,NewSup>::ret };
711 };
712 
713 template<int Y, int InfX, int SupX>
714 class meta_sqrt<Y, InfX, SupX, true> { public:  enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; };
715 
716 
717 /** \internal Computes the least common multiple of two positive integer A and B
718   * at compile-time.
719   */
720 template<int A, int B, int K=1, bool Done = ((A*K)%B)==0, bool Big=(A>=B)>
721 struct meta_least_common_multiple
722 {
723   enum { ret = meta_least_common_multiple<A,B,K+1>::ret };
724 };
725 template<int A, int B, int K, bool Done>
726 struct meta_least_common_multiple<A,B,K,Done,false>
727 {
728   enum { ret = meta_least_common_multiple<B,A,K>::ret };
729 };
730 template<int A, int B, int K>
731 struct meta_least_common_multiple<A,B,K,true,true>
732 {
733   enum { ret = A*K };
734 };
735 
736 
737 /** \internal determines whether the product of two numeric types is allowed and what the return type is */
738 template<typename T, typename U> struct scalar_product_traits
739 {
740   enum { Defined = 0 };
741 };
742 
743 // FIXME quick workaround around current limitation of result_of
744 // template<typename Scalar, typename ArgType0, typename ArgType1>
745 // struct result_of<scalar_product_op<Scalar>(ArgType0,ArgType1)> {
746 // typedef typename scalar_product_traits<typename remove_all<ArgType0>::type, typename remove_all<ArgType1>::type>::ReturnType type;
747 // };
748 
749 /** \internal Obtains a POD type suitable to use as storage for an object of a size
750   * of at most Len bytes, aligned as specified by \c Align.
751   */
752 template<unsigned Len, unsigned Align>
753 struct aligned_storage {
754   struct type {
755     EIGEN_ALIGN_TO_BOUNDARY(Align) unsigned char data[Len];
756   };
757 };
758 
759 } // end namespace internal
760 
761 namespace numext {
762 
763 #if defined(EIGEN_GPU_COMPILE_PHASE)
764 template<typename T> EIGEN_DEVICE_FUNC   void swap(T &a, T &b) { T tmp = b; b = a; a = tmp; }
765 #else
766 template<typename T> EIGEN_STRONG_INLINE void swap(T &a, T &b) { std::swap(a,b); }
767 #endif
768 
769 #if defined(EIGEN_GPU_COMPILE_PHASE) && !EIGEN_HAS_CXX11
770 using internal::device::numeric_limits;
771 #else
772 using std::numeric_limits;
773 #endif
774 
775 // Integer division with rounding up.
776 // T is assumed to be an integer type with a>=0, and b>0
777 template<typename T>
778 EIGEN_DEVICE_FUNC
779 T div_ceil(const T &a, const T &b)
780 {
781   return (a+b-1) / b;
782 }
783 
784 // The aim of the following functions is to bypass -Wfloat-equal warnings
785 // when we really want a strict equality comparison on floating points.
786 template<typename X, typename Y> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
787 bool equal_strict(const X& x,const Y& y) { return x == y; }
788 
789 #if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
790 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
791 bool equal_strict(const float& x,const float& y) { return std::equal_to<float>()(x,y); }
792 
793 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
794 bool equal_strict(const double& x,const double& y) { return std::equal_to<double>()(x,y); }
795 #endif
796 
797 template<typename X, typename Y> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
798 bool not_equal_strict(const X& x,const Y& y) { return x != y; }
799 
800 #if !defined(EIGEN_GPU_COMPILE_PHASE) || (!defined(EIGEN_CUDA_ARCH) && defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
801 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
802 bool not_equal_strict(const float& x,const float& y) { return std::not_equal_to<float>()(x,y); }
803 
804 template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC
805 bool not_equal_strict(const double& x,const double& y) { return std::not_equal_to<double>()(x,y); }
806 #endif
807 
808 } // end namespace numext
809 
810 } // end namespace Eigen
811 
812 #endif // EIGEN_META_H
813