cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

NumTraits.h (12884B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #ifndef EIGEN_NUMTRAITS_H
     11 #define EIGEN_NUMTRAITS_H
     12 
     13 namespace Eigen {
     14 
     15 namespace internal {
     16 
     17 // default implementation of digits10(), based on numeric_limits if specialized,
     18 // 0 for integer types, and log10(epsilon()) otherwise.
     19 template< typename T,
     20           bool use_numeric_limits = std::numeric_limits<T>::is_specialized,
     21           bool is_integer = NumTraits<T>::IsInteger>
     22 struct default_digits10_impl
     23 {
     24   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
     25   static int run() { return std::numeric_limits<T>::digits10; }
     26 };
     27 
     28 template<typename T>
     29 struct default_digits10_impl<T,false,false> // Floating point
     30 {
     31   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
     32   static int run() {
     33     using std::log10;
     34     using std::ceil;
     35     typedef typename NumTraits<T>::Real Real;
     36     return int(ceil(-log10(NumTraits<Real>::epsilon())));
     37   }
     38 };
     39 
     40 template<typename T>
     41 struct default_digits10_impl<T,false,true> // Integer
     42 {
     43   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
     44   static int run() { return 0; }
     45 };
     46 
     47 
     48 // default implementation of digits(), based on numeric_limits if specialized,
     49 // 0 for integer types, and log2(epsilon()) otherwise.
     50 template< typename T,
     51           bool use_numeric_limits = std::numeric_limits<T>::is_specialized,
     52           bool is_integer = NumTraits<T>::IsInteger>
     53 struct default_digits_impl
     54 {
     55   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
     56   static int run() { return std::numeric_limits<T>::digits; }
     57 };
     58 
     59 template<typename T>
     60 struct default_digits_impl<T,false,false> // Floating point
     61 {
     62   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
     63   static int run() {
     64     using std::log;
     65     using std::ceil;
     66     typedef typename NumTraits<T>::Real Real;
     67     return int(ceil(-log(NumTraits<Real>::epsilon())/log(static_cast<Real>(2))));
     68   }
     69 };
     70 
     71 template<typename T>
     72 struct default_digits_impl<T,false,true> // Integer
     73 {
     74   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
     75   static int run() { return 0; }
     76 };
     77 
     78 } // end namespace internal
     79 
     80 namespace numext {
     81 /** \internal bit-wise cast without changing the underlying bit representation. */
     82 
     83 // TODO: Replace by std::bit_cast (available in C++20)
     84 template <typename Tgt, typename Src>
     85 EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Tgt bit_cast(const Src& src) {
     86 #if EIGEN_HAS_TYPE_TRAITS
     87   // The behaviour of memcpy is not specified for non-trivially copyable types
     88   EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Src>::value, THIS_TYPE_IS_NOT_SUPPORTED);
     89   EIGEN_STATIC_ASSERT(std::is_trivially_copyable<Tgt>::value && std::is_default_constructible<Tgt>::value,
     90                       THIS_TYPE_IS_NOT_SUPPORTED);
     91 #endif
     92 
     93   EIGEN_STATIC_ASSERT(sizeof(Src) == sizeof(Tgt), THIS_TYPE_IS_NOT_SUPPORTED);
     94   Tgt tgt;
     95   EIGEN_USING_STD(memcpy)
     96   memcpy(&tgt, &src, sizeof(Tgt));
     97   return tgt;
     98 }
     99 }  // namespace numext
    100 
    101 /** \class NumTraits
    102   * \ingroup Core_Module
    103   *
    104   * \brief Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
    105   *
    106   * \tparam T the numeric type at hand
    107   *
    108   * This class stores enums, typedefs and static methods giving information about a numeric type.
    109   *
    110   * The provided data consists of:
    111   * \li A typedef \c Real, giving the "real part" type of \a T. If \a T is already real,
    112   *     then \c Real is just a typedef to \a T. If \a T is \c std::complex<U> then \c Real
    113   *     is a typedef to \a U.
    114   * \li A typedef \c NonInteger, giving the type that should be used for operations producing non-integral values,
    115   *     such as quotients, square roots, etc. If \a T is a floating-point type, then this typedef just gives
    116   *     \a T again. Note however that many Eigen functions such as internal::sqrt simply refuse to
    117   *     take integers. Outside of a few cases, Eigen doesn't do automatic type promotion. Thus, this typedef is
    118   *     only intended as a helper for code that needs to explicitly promote types.
    119   * \li A typedef \c Literal giving the type to use for numeric literals such as "2" or "0.5". For instance, for \c std::complex<U>, Literal is defined as \c U.
    120   *     Of course, this type must be fully compatible with \a T. In doubt, just use \a T here.
    121   * \li A typedef \a Nested giving the type to use to nest a value inside of the expression tree. If you don't know what
    122   *     this means, just use \a T here.
    123   * \li An enum value \a IsComplex. It is equal to 1 if \a T is a \c std::complex
    124   *     type, and to 0 otherwise.
    125   * \li An enum value \a IsInteger. It is equal to \c 1 if \a T is an integer type such as \c int,
    126   *     and to \c 0 otherwise.
    127   * \li Enum values ReadCost, AddCost and MulCost representing a rough estimate of the number of CPU cycles needed
    128   *     to by move / add / mul instructions respectively, assuming the data is already stored in CPU registers.
    129   *     Stay vague here. No need to do architecture-specific stuff. If you don't know what this means, just use \c Eigen::HugeCost.
    130   * \li An enum value \a IsSigned. It is equal to \c 1 if \a T is a signed type and to 0 if \a T is unsigned.
    131   * \li An enum value \a RequireInitialization. It is equal to \c 1 if the constructor of the numeric type \a T must
    132   *     be called, and to 0 if it is safe not to call it. Default is 0 if \a T is an arithmetic type, and 1 otherwise.
    133   * \li An epsilon() function which, unlike <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/epsilon">std::numeric_limits::epsilon()</a>,
    134   *     it returns a \a Real instead of a \a T.
    135   * \li A dummy_precision() function returning a weak epsilon value. It is mainly used as a default
    136   *     value by the fuzzy comparison operators.
    137   * \li highest() and lowest() functions returning the highest and lowest possible values respectively.
    138   * \li digits() function returning the number of radix digits (non-sign digits for integers, mantissa for floating-point). This is
    139   *     the analogue of <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits">std::numeric_limits<T>::digits</a>
    140   *     which is used as the default implementation if specialized.
    141   * \li digits10() function returning the number of decimal digits that can be represented without change. This is
    142   *     the analogue of <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/digits10">std::numeric_limits<T>::digits10</a>
    143   *     which is used as the default implementation if specialized.
    144   * \li min_exponent() and max_exponent() functions returning the highest and lowest possible values, respectively,
    145   *     such that the radix raised to the power exponent-1 is a normalized floating-point number.  These are equivalent to
    146   *     <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/min_exponent">std::numeric_limits<T>::min_exponent</a>/
    147   *     <a href="http://en.cppreference.com/w/cpp/types/numeric_limits/max_exponent">std::numeric_limits<T>::max_exponent</a>.
    148   * \li infinity() function returning a representation of positive infinity, if available.
    149   * \li quiet_NaN function returning a non-signaling "not-a-number", if available.
    150   */
    151 
    152 template<typename T> struct GenericNumTraits
    153 {
    154   enum {
    155     IsInteger = std::numeric_limits<T>::is_integer,
    156     IsSigned = std::numeric_limits<T>::is_signed,
    157     IsComplex = 0,
    158     RequireInitialization = internal::is_arithmetic<T>::value ? 0 : 1,
    159     ReadCost = 1,
    160     AddCost = 1,
    161     MulCost = 1
    162   };
    163 
    164   typedef T Real;
    165   typedef typename internal::conditional<
    166                      IsInteger,
    167                      typename internal::conditional<sizeof(T)<=2, float, double>::type,
    168                      T
    169                    >::type NonInteger;
    170   typedef T Nested;
    171   typedef T Literal;
    172 
    173   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    174   static inline Real epsilon()
    175   {
    176     return numext::numeric_limits<T>::epsilon();
    177   }
    178 
    179   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    180   static inline int digits10()
    181   {
    182     return internal::default_digits10_impl<T>::run();
    183   }
    184 
    185   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    186   static inline int digits()
    187   {
    188     return internal::default_digits_impl<T>::run();
    189   }
    190 
    191   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    192   static inline int min_exponent()
    193   {
    194     return numext::numeric_limits<T>::min_exponent;
    195   }
    196 
    197   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    198   static inline int max_exponent()
    199   {
    200     return numext::numeric_limits<T>::max_exponent;
    201   }
    202 
    203   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    204   static inline Real dummy_precision()
    205   {
    206     // make sure to override this for floating-point types
    207     return Real(0);
    208   }
    209 
    210   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    211   static inline T highest() {
    212     return (numext::numeric_limits<T>::max)();
    213   }
    214 
    215   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    216   static inline T lowest()  {
    217     return IsInteger ? (numext::numeric_limits<T>::min)()
    218                      : static_cast<T>(-(numext::numeric_limits<T>::max)());
    219   }
    220 
    221   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    222   static inline T infinity() {
    223     return numext::numeric_limits<T>::infinity();
    224   }
    225 
    226   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    227   static inline T quiet_NaN() {
    228     return numext::numeric_limits<T>::quiet_NaN();
    229   }
    230 };
    231 
    232 template<typename T> struct NumTraits : GenericNumTraits<T>
    233 {};
    234 
    235 template<> struct NumTraits<float>
    236   : GenericNumTraits<float>
    237 {
    238   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    239   static inline float dummy_precision() { return 1e-5f; }
    240 };
    241 
    242 template<> struct NumTraits<double> : GenericNumTraits<double>
    243 {
    244   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    245   static inline double dummy_precision() { return 1e-12; }
    246 };
    247 
    248 template<> struct NumTraits<long double>
    249   : GenericNumTraits<long double>
    250 {
    251   EIGEN_CONSTEXPR
    252   static inline long double dummy_precision() { return 1e-15l; }
    253 };
    254 
    255 template<typename _Real> struct NumTraits<std::complex<_Real> >
    256   : GenericNumTraits<std::complex<_Real> >
    257 {
    258   typedef _Real Real;
    259   typedef typename NumTraits<_Real>::Literal Literal;
    260   enum {
    261     IsComplex = 1,
    262     RequireInitialization = NumTraits<_Real>::RequireInitialization,
    263     ReadCost = 2 * NumTraits<_Real>::ReadCost,
    264     AddCost = 2 * NumTraits<Real>::AddCost,
    265     MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
    266   };
    267 
    268   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    269   static inline Real epsilon() { return NumTraits<Real>::epsilon(); }
    270   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    271   static inline Real dummy_precision() { return NumTraits<Real>::dummy_precision(); }
    272   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    273   static inline int digits10() { return NumTraits<Real>::digits10(); }
    274 };
    275 
    276 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    277 struct NumTraits<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
    278 {
    279   typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> ArrayType;
    280   typedef typename NumTraits<Scalar>::Real RealScalar;
    281   typedef Array<RealScalar, Rows, Cols, Options, MaxRows, MaxCols> Real;
    282   typedef typename NumTraits<Scalar>::NonInteger NonIntegerScalar;
    283   typedef Array<NonIntegerScalar, Rows, Cols, Options, MaxRows, MaxCols> NonInteger;
    284   typedef ArrayType & Nested;
    285   typedef typename NumTraits<Scalar>::Literal Literal;
    286 
    287   enum {
    288     IsComplex = NumTraits<Scalar>::IsComplex,
    289     IsInteger = NumTraits<Scalar>::IsInteger,
    290     IsSigned  = NumTraits<Scalar>::IsSigned,
    291     RequireInitialization = 1,
    292     ReadCost = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::ReadCost),
    293     AddCost  = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::AddCost),
    294     MulCost  = ArrayType::SizeAtCompileTime==Dynamic ? HugeCost : ArrayType::SizeAtCompileTime * int(NumTraits<Scalar>::MulCost)
    295   };
    296 
    297   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    298   static inline RealScalar epsilon() { return NumTraits<RealScalar>::epsilon(); }
    299   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
    300   static inline RealScalar dummy_precision() { return NumTraits<RealScalar>::dummy_precision(); }
    301 
    302   EIGEN_CONSTEXPR
    303   static inline int digits10() { return NumTraits<Scalar>::digits10(); }
    304 };
    305 
    306 template<> struct NumTraits<std::string>
    307   : GenericNumTraits<std::string>
    308 {
    309   enum {
    310     RequireInitialization = 1,
    311     ReadCost = HugeCost,
    312     AddCost  = HugeCost,
    313     MulCost  = HugeCost
    314   };
    315 
    316   EIGEN_CONSTEXPR
    317   static inline int digits10() { return 0; }
    318 
    319 private:
    320   static inline std::string epsilon();
    321   static inline std::string dummy_precision();
    322   static inline std::string lowest();
    323   static inline std::string highest();
    324   static inline std::string infinity();
    325   static inline std::string quiet_NaN();
    326 };
    327 
    328 // Empty specialization for void to allow template specialization based on NumTraits<T>::Real with T==void and SFINAE.
    329 template<> struct NumTraits<void> {};
    330 
    331 template<> struct NumTraits<bool> : GenericNumTraits<bool> {};
    332 
    333 } // end namespace Eigen
    334 
    335 #endif // EIGEN_NUMTRAITS_H