Eigne Matrix Class Library
Dependents: Eigen_test Odometry_test AttitudeEstimation_usingTicker MPU9250_Quaternion_Binary_Serial ... more
MathFunctions.h
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> 00005 // 00006 // This Source Code Form is subject to the terms of the Mozilla 00007 // Public License v. 2.0. If a copy of the MPL was not distributed 00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00009 00010 #ifndef EIGEN_MATHFUNCTIONS_H 00011 #define EIGEN_MATHFUNCTIONS_H 00012 00013 namespace Eigen { 00014 00015 namespace internal { 00016 00017 /** \internal \struct global_math_functions_filtering_base 00018 * 00019 * What it does: 00020 * Defines a typedef 'type' as follows: 00021 * - if type T has a member typedef Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then 00022 * global_math_functions_filtering_base<T>::type is a typedef for it. 00023 * - otherwise, global_math_functions_filtering_base<T>::type is a typedef for T. 00024 * 00025 * How it's used: 00026 * To allow to defined the global math functions (like sin...) in certain cases, like the Array expressions. 00027 * When you do sin(array1+array2), the object array1+array2 has a complicated expression type, all what you want to know 00028 * is that it inherits ArrayBase. So we implement a partial specialization of sin_impl for ArrayBase<Derived>. 00029 * So we must make sure to use sin_impl<ArrayBase<Derived> > and not sin_impl<Derived>, otherwise our partial specialization 00030 * won't be used. How does sin know that? That's exactly what global_math_functions_filtering_base tells it. 00031 * 00032 * How it's implemented: 00033 * SFINAE in the style of enable_if. Highly susceptible of breaking compilers. With GCC, it sure does work, but if you replace 00034 * the typename dummy by an integer template parameter, it doesn't work anymore! 00035 */ 00036 00037 template<typename T, typename dummy = void> 00038 struct global_math_functions_filtering_base 00039 { 00040 typedef T type; 00041 }; 00042 00043 template<typename T> struct always_void { typedef void type; }; 00044 00045 template<typename T> 00046 struct global_math_functions_filtering_base 00047 <T, 00048 typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type 00049 > 00050 { 00051 typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type; 00052 }; 00053 00054 #define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type> 00055 #define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type 00056 00057 /**************************************************************************** 00058 * Implementation of real * 00059 ****************************************************************************/ 00060 00061 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> 00062 struct real_default_impl 00063 { 00064 typedef typename NumTraits<Scalar>::Real RealScalar; 00065 static inline RealScalar run(const Scalar& x) 00066 { 00067 return x; 00068 } 00069 }; 00070 00071 template<typename Scalar> 00072 struct real_default_impl<Scalar,true> 00073 { 00074 typedef typename NumTraits<Scalar>::Real RealScalar; 00075 static inline RealScalar run(const Scalar& x) 00076 { 00077 using std::real; 00078 return real(x); 00079 } 00080 }; 00081 00082 template<typename Scalar> struct real_impl : real_default_impl<Scalar> {}; 00083 00084 template<typename Scalar> 00085 struct real_retval 00086 { 00087 typedef typename NumTraits<Scalar>::Real type; 00088 }; 00089 00090 00091 /**************************************************************************** 00092 * Implementation of imag * 00093 ****************************************************************************/ 00094 00095 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> 00096 struct imag_default_impl 00097 { 00098 typedef typename NumTraits<Scalar>::Real RealScalar; 00099 static inline RealScalar run(const Scalar&) 00100 { 00101 return RealScalar(0); 00102 } 00103 }; 00104 00105 template<typename Scalar> 00106 struct imag_default_impl<Scalar,true> 00107 { 00108 typedef typename NumTraits<Scalar>::Real RealScalar; 00109 static inline RealScalar run(const Scalar& x) 00110 { 00111 using std::imag; 00112 return imag(x); 00113 } 00114 }; 00115 00116 template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {}; 00117 00118 template<typename Scalar> 00119 struct imag_retval 00120 { 00121 typedef typename NumTraits<Scalar>::Real type; 00122 }; 00123 00124 /**************************************************************************** 00125 * Implementation of real_ref * 00126 ****************************************************************************/ 00127 00128 template<typename Scalar> 00129 struct real_ref_impl 00130 { 00131 typedef typename NumTraits<Scalar>::Real RealScalar; 00132 static inline RealScalar& run(Scalar& x) 00133 { 00134 return reinterpret_cast<RealScalar*>(&x)[0]; 00135 } 00136 static inline const RealScalar& run(const Scalar& x) 00137 { 00138 return reinterpret_cast<const RealScalar*>(&x)[0]; 00139 } 00140 }; 00141 00142 template<typename Scalar> 00143 struct real_ref_retval 00144 { 00145 typedef typename NumTraits<Scalar>::Real & type; 00146 }; 00147 00148 /**************************************************************************** 00149 * Implementation of imag_ref * 00150 ****************************************************************************/ 00151 00152 template<typename Scalar, bool IsComplex> 00153 struct imag_ref_default_impl 00154 { 00155 typedef typename NumTraits<Scalar>::Real RealScalar; 00156 static inline RealScalar& run(Scalar& x) 00157 { 00158 return reinterpret_cast<RealScalar*>(&x)[1]; 00159 } 00160 static inline const RealScalar& run(const Scalar& x) 00161 { 00162 return reinterpret_cast<RealScalar*>(&x)[1]; 00163 } 00164 }; 00165 00166 template<typename Scalar> 00167 struct imag_ref_default_impl<Scalar, false> 00168 { 00169 static inline Scalar run(Scalar&) 00170 { 00171 return Scalar(0); 00172 } 00173 static inline const Scalar run(const Scalar&) 00174 { 00175 return Scalar(0); 00176 } 00177 }; 00178 00179 template<typename Scalar> 00180 struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 00181 00182 template<typename Scalar> 00183 struct imag_ref_retval 00184 { 00185 typedef typename NumTraits<Scalar>::Real & type; 00186 }; 00187 00188 /**************************************************************************** 00189 * Implementation of conj * 00190 ****************************************************************************/ 00191 00192 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> 00193 struct conj_impl 00194 { 00195 static inline Scalar run(const Scalar& x) 00196 { 00197 return x; 00198 } 00199 }; 00200 00201 template<typename Scalar> 00202 struct conj_impl<Scalar,true> 00203 { 00204 static inline Scalar run(const Scalar& x) 00205 { 00206 using std::conj; 00207 return conj(x); 00208 } 00209 }; 00210 00211 template<typename Scalar> 00212 struct conj_retval 00213 { 00214 typedef Scalar type; 00215 }; 00216 00217 /**************************************************************************** 00218 * Implementation of abs2 * 00219 ****************************************************************************/ 00220 00221 template<typename Scalar> 00222 struct abs2_impl 00223 { 00224 typedef typename NumTraits<Scalar>::Real RealScalar; 00225 static inline RealScalar run(const Scalar& x) 00226 { 00227 return x*x; 00228 } 00229 }; 00230 00231 template<typename RealScalar> 00232 struct abs2_impl<std::complex<RealScalar> > 00233 { 00234 static inline RealScalar run(const std::complex<RealScalar>& x) 00235 { 00236 return real(x)*real(x) + imag(x)*imag(x); 00237 } 00238 }; 00239 00240 template<typename Scalar> 00241 struct abs2_retval 00242 { 00243 typedef typename NumTraits<Scalar>::Real type; 00244 }; 00245 00246 /**************************************************************************** 00247 * Implementation of norm1 * 00248 ****************************************************************************/ 00249 00250 template<typename Scalar, bool IsComplex> 00251 struct norm1_default_impl 00252 { 00253 typedef typename NumTraits<Scalar>::Real RealScalar; 00254 static inline RealScalar run(const Scalar& x) 00255 { 00256 using std::abs; 00257 return abs(real(x)) + abs(imag(x)); 00258 } 00259 }; 00260 00261 template<typename Scalar> 00262 struct norm1_default_impl<Scalar, false> 00263 { 00264 static inline Scalar run(const Scalar& x) 00265 { 00266 using std::abs; 00267 return abs(x); 00268 } 00269 }; 00270 00271 template<typename Scalar> 00272 struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 00273 00274 template<typename Scalar> 00275 struct norm1_retval 00276 { 00277 typedef typename NumTraits<Scalar>::Real type; 00278 }; 00279 00280 /**************************************************************************** 00281 * Implementation of hypot * 00282 ****************************************************************************/ 00283 00284 template<typename Scalar> 00285 struct hypot_impl 00286 { 00287 typedef typename NumTraits<Scalar>::Real RealScalar; 00288 static inline RealScalar run(const Scalar& x, const Scalar& y) 00289 { 00290 using std::max; 00291 using std::min; 00292 using std::abs; 00293 using std::sqrt; 00294 RealScalar _x = abs(x); 00295 RealScalar _y = abs(y); 00296 RealScalar p = (max)(_x, _y); 00297 if(p==RealScalar(0)) return RealScalar(0); 00298 RealScalar q = (min)(_x, _y); 00299 RealScalar qp = q/p; 00300 return p * sqrt(RealScalar(1) + qp*qp); 00301 } 00302 }; 00303 00304 template<typename Scalar> 00305 struct hypot_retval 00306 { 00307 typedef typename NumTraits<Scalar>::Real type; 00308 }; 00309 00310 /**************************************************************************** 00311 * Implementation of cast * 00312 ****************************************************************************/ 00313 00314 template<typename OldType, typename NewType> 00315 struct cast_impl 00316 { 00317 static inline NewType run(const OldType& x) 00318 { 00319 return static_cast<NewType>(x); 00320 } 00321 }; 00322 00323 // here, for once, we're plainly returning NewType: we don't want cast to do weird things. 00324 00325 template<typename OldType, typename NewType> 00326 inline NewType cast(const OldType& x) 00327 { 00328 return cast_impl<OldType, NewType>::run(x); 00329 } 00330 00331 /**************************************************************************** 00332 * Implementation of atanh2 * 00333 ****************************************************************************/ 00334 00335 template<typename Scalar, bool IsInteger> 00336 struct atanh2_default_impl 00337 { 00338 typedef Scalar retval; 00339 typedef typename NumTraits<Scalar>::Real RealScalar; 00340 static inline Scalar run(const Scalar& x, const Scalar& y) 00341 { 00342 using std::abs; 00343 using std::log; 00344 using std::sqrt; 00345 Scalar z = x / y; 00346 if (y == Scalar(0) || abs(z) > sqrt(NumTraits<RealScalar>::epsilon())) 00347 return RealScalar(0.5) * log((y + x) / (y - x)); 00348 else 00349 return z + z*z*z / RealScalar(3); 00350 } 00351 }; 00352 00353 template<typename Scalar> 00354 struct atanh2_default_impl<Scalar, true> 00355 { 00356 static inline Scalar run(const Scalar&, const Scalar&) 00357 { 00358 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) 00359 return Scalar(0); 00360 } 00361 }; 00362 00363 template<typename Scalar> 00364 struct atanh2_impl : atanh2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 00365 00366 template<typename Scalar> 00367 struct atanh2_retval 00368 { 00369 typedef Scalar type; 00370 }; 00371 00372 /**************************************************************************** 00373 * Implementation of pow * 00374 ****************************************************************************/ 00375 00376 template<typename Scalar, bool IsInteger> 00377 struct pow_default_impl 00378 { 00379 typedef Scalar retval; 00380 static inline Scalar run(const Scalar& x, const Scalar& y) 00381 { 00382 using std::pow; 00383 return pow(x, y); 00384 } 00385 }; 00386 00387 template<typename Scalar> 00388 struct pow_default_impl<Scalar, true> 00389 { 00390 static inline Scalar run(Scalar x, Scalar y) 00391 { 00392 Scalar res(1); 00393 eigen_assert(!NumTraits<Scalar>::IsSigned || y >= 0); 00394 if(y & 1) res *= x; 00395 y >>= 1; 00396 while(y) 00397 { 00398 x *= x; 00399 if(y&1) res *= x; 00400 y >>= 1; 00401 } 00402 return res; 00403 } 00404 }; 00405 00406 template<typename Scalar> 00407 struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 00408 00409 template<typename Scalar> 00410 struct pow_retval 00411 { 00412 typedef Scalar type; 00413 }; 00414 00415 /**************************************************************************** 00416 * Implementation of random * 00417 ****************************************************************************/ 00418 00419 template<typename Scalar, 00420 bool IsComplex, 00421 bool IsInteger> 00422 struct random_default_impl {}; 00423 00424 template<typename Scalar> 00425 struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 00426 00427 template<typename Scalar> 00428 struct random_retval 00429 { 00430 typedef Scalar type; 00431 }; 00432 00433 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y); 00434 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(); 00435 00436 template<typename Scalar> 00437 struct random_default_impl<Scalar, false, false> 00438 { 00439 static inline Scalar run(const Scalar& x, const Scalar& y) 00440 { 00441 return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX); 00442 } 00443 static inline Scalar run() 00444 { 00445 return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1)); 00446 } 00447 }; 00448 00449 enum { 00450 floor_log2_terminate, 00451 floor_log2_move_up, 00452 floor_log2_move_down, 00453 floor_log2_bogus 00454 }; 00455 00456 template<unsigned int n, int lower, int upper> struct floor_log2_selector 00457 { 00458 enum { middle = (lower + upper) / 2, 00459 value = (upper <= lower + 1) ? int(floor_log2_terminate) 00460 : (n < (1 << middle)) ? int(floor_log2_move_down) 00461 : (n==0) ? int(floor_log2_bogus) 00462 : int(floor_log2_move_up) 00463 }; 00464 }; 00465 00466 template<unsigned int n, 00467 int lower = 0, 00468 int upper = sizeof(unsigned int) * CHAR_BIT - 1, 00469 int selector = floor_log2_selector<n, lower, upper>::value> 00470 struct floor_log2 {}; 00471 00472 template<unsigned int n, int lower, int upper> 00473 struct floor_log2<n, lower, upper, floor_log2_move_down> 00474 { 00475 enum { value = floor_log2<n, lower, floor_log2_selector<n, lower, upper>::middle>::value }; 00476 }; 00477 00478 template<unsigned int n, int lower, int upper> 00479 struct floor_log2<n, lower, upper, floor_log2_move_up> 00480 { 00481 enum { value = floor_log2<n, floor_log2_selector<n, lower, upper>::middle, upper>::value }; 00482 }; 00483 00484 template<unsigned int n, int lower, int upper> 00485 struct floor_log2<n, lower, upper, floor_log2_terminate> 00486 { 00487 enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; 00488 }; 00489 00490 template<unsigned int n, int lower, int upper> 00491 struct floor_log2<n, lower, upper, floor_log2_bogus> 00492 { 00493 // no value, error at compile time 00494 }; 00495 00496 template<typename Scalar> 00497 struct random_default_impl<Scalar, false, true> 00498 { 00499 typedef typename NumTraits<Scalar>::NonInteger NonInteger; 00500 00501 static inline Scalar run(const Scalar& x, const Scalar& y) 00502 { 00503 return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1))); 00504 } 00505 00506 static inline Scalar run() 00507 { 00508 #ifdef EIGEN_MAKING_DOCS 00509 return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10)); 00510 #else 00511 enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value, 00512 scalar_bits = sizeof(Scalar) * CHAR_BIT, 00513 shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)), 00514 offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0 00515 }; 00516 return Scalar((std::rand() >> shift) - offset); 00517 #endif 00518 } 00519 }; 00520 00521 template<typename Scalar> 00522 struct random_default_impl<Scalar, true, false> 00523 { 00524 static inline Scalar run(const Scalar& x, const Scalar& y) 00525 { 00526 return Scalar(random(real(x), real(y)), 00527 random(imag(x), imag(y))); 00528 } 00529 static inline Scalar run() 00530 { 00531 typedef typename NumTraits<Scalar>::Real RealScalar; 00532 return Scalar(random<RealScalar>(), random<RealScalar>()); 00533 } 00534 }; 00535 00536 template<typename Scalar> 00537 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y) 00538 { 00539 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y); 00540 } 00541 00542 template<typename Scalar> 00543 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() 00544 { 00545 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(); 00546 } 00547 00548 } // end namespace internal 00549 00550 /**************************************************************************** 00551 * Generic math function * 00552 ****************************************************************************/ 00553 00554 namespace numext { 00555 00556 template<typename Scalar> 00557 inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) 00558 { 00559 return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x); 00560 } 00561 00562 template<typename Scalar> 00563 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x) 00564 { 00565 return internal::real_ref_impl<Scalar>::run(x); 00566 } 00567 00568 template<typename Scalar> 00569 inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) 00570 { 00571 return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x); 00572 } 00573 00574 template<typename Scalar> 00575 inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) 00576 { 00577 return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x); 00578 } 00579 00580 template<typename Scalar> 00581 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x) 00582 { 00583 return internal::imag_ref_impl<Scalar>::run(x); 00584 } 00585 00586 template<typename Scalar> 00587 inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x) 00588 { 00589 return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x); 00590 } 00591 00592 template<typename Scalar> 00593 inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x) 00594 { 00595 return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x); 00596 } 00597 00598 template<typename Scalar> 00599 inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) 00600 { 00601 return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); 00602 } 00603 00604 template<typename Scalar> 00605 inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) 00606 { 00607 return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x); 00608 } 00609 00610 template<typename Scalar> 00611 inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y) 00612 { 00613 return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y); 00614 } 00615 00616 template<typename Scalar> 00617 inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y) 00618 { 00619 return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y); 00620 } 00621 00622 template<typename Scalar> 00623 inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y) 00624 { 00625 return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y); 00626 } 00627 00628 // std::isfinite is non standard, so let's define our own version, 00629 // even though it is not very efficient. 00630 template<typename T> bool (isfinite)(const T& x) 00631 { 00632 return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest(); 00633 } 00634 00635 } // end namespace numext 00636 00637 namespace internal { 00638 00639 /**************************************************************************** 00640 * Implementation of fuzzy comparisons * 00641 ****************************************************************************/ 00642 00643 template<typename Scalar, 00644 bool IsComplex, 00645 bool IsInteger> 00646 struct scalar_fuzzy_default_impl {}; 00647 00648 template<typename Scalar> 00649 struct scalar_fuzzy_default_impl<Scalar, false, false> 00650 { 00651 typedef typename NumTraits<Scalar>::Real RealScalar; 00652 template<typename OtherScalar> 00653 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) 00654 { 00655 using std::abs; 00656 return abs(x) <= abs(y) * prec; 00657 } 00658 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) 00659 { 00660 using std::min; 00661 using std::abs; 00662 return abs(x - y) <= (min)(abs(x), abs(y)) * prec; 00663 } 00664 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec) 00665 { 00666 return x <= y || isApprox(x, y, prec); 00667 } 00668 }; 00669 00670 template<typename Scalar> 00671 struct scalar_fuzzy_default_impl<Scalar, false, true> 00672 { 00673 typedef typename NumTraits<Scalar>::Real RealScalar; 00674 template<typename OtherScalar> 00675 static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&) 00676 { 00677 return x == Scalar(0); 00678 } 00679 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&) 00680 { 00681 return x == y; 00682 } 00683 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&) 00684 { 00685 return x <= y; 00686 } 00687 }; 00688 00689 template<typename Scalar> 00690 struct scalar_fuzzy_default_impl<Scalar, true, false> 00691 { 00692 typedef typename NumTraits<Scalar>::Real RealScalar; 00693 template<typename OtherScalar> 00694 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) 00695 { 00696 return numext::abs2(x) <= numext::abs2(y) * prec * prec; 00697 } 00698 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) 00699 { 00700 using std::min; 00701 return numext::abs2(x - y) <= (min)(numext::abs2(x), numext::abs2(y)) * prec * prec; 00702 } 00703 }; 00704 00705 template<typename Scalar> 00706 struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 00707 00708 template<typename Scalar, typename OtherScalar> 00709 inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, 00710 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) 00711 { 00712 return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision); 00713 } 00714 00715 template<typename Scalar> 00716 inline bool isApprox(const Scalar& x, const Scalar& y, 00717 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) 00718 { 00719 return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision); 00720 } 00721 00722 template<typename Scalar> 00723 inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, 00724 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) 00725 { 00726 return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision); 00727 } 00728 00729 /****************************************** 00730 *** The special case of the bool type *** 00731 ******************************************/ 00732 00733 template<> struct random_impl<bool> 00734 { 00735 static inline bool run() 00736 { 00737 return random<int>(0,1)==0 ? false : true; 00738 } 00739 }; 00740 00741 template<> struct scalar_fuzzy_impl<bool> 00742 { 00743 typedef bool RealScalar; 00744 00745 template<typename OtherScalar> 00746 static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&) 00747 { 00748 return !x; 00749 } 00750 00751 static inline bool isApprox(bool x, bool y, bool) 00752 { 00753 return x == y; 00754 } 00755 00756 static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&) 00757 { 00758 return (!x) || y; 00759 } 00760 00761 }; 00762 00763 00764 } // end namespace internal 00765 00766 } // end namespace Eigen 00767 00768 #endif // EIGEN_MATHFUNCTIONS_H
Generated on Tue Jul 12 2022 17:46:57 by 1.7.2