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