Home | History | Annotate | Download | only in Core
      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 (at) 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_MATHFUNCTIONS_H
     11 #define EIGEN_MATHFUNCTIONS_H
     12 
     13 namespace Eigen {
     14 
     15 namespace internal {
     16 
     17 /** \internal \struct global_math_functions_filtering_base
     18   *
     19   * What it does:
     20   * Defines a typedef 'type' as follows:
     21   * - if type T has a member typedef Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then
     22   *   global_math_functions_filtering_base<T>::type is a typedef for it.
     23   * - otherwise, global_math_functions_filtering_base<T>::type is a typedef for T.
     24   *
     25   * How it's used:
     26   * To allow to defined the global math functions (like sin...) in certain cases, like the Array expressions.
     27   * When you do sin(array1+array2), the object array1+array2 has a complicated expression type, all what you want to know
     28   * is that it inherits ArrayBase. So we implement a partial specialization of sin_impl for ArrayBase<Derived>.
     29   * So we must make sure to use sin_impl<ArrayBase<Derived> > and not sin_impl<Derived>, otherwise our partial specialization
     30   * won't be used. How does sin know that? That's exactly what global_math_functions_filtering_base tells it.
     31   *
     32   * How it's implemented:
     33   * SFINAE in the style of enable_if. Highly susceptible of breaking compilers. With GCC, it sure does work, but if you replace
     34   * the typename dummy by an integer template parameter, it doesn't work anymore!
     35   */
     36 
     37 template<typename T, typename dummy = void>
     38 struct global_math_functions_filtering_base
     39 {
     40   typedef T type;
     41 };
     42 
     43 template<typename T> struct always_void { typedef void type; };
     44 
     45 template<typename T>
     46 struct global_math_functions_filtering_base
     47   <T,
     48    typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type
     49   >
     50 {
     51   typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type;
     52 };
     53 
     54 #define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>
     55 #define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type
     56 
     57 /****************************************************************************
     58 * Implementation of real                                                 *
     59 ****************************************************************************/
     60 
     61 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
     62 struct real_default_impl
     63 {
     64   typedef typename NumTraits<Scalar>::Real RealScalar;
     65   static inline RealScalar run(const Scalar& x)
     66   {
     67     return x;
     68   }
     69 };
     70 
     71 template<typename Scalar>
     72 struct real_default_impl<Scalar,true>
     73 {
     74   typedef typename NumTraits<Scalar>::Real RealScalar;
     75   static inline RealScalar run(const Scalar& x)
     76   {
     77     using std::real;
     78     return real(x);
     79   }
     80 };
     81 
     82 template<typename Scalar> struct real_impl : real_default_impl<Scalar> {};
     83 
     84 template<typename Scalar>
     85 struct real_retval
     86 {
     87   typedef typename NumTraits<Scalar>::Real type;
     88 };
     89 
     90 
     91 /****************************************************************************
     92 * Implementation of imag                                                 *
     93 ****************************************************************************/
     94 
     95 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
     96 struct imag_default_impl
     97 {
     98   typedef typename NumTraits<Scalar>::Real RealScalar;
     99   static inline RealScalar run(const Scalar&)
    100   {
    101     return RealScalar(0);
    102   }
    103 };
    104 
    105 template<typename Scalar>
    106 struct imag_default_impl<Scalar,true>
    107 {
    108   typedef typename NumTraits<Scalar>::Real RealScalar;
    109   static inline RealScalar run(const Scalar& x)
    110   {
    111     using std::imag;
    112     return imag(x);
    113   }
    114 };
    115 
    116 template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {};
    117 
    118 template<typename Scalar>
    119 struct imag_retval
    120 {
    121   typedef typename NumTraits<Scalar>::Real type;
    122 };
    123 
    124 /****************************************************************************
    125 * Implementation of real_ref                                             *
    126 ****************************************************************************/
    127 
    128 template<typename Scalar>
    129 struct real_ref_impl
    130 {
    131   typedef typename NumTraits<Scalar>::Real RealScalar;
    132   static inline RealScalar& run(Scalar& x)
    133   {
    134     return reinterpret_cast<RealScalar*>(&x)[0];
    135   }
    136   static inline const RealScalar& run(const Scalar& x)
    137   {
    138     return reinterpret_cast<const RealScalar*>(&x)[0];
    139   }
    140 };
    141 
    142 template<typename Scalar>
    143 struct real_ref_retval
    144 {
    145   typedef typename NumTraits<Scalar>::Real & type;
    146 };
    147 
    148 /****************************************************************************
    149 * Implementation of imag_ref                                             *
    150 ****************************************************************************/
    151 
    152 template<typename Scalar, bool IsComplex>
    153 struct imag_ref_default_impl
    154 {
    155   typedef typename NumTraits<Scalar>::Real RealScalar;
    156   static inline RealScalar& run(Scalar& x)
    157   {
    158     return reinterpret_cast<RealScalar*>(&x)[1];
    159   }
    160   static inline const RealScalar& run(const Scalar& x)
    161   {
    162     return reinterpret_cast<RealScalar*>(&x)[1];
    163   }
    164 };
    165 
    166 template<typename Scalar>
    167 struct imag_ref_default_impl<Scalar, false>
    168 {
    169   static inline Scalar run(Scalar&)
    170   {
    171     return Scalar(0);
    172   }
    173   static inline const Scalar run(const Scalar&)
    174   {
    175     return Scalar(0);
    176   }
    177 };
    178 
    179 template<typename Scalar>
    180 struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {};
    181 
    182 template<typename Scalar>
    183 struct imag_ref_retval
    184 {
    185   typedef typename NumTraits<Scalar>::Real & type;
    186 };
    187 
    188 /****************************************************************************
    189 * Implementation of conj                                                 *
    190 ****************************************************************************/
    191 
    192 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
    193 struct conj_impl
    194 {
    195   static inline Scalar run(const Scalar& x)
    196   {
    197     return x;
    198   }
    199 };
    200 
    201 template<typename Scalar>
    202 struct conj_impl<Scalar,true>
    203 {
    204   static inline Scalar run(const Scalar& x)
    205   {
    206     using std::conj;
    207     return conj(x);
    208   }
    209 };
    210 
    211 template<typename Scalar>
    212 struct conj_retval
    213 {
    214   typedef Scalar type;
    215 };
    216 
    217 /****************************************************************************
    218 * Implementation of abs2                                                 *
    219 ****************************************************************************/
    220 
    221 template<typename Scalar>
    222 struct abs2_impl
    223 {
    224   typedef typename NumTraits<Scalar>::Real RealScalar;
    225   static inline RealScalar run(const Scalar& x)
    226   {
    227     return x*x;
    228   }
    229 };
    230 
    231 template<typename RealScalar>
    232 struct abs2_impl<std::complex<RealScalar> >
    233 {
    234   static inline RealScalar run(const std::complex<RealScalar>& x)
    235   {
    236     return real(x)*real(x) + imag(x)*imag(x);
    237   }
    238 };
    239 
    240 template<typename Scalar>
    241 struct abs2_retval
    242 {
    243   typedef typename NumTraits<Scalar>::Real type;
    244 };
    245 
    246 /****************************************************************************
    247 * Implementation of norm1                                                *
    248 ****************************************************************************/
    249 
    250 template<typename Scalar, bool IsComplex>
    251 struct norm1_default_impl
    252 {
    253   typedef typename NumTraits<Scalar>::Real RealScalar;
    254   static inline RealScalar run(const Scalar& x)
    255   {
    256     using std::abs;
    257     return abs(real(x)) + abs(imag(x));
    258   }
    259 };
    260 
    261 template<typename Scalar>
    262 struct norm1_default_impl<Scalar, false>
    263 {
    264   static inline Scalar run(const Scalar& x)
    265   {
    266     using std::abs;
    267     return abs(x);
    268   }
    269 };
    270 
    271 template<typename Scalar>
    272 struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {};
    273 
    274 template<typename Scalar>
    275 struct norm1_retval
    276 {
    277   typedef typename NumTraits<Scalar>::Real type;
    278 };
    279 
    280 /****************************************************************************
    281 * Implementation of hypot                                                *
    282 ****************************************************************************/
    283 
    284 template<typename Scalar>
    285 struct hypot_impl
    286 {
    287   typedef typename NumTraits<Scalar>::Real RealScalar;
    288   static inline RealScalar run(const Scalar& x, const Scalar& y)
    289   {
    290     using std::max;
    291     using std::min;
    292     using std::abs;
    293     using std::sqrt;
    294     RealScalar _x = abs(x);
    295     RealScalar _y = abs(y);
    296     RealScalar p = (max)(_x, _y);
    297     if(p==RealScalar(0)) return 0;
    298     RealScalar q = (min)(_x, _y);
    299     RealScalar qp = q/p;
    300     return p * sqrt(RealScalar(1) + qp*qp);
    301   }
    302 };
    303 
    304 template<typename Scalar>
    305 struct hypot_retval
    306 {
    307   typedef typename NumTraits<Scalar>::Real type;
    308 };
    309 
    310 /****************************************************************************
    311 * Implementation of cast                                                 *
    312 ****************************************************************************/
    313 
    314 template<typename OldType, typename NewType>
    315 struct cast_impl
    316 {
    317   static inline NewType run(const OldType& x)
    318   {
    319     return static_cast<NewType>(x);
    320   }
    321 };
    322 
    323 // here, for once, we're plainly returning NewType: we don't want cast to do weird things.
    324 
    325 template<typename OldType, typename NewType>
    326 inline NewType cast(const OldType& x)
    327 {
    328   return cast_impl<OldType, NewType>::run(x);
    329 }
    330 
    331 /****************************************************************************
    332 * Implementation of atanh2                                                *
    333 ****************************************************************************/
    334 
    335 template<typename Scalar, bool IsInteger>
    336 struct atanh2_default_impl
    337 {
    338   typedef Scalar retval;
    339   typedef typename NumTraits<Scalar>::Real RealScalar;
    340   static inline Scalar run(const Scalar& x, const Scalar& y)
    341   {
    342     using std::abs;
    343     using std::log;
    344     using std::sqrt;
    345     Scalar z = x / y;
    346     if (y == Scalar(0) || abs(z) > sqrt(NumTraits<RealScalar>::epsilon()))
    347       return RealScalar(0.5) * log((y + x) / (y - x));
    348     else
    349       return z + z*z*z / RealScalar(3);
    350   }
    351 };
    352 
    353 template<typename Scalar>
    354 struct atanh2_default_impl<Scalar, true>
    355 {
    356   static inline Scalar run(const Scalar&, const Scalar&)
    357   {
    358     EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
    359     return Scalar(0);
    360   }
    361 };
    362 
    363 template<typename Scalar>
    364 struct atanh2_impl : atanh2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
    365 
    366 template<typename Scalar>
    367 struct atanh2_retval
    368 {
    369   typedef Scalar type;
    370 };
    371 
    372 /****************************************************************************
    373 * Implementation of pow                                                  *
    374 ****************************************************************************/
    375 
    376 template<typename Scalar, bool IsInteger>
    377 struct pow_default_impl
    378 {
    379   typedef Scalar retval;
    380   static inline Scalar run(const Scalar& x, const Scalar& y)
    381   {
    382     using std::pow;
    383     return pow(x, y);
    384   }
    385 };
    386 
    387 template<typename Scalar>
    388 struct pow_default_impl<Scalar, true>
    389 {
    390   static inline Scalar run(Scalar x, Scalar y)
    391   {
    392     Scalar res(1);
    393     eigen_assert(!NumTraits<Scalar>::IsSigned || y >= 0);
    394     if(y & 1) res *= x;
    395     y >>= 1;
    396     while(y)
    397     {
    398       x *= x;
    399       if(y&1) res *= x;
    400       y >>= 1;
    401     }
    402     return res;
    403   }
    404 };
    405 
    406 template<typename Scalar>
    407 struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
    408 
    409 template<typename Scalar>
    410 struct pow_retval
    411 {
    412   typedef Scalar type;
    413 };
    414 
    415 /****************************************************************************
    416 * Implementation of random                                               *
    417 ****************************************************************************/
    418 
    419 template<typename Scalar,
    420          bool IsComplex,
    421          bool IsInteger>
    422 struct random_default_impl {};
    423 
    424 template<typename Scalar>
    425 struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
    426 
    427 template<typename Scalar>
    428 struct random_retval
    429 {
    430   typedef Scalar type;
    431 };
    432 
    433 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y);
    434 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random();
    435 
    436 template<typename Scalar>
    437 struct random_default_impl<Scalar, false, false>
    438 {
    439   static inline Scalar run(const Scalar& x, const Scalar& y)
    440   {
    441     return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX);
    442   }
    443   static inline Scalar run()
    444   {
    445     return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1));
    446   }
    447 };
    448 
    449 enum {
    450   floor_log2_terminate,
    451   floor_log2_move_up,
    452   floor_log2_move_down,
    453   floor_log2_bogus
    454 };
    455 
    456 template<unsigned int n, int lower, int upper> struct floor_log2_selector
    457 {
    458   enum { middle = (lower + upper) / 2,
    459          value = (upper <= lower + 1) ? int(floor_log2_terminate)
    460                : (n < (1 << middle)) ? int(floor_log2_move_down)
    461                : (n==0) ? int(floor_log2_bogus)
    462                : int(floor_log2_move_up)
    463   };
    464 };
    465 
    466 template<unsigned int n,
    467          int lower = 0,
    468          int upper = sizeof(unsigned int) * CHAR_BIT - 1,
    469          int selector = floor_log2_selector<n, lower, upper>::value>
    470 struct floor_log2 {};
    471 
    472 template<unsigned int n, int lower, int upper>
    473 struct floor_log2<n, lower, upper, floor_log2_move_down>
    474 {
    475   enum { value = floor_log2<n, lower, floor_log2_selector<n, lower, upper>::middle>::value };
    476 };
    477 
    478 template<unsigned int n, int lower, int upper>
    479 struct floor_log2<n, lower, upper, floor_log2_move_up>
    480 {
    481   enum { value = floor_log2<n, floor_log2_selector<n, lower, upper>::middle, upper>::value };
    482 };
    483 
    484 template<unsigned int n, int lower, int upper>
    485 struct floor_log2<n, lower, upper, floor_log2_terminate>
    486 {
    487   enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower };
    488 };
    489 
    490 template<unsigned int n, int lower, int upper>
    491 struct floor_log2<n, lower, upper, floor_log2_bogus>
    492 {
    493   // no value, error at compile time
    494 };
    495 
    496 template<typename Scalar>
    497 struct random_default_impl<Scalar, false, true>
    498 {
    499   typedef typename NumTraits<Scalar>::NonInteger NonInteger;
    500 
    501   static inline Scalar run(const Scalar& x, const Scalar& y)
    502   {
    503     return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1)));
    504   }
    505 
    506   static inline Scalar run()
    507   {
    508 #ifdef EIGEN_MAKING_DOCS
    509     return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10));
    510 #else
    511     enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value,
    512            scalar_bits = sizeof(Scalar) * CHAR_BIT,
    513            shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)),
    514            offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0
    515     };
    516     return Scalar((std::rand() >> shift) - offset);
    517 #endif
    518   }
    519 };
    520 
    521 template<typename Scalar>
    522 struct random_default_impl<Scalar, true, false>
    523 {
    524   static inline Scalar run(const Scalar& x, const Scalar& y)
    525   {
    526     return Scalar(random(real(x), real(y)),
    527                   random(imag(x), imag(y)));
    528   }
    529   static inline Scalar run()
    530   {
    531     typedef typename NumTraits<Scalar>::Real RealScalar;
    532     return Scalar(random<RealScalar>(), random<RealScalar>());
    533   }
    534 };
    535 
    536 template<typename Scalar>
    537 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y)
    538 {
    539   return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y);
    540 }
    541 
    542 template<typename Scalar>
    543 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
    544 {
    545   return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
    546 }
    547 
    548 } // end namespace internal
    549 
    550 /****************************************************************************
    551 * Generic math function                                                    *
    552 ****************************************************************************/
    553 
    554 namespace numext {
    555 
    556 template<typename Scalar>
    557 inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
    558 {
    559   return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
    560 }
    561 
    562 template<typename Scalar>
    563 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
    564 {
    565   return internal::real_ref_impl<Scalar>::run(x);
    566 }
    567 
    568 template<typename Scalar>
    569 inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
    570 {
    571   return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
    572 }
    573 
    574 template<typename Scalar>
    575 inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
    576 {
    577   return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
    578 }
    579 
    580 template<typename Scalar>
    581 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
    582 {
    583   return internal::imag_ref_impl<Scalar>::run(x);
    584 }
    585 
    586 template<typename Scalar>
    587 inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
    588 {
    589   return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
    590 }
    591 
    592 template<typename Scalar>
    593 inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
    594 {
    595   return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
    596 }
    597 
    598 template<typename Scalar>
    599 inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
    600 {
    601   return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
    602 }
    603 
    604 template<typename Scalar>
    605 inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
    606 {
    607   return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
    608 }
    609 
    610 template<typename Scalar>
    611 inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
    612 {
    613   return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
    614 }
    615 
    616 template<typename Scalar>
    617 inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y)
    618 {
    619   return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y);
    620 }
    621 
    622 template<typename Scalar>
    623 inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
    624 {
    625   return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
    626 }
    627 
    628 // std::isfinite is non standard, so let's define our own version,
    629 // even though it is not very efficient.
    630 template<typename T> bool (isfinite)(const T& x)
    631 {
    632   return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
    633 }
    634 
    635 } // end namespace numext
    636 
    637 namespace internal {
    638 
    639 /****************************************************************************
    640 * Implementation of fuzzy comparisons                                       *
    641 ****************************************************************************/
    642 
    643 template<typename Scalar,
    644          bool IsComplex,
    645          bool IsInteger>
    646 struct scalar_fuzzy_default_impl {};
    647 
    648 template<typename Scalar>
    649 struct scalar_fuzzy_default_impl<Scalar, false, false>
    650 {
    651   typedef typename NumTraits<Scalar>::Real RealScalar;
    652   template<typename OtherScalar>
    653   static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
    654   {
    655     using std::abs;
    656     return abs(x) <= abs(y) * prec;
    657   }
    658   static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
    659   {
    660     using std::min;
    661     using std::abs;
    662     return abs(x - y) <= (min)(abs(x), abs(y)) * prec;
    663   }
    664   static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
    665   {
    666     return x <= y || isApprox(x, y, prec);
    667   }
    668 };
    669 
    670 template<typename Scalar>
    671 struct scalar_fuzzy_default_impl<Scalar, false, true>
    672 {
    673   typedef typename NumTraits<Scalar>::Real RealScalar;
    674   template<typename OtherScalar>
    675   static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&)
    676   {
    677     return x == Scalar(0);
    678   }
    679   static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&)
    680   {
    681     return x == y;
    682   }
    683   static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&)
    684   {
    685     return x <= y;
    686   }
    687 };
    688 
    689 template<typename Scalar>
    690 struct scalar_fuzzy_default_impl<Scalar, true, false>
    691 {
    692   typedef typename NumTraits<Scalar>::Real RealScalar;
    693   template<typename OtherScalar>
    694   static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
    695   {
    696     return numext::abs2(x) <= numext::abs2(y) * prec * prec;
    697   }
    698   static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
    699   {
    700     using std::min;
    701     return numext::abs2(x - y) <= (min)(numext::abs2(x), numext::abs2(y)) * prec * prec;
    702   }
    703 };
    704 
    705 template<typename Scalar>
    706 struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
    707 
    708 template<typename Scalar, typename OtherScalar>
    709 inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
    710                                    typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
    711 {
    712   return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
    713 }
    714 
    715 template<typename Scalar>
    716 inline bool isApprox(const Scalar& x, const Scalar& y,
    717                           typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
    718 {
    719   return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
    720 }
    721 
    722 template<typename Scalar>
    723 inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
    724                                     typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
    725 {
    726   return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
    727 }
    728 
    729 /******************************************
    730 ***  The special case of the  bool type ***
    731 ******************************************/
    732 
    733 template<> struct random_impl<bool>
    734 {
    735   static inline bool run()
    736   {
    737     return random<int>(0,1)==0 ? false : true;
    738   }
    739 };
    740 
    741 template<> struct scalar_fuzzy_impl<bool>
    742 {
    743   typedef bool RealScalar;
    744 
    745   template<typename OtherScalar>
    746   static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&)
    747   {
    748     return !x;
    749   }
    750 
    751   static inline bool isApprox(bool x, bool y, bool)
    752   {
    753     return x == y;
    754   }
    755 
    756   static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&)
    757   {
    758     return (!x) || y;
    759   }
    760 
    761 };
    762 
    763 
    764 } // end namespace internal
    765 
    766 } // end namespace Eigen
    767 
    768 #endif // EIGEN_MATHFUNCTIONS_H
    769