MOAB
4.9.3pre
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2006-2010 Benoit Jacob <[email protected]> 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 // source: http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html 00014 #define EIGEN_PI 3.141592653589793238462643383279502884197169399375105820974944592307816406 00015 00016 namespace Eigen { 00017 00018 // On WINCE, std::abs is defined for int only, so let's defined our own overloads: 00019 // This issue has been confirmed with MSVC 2008 only, but the issue might exist for more recent versions too. 00020 #if EIGEN_OS_WINCE && EIGEN_COMP_MSVC && EIGEN_COMP_MSVC<=1500 00021 long abs(long x) { return (labs(x)); } 00022 double abs(double x) { return (fabs(x)); } 00023 float abs(float x) { return (fabsf(x)); } 00024 long double abs(long double x) { return (fabsl(x)); } 00025 #endif 00026 00027 namespace internal { 00028 00049 template<typename T, typename dummy = void> 00050 struct global_math_functions_filtering_base 00051 { 00052 typedef T type; 00053 }; 00054 00055 template<typename T> struct always_void { typedef void type; }; 00056 00057 template<typename T> 00058 struct global_math_functions_filtering_base 00059 <T, 00060 typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type 00061 > 00062 { 00063 typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type; 00064 }; 00065 00066 #define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type> 00067 #define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type 00068 00069 /**************************************************************************** 00070 * Implementation of real * 00071 ****************************************************************************/ 00072 00073 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> 00074 struct real_default_impl 00075 { 00076 typedef typename NumTraits<Scalar>::Real RealScalar; 00077 EIGEN_DEVICE_FUNC 00078 static inline RealScalar run(const Scalar& x) 00079 { 00080 return x; 00081 } 00082 }; 00083 00084 template<typename Scalar> 00085 struct real_default_impl<Scalar,true> 00086 { 00087 typedef typename NumTraits<Scalar>::Real RealScalar; 00088 EIGEN_DEVICE_FUNC 00089 static inline RealScalar run(const Scalar& x) 00090 { 00091 using std::real; 00092 return real(x); 00093 } 00094 }; 00095 00096 template<typename Scalar> struct real_impl : real_default_impl<Scalar> {}; 00097 00098 template<typename Scalar> 00099 struct real_retval 00100 { 00101 typedef typename NumTraits<Scalar>::Real type; 00102 }; 00103 00104 /**************************************************************************** 00105 * Implementation of imag * 00106 ****************************************************************************/ 00107 00108 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> 00109 struct imag_default_impl 00110 { 00111 typedef typename NumTraits<Scalar>::Real RealScalar; 00112 EIGEN_DEVICE_FUNC 00113 static inline RealScalar run(const Scalar&) 00114 { 00115 return RealScalar(0); 00116 } 00117 }; 00118 00119 template<typename Scalar> 00120 struct imag_default_impl<Scalar,true> 00121 { 00122 typedef typename NumTraits<Scalar>::Real RealScalar; 00123 EIGEN_DEVICE_FUNC 00124 static inline RealScalar run(const Scalar& x) 00125 { 00126 using std::imag; 00127 return imag(x); 00128 } 00129 }; 00130 00131 template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {}; 00132 00133 template<typename Scalar> 00134 struct imag_retval 00135 { 00136 typedef typename NumTraits<Scalar>::Real type; 00137 }; 00138 00139 /**************************************************************************** 00140 * Implementation of real_ref * 00141 ****************************************************************************/ 00142 00143 template<typename Scalar> 00144 struct real_ref_impl 00145 { 00146 typedef typename NumTraits<Scalar>::Real RealScalar; 00147 EIGEN_DEVICE_FUNC 00148 static inline RealScalar& run(Scalar& x) 00149 { 00150 return reinterpret_cast<RealScalar*>(&x)[0]; 00151 } 00152 EIGEN_DEVICE_FUNC 00153 static inline const RealScalar& run(const Scalar& x) 00154 { 00155 return reinterpret_cast<const RealScalar*>(&x)[0]; 00156 } 00157 }; 00158 00159 template<typename Scalar> 00160 struct real_ref_retval 00161 { 00162 typedef typename NumTraits<Scalar>::Real & type; 00163 }; 00164 00165 /**************************************************************************** 00166 * Implementation of imag_ref * 00167 ****************************************************************************/ 00168 00169 template<typename Scalar, bool IsComplex> 00170 struct imag_ref_default_impl 00171 { 00172 typedef typename NumTraits<Scalar>::Real RealScalar; 00173 EIGEN_DEVICE_FUNC 00174 static inline RealScalar& run(Scalar& x) 00175 { 00176 return reinterpret_cast<RealScalar*>(&x)[1]; 00177 } 00178 EIGEN_DEVICE_FUNC 00179 static inline const RealScalar& run(const Scalar& x) 00180 { 00181 return reinterpret_cast<RealScalar*>(&x)[1]; 00182 } 00183 }; 00184 00185 template<typename Scalar> 00186 struct imag_ref_default_impl<Scalar, false> 00187 { 00188 EIGEN_DEVICE_FUNC 00189 static inline Scalar run(Scalar&) 00190 { 00191 return Scalar(0); 00192 } 00193 EIGEN_DEVICE_FUNC 00194 static inline const Scalar run(const Scalar&) 00195 { 00196 return Scalar(0); 00197 } 00198 }; 00199 00200 template<typename Scalar> 00201 struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 00202 00203 template<typename Scalar> 00204 struct imag_ref_retval 00205 { 00206 typedef typename NumTraits<Scalar>::Real & type; 00207 }; 00208 00209 /**************************************************************************** 00210 * Implementation of conj * 00211 ****************************************************************************/ 00212 00213 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> 00214 struct conj_impl 00215 { 00216 EIGEN_DEVICE_FUNC 00217 static inline Scalar run(const Scalar& x) 00218 { 00219 return x; 00220 } 00221 }; 00222 00223 template<typename Scalar> 00224 struct conj_impl<Scalar,true> 00225 { 00226 EIGEN_DEVICE_FUNC 00227 static inline Scalar run(const Scalar& x) 00228 { 00229 using std::conj; 00230 return conj(x); 00231 } 00232 }; 00233 00234 template<typename Scalar> 00235 struct conj_retval 00236 { 00237 typedef Scalar type; 00238 }; 00239 00240 /**************************************************************************** 00241 * Implementation of abs2 * 00242 ****************************************************************************/ 00243 00244 template<typename Scalar,bool IsComplex> 00245 struct abs2_impl_default 00246 { 00247 typedef typename NumTraits<Scalar>::Real RealScalar; 00248 EIGEN_DEVICE_FUNC 00249 static inline RealScalar run(const Scalar& x) 00250 { 00251 return x*x; 00252 } 00253 }; 00254 00255 template<typename Scalar> 00256 struct abs2_impl_default<Scalar, true> // IsComplex 00257 { 00258 typedef typename NumTraits<Scalar>::Real RealScalar; 00259 EIGEN_DEVICE_FUNC 00260 static inline RealScalar run(const Scalar& x) 00261 { 00262 return real(x)*real(x) + imag(x)*imag(x); 00263 } 00264 }; 00265 00266 template<typename Scalar> 00267 struct abs2_impl 00268 { 00269 typedef typename NumTraits<Scalar>::Real RealScalar; 00270 EIGEN_DEVICE_FUNC 00271 static inline RealScalar run(const Scalar& x) 00272 { 00273 return abs2_impl_default<Scalar,NumTraits<Scalar>::IsComplex>::run(x); 00274 } 00275 }; 00276 00277 template<typename Scalar> 00278 struct abs2_retval 00279 { 00280 typedef typename NumTraits<Scalar>::Real type; 00281 }; 00282 00283 /**************************************************************************** 00284 * Implementation of norm1 * 00285 ****************************************************************************/ 00286 00287 template<typename Scalar, bool IsComplex> 00288 struct norm1_default_impl 00289 { 00290 typedef typename NumTraits<Scalar>::Real RealScalar; 00291 EIGEN_DEVICE_FUNC 00292 static inline RealScalar run(const Scalar& x) 00293 { 00294 EIGEN_USING_STD_MATH(abs); 00295 return abs(real(x)) + abs(imag(x)); 00296 } 00297 }; 00298 00299 template<typename Scalar> 00300 struct norm1_default_impl<Scalar, false> 00301 { 00302 EIGEN_DEVICE_FUNC 00303 static inline Scalar run(const Scalar& x) 00304 { 00305 EIGEN_USING_STD_MATH(abs); 00306 return abs(x); 00307 } 00308 }; 00309 00310 template<typename Scalar> 00311 struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 00312 00313 template<typename Scalar> 00314 struct norm1_retval 00315 { 00316 typedef typename NumTraits<Scalar>::Real type; 00317 }; 00318 00319 /**************************************************************************** 00320 * Implementation of hypot * 00321 ****************************************************************************/ 00322 00323 template<typename Scalar> 00324 struct hypot_impl 00325 { 00326 typedef typename NumTraits<Scalar>::Real RealScalar; 00327 static inline RealScalar run(const Scalar& x, const Scalar& y) 00328 { 00329 EIGEN_USING_STD_MATH(abs); 00330 EIGEN_USING_STD_MATH(sqrt); 00331 RealScalar _x = abs(x); 00332 RealScalar _y = abs(y); 00333 Scalar p, qp; 00334 if(_x>_y) 00335 { 00336 p = _x; 00337 qp = _y / p; 00338 } 00339 else 00340 { 00341 p = _y; 00342 qp = _x / p; 00343 } 00344 if(p==RealScalar(0)) return RealScalar(0); 00345 return p * sqrt(RealScalar(1) + qp*qp); 00346 } 00347 }; 00348 00349 template<typename Scalar> 00350 struct hypot_retval 00351 { 00352 typedef typename NumTraits<Scalar>::Real type; 00353 }; 00354 00355 /**************************************************************************** 00356 * Implementation of cast * 00357 ****************************************************************************/ 00358 00359 template<typename OldType, typename NewType> 00360 struct cast_impl 00361 { 00362 EIGEN_DEVICE_FUNC 00363 static inline NewType run(const OldType& x) 00364 { 00365 return static_cast<NewType>(x); 00366 } 00367 }; 00368 00369 // here, for once, we're plainly returning NewType: we don't want cast to do weird things. 00370 00371 template<typename OldType, typename NewType> 00372 EIGEN_DEVICE_FUNC 00373 inline NewType cast(const OldType& x) 00374 { 00375 return cast_impl<OldType, NewType>::run(x); 00376 } 00377 00378 /**************************************************************************** 00379 * Implementation of round * 00380 ****************************************************************************/ 00381 00382 #if EIGEN_HAS_CXX11_MATH 00383 template<typename Scalar> 00384 struct round_impl { 00385 static inline Scalar run(const Scalar& x) 00386 { 00387 EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL) 00388 using std::round; 00389 return round(x); 00390 } 00391 }; 00392 #else 00393 template<typename Scalar> 00394 struct round_impl 00395 { 00396 static inline Scalar run(const Scalar& x) 00397 { 00398 EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL) 00399 EIGEN_USING_STD_MATH(floor); 00400 EIGEN_USING_STD_MATH(ceil); 00401 return (x > Scalar(0)) ? floor(x + Scalar(0.5)) : ceil(x - Scalar(0.5)); 00402 } 00403 }; 00404 #endif 00405 00406 template<typename Scalar> 00407 struct round_retval 00408 { 00409 typedef Scalar type; 00410 }; 00411 00412 /**************************************************************************** 00413 * Implementation of arg * 00414 ****************************************************************************/ 00415 00416 #if EIGEN_HAS_CXX11_MATH 00417 template<typename Scalar> 00418 struct arg_impl { 00419 static inline Scalar run(const Scalar& x) 00420 { 00421 EIGEN_USING_STD_MATH(arg); 00422 return arg(x); 00423 } 00424 }; 00425 #else 00426 template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> 00427 struct arg_default_impl 00428 { 00429 typedef typename NumTraits<Scalar>::Real RealScalar; 00430 EIGEN_DEVICE_FUNC 00431 static inline RealScalar run(const Scalar& x) 00432 { 00433 return (x < Scalar(0)) ? Scalar(EIGEN_PI) : Scalar(0); } 00434 }; 00435 00436 template<typename Scalar> 00437 struct arg_default_impl<Scalar,true> 00438 { 00439 typedef typename NumTraits<Scalar>::Real RealScalar; 00440 EIGEN_DEVICE_FUNC 00441 static inline RealScalar run(const Scalar& x) 00442 { 00443 EIGEN_USING_STD_MATH(arg); 00444 return arg(x); 00445 } 00446 }; 00447 00448 template<typename Scalar> struct arg_impl : arg_default_impl<Scalar> {}; 00449 #endif 00450 00451 template<typename Scalar> 00452 struct arg_retval 00453 { 00454 typedef typename NumTraits<Scalar>::Real type; 00455 }; 00456 00457 /**************************************************************************** 00458 * Implementation of log1p * 00459 ****************************************************************************/ 00460 template<typename Scalar, bool isComplex = NumTraits<Scalar>::IsComplex > 00461 struct log1p_impl 00462 { 00463 static inline Scalar run(const Scalar& x) 00464 { 00465 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) 00466 typedef typename NumTraits<Scalar>::Real RealScalar; 00467 EIGEN_USING_STD_MATH(log); 00468 Scalar x1p = RealScalar(1) + x; 00469 return ( x1p == Scalar(1) ) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); 00470 } 00471 }; 00472 00473 #if EIGEN_HAS_CXX11_MATH 00474 template<typename Scalar> 00475 struct log1p_impl<Scalar, false> { 00476 static inline Scalar run(const Scalar& x) 00477 { 00478 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) 00479 using std::log1p; 00480 return log1p(x); 00481 } 00482 }; 00483 #endif 00484 00485 template<typename Scalar> 00486 struct log1p_retval 00487 { 00488 typedef Scalar type; 00489 }; 00490 00491 /**************************************************************************** 00492 * Implementation of pow * 00493 ****************************************************************************/ 00494 00495 template<typename Scalar, bool IsInteger> 00496 struct pow_default_impl 00497 { 00498 typedef Scalar retval; 00499 static EIGEN_DEVICE_FUNC inline Scalar run(const Scalar& x, const Scalar& y) 00500 { 00501 EIGEN_USING_STD_MATH(pow); 00502 return pow(x, y); 00503 } 00504 }; 00505 00506 template<typename Scalar> 00507 struct pow_default_impl<Scalar, true> 00508 { 00509 static EIGEN_DEVICE_FUNC inline Scalar run(Scalar x, Scalar y) 00510 { 00511 Scalar res(1); 00512 eigen_assert(!NumTraits<Scalar>::IsSigned || y >= 0); 00513 if(y & 1) res *= x; 00514 y >>= 1; 00515 while(y) 00516 { 00517 x *= x; 00518 if(y&1) res *= x; 00519 y >>= 1; 00520 } 00521 return res; 00522 } 00523 }; 00524 00525 template<typename Scalar> 00526 struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 00527 00528 template<typename Scalar> 00529 struct pow_retval 00530 { 00531 typedef Scalar type; 00532 }; 00533 00534 /**************************************************************************** 00535 * Implementation of random * 00536 ****************************************************************************/ 00537 00538 template<typename Scalar, 00539 bool IsComplex, 00540 bool IsInteger> 00541 struct random_default_impl {}; 00542 00543 template<typename Scalar> 00544 struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 00545 00546 template<typename Scalar> 00547 struct random_retval 00548 { 00549 typedef Scalar type; 00550 }; 00551 00552 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y); 00553 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(); 00554 00555 template<typename Scalar> 00556 struct random_default_impl<Scalar, false, false> 00557 { 00558 static inline Scalar run(const Scalar& x, const Scalar& y) 00559 { 00560 return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX); 00561 } 00562 static inline Scalar run() 00563 { 00564 return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1)); 00565 } 00566 }; 00567 00568 enum { 00569 meta_floor_log2_terminate, 00570 meta_floor_log2_move_up, 00571 meta_floor_log2_move_down, 00572 meta_floor_log2_bogus 00573 }; 00574 00575 template<unsigned int n, int lower, int upper> struct meta_floor_log2_selector 00576 { 00577 enum { middle = (lower + upper) / 2, 00578 value = (upper <= lower + 1) ? int(meta_floor_log2_terminate) 00579 : (n < (1 << middle)) ? int(meta_floor_log2_move_down) 00580 : (n==0) ? int(meta_floor_log2_bogus) 00581 : int(meta_floor_log2_move_up) 00582 }; 00583 }; 00584 00585 template<unsigned int n, 00586 int lower = 0, 00587 int upper = sizeof(unsigned int) * CHAR_BIT - 1, 00588 int selector = meta_floor_log2_selector<n, lower, upper>::value> 00589 struct meta_floor_log2 {}; 00590 00591 template<unsigned int n, int lower, int upper> 00592 struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_down> 00593 { 00594 enum { value = meta_floor_log2<n, lower, meta_floor_log2_selector<n, lower, upper>::middle>::value }; 00595 }; 00596 00597 template<unsigned int n, int lower, int upper> 00598 struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_up> 00599 { 00600 enum { value = meta_floor_log2<n, meta_floor_log2_selector<n, lower, upper>::middle, upper>::value }; 00601 }; 00602 00603 template<unsigned int n, int lower, int upper> 00604 struct meta_floor_log2<n, lower, upper, meta_floor_log2_terminate> 00605 { 00606 enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; 00607 }; 00608 00609 template<unsigned int n, int lower, int upper> 00610 struct meta_floor_log2<n, lower, upper, meta_floor_log2_bogus> 00611 { 00612 // no value, error at compile time 00613 }; 00614 00615 template<typename Scalar> 00616 struct random_default_impl<Scalar, false, true> 00617 { 00618 static inline Scalar run(const Scalar& x, const Scalar& y) 00619 { 00620 typedef typename conditional<NumTraits<Scalar>::IsSigned,std::ptrdiff_t,std::size_t>::type ScalarX; 00621 if(y<x) 00622 return x; 00623 std::size_t range = ScalarX(y)-ScalarX(x); 00624 std::size_t offset = 0; 00625 // rejection sampling 00626 std::size_t divisor = (range+RAND_MAX-1)/(range+1); 00627 std::size_t multiplier = (range+RAND_MAX-1)/std::size_t(RAND_MAX); 00628 00629 do { 00630 offset = ( (std::size_t(std::rand()) * multiplier) / divisor ); 00631 } while (offset > range); 00632 00633 return Scalar(ScalarX(x) + offset); 00634 } 00635 00636 static inline Scalar run() 00637 { 00638 #ifdef EIGEN_MAKING_DOCS 00639 return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10)); 00640 #else 00641 enum { rand_bits = meta_floor_log2<(unsigned int)(RAND_MAX)+1>::value, 00642 scalar_bits = sizeof(Scalar) * CHAR_BIT, 00643 shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)), 00644 offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0 00645 }; 00646 return Scalar((std::rand() >> shift) - offset); 00647 #endif 00648 } 00649 }; 00650 00651 template<typename Scalar> 00652 struct random_default_impl<Scalar, true, false> 00653 { 00654 static inline Scalar run(const Scalar& x, const Scalar& y) 00655 { 00656 return Scalar(random(real(x), real(y)), 00657 random(imag(x), imag(y))); 00658 } 00659 static inline Scalar run() 00660 { 00661 typedef typename NumTraits<Scalar>::Real RealScalar; 00662 return Scalar(random<RealScalar>(), random<RealScalar>()); 00663 } 00664 }; 00665 00666 template<typename Scalar> 00667 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y) 00668 { 00669 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y); 00670 } 00671 00672 template<typename Scalar> 00673 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() 00674 { 00675 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(); 00676 } 00677 00678 // Implementatin of is* functions 00679 00680 // std::is* do not work with fast-math and gcc, std::is* are available on MSVC 2013 and newer, as well as in clang. 00681 #if (EIGEN_HAS_CXX11_MATH && !(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || (EIGEN_COMP_MSVC>=1800) || (EIGEN_COMP_CLANG) 00682 #define EIGEN_USE_STD_FPCLASSIFY 1 00683 #else 00684 #define EIGEN_USE_STD_FPCLASSIFY 0 00685 #endif 00686 00687 template<typename T> 00688 EIGEN_DEVICE_FUNC 00689 typename internal::enable_if<internal::is_integral<T>::value,bool>::type 00690 isnan_impl(const T&) { return false; } 00691 00692 template<typename T> 00693 EIGEN_DEVICE_FUNC 00694 typename internal::enable_if<internal::is_integral<T>::value,bool>::type 00695 isinf_impl(const T&) { return false; } 00696 00697 template<typename T> 00698 EIGEN_DEVICE_FUNC 00699 typename internal::enable_if<internal::is_integral<T>::value,bool>::type 00700 isfinite_impl(const T&) { return true; } 00701 00702 template<typename T> 00703 EIGEN_DEVICE_FUNC 00704 typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type 00705 isfinite_impl(const T& x) 00706 { 00707 #if EIGEN_USE_STD_FPCLASSIFY 00708 using std::isfinite; 00709 return isfinite EIGEN_NOT_A_MACRO (x); 00710 #else 00711 return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest(); 00712 #endif 00713 } 00714 00715 template<typename T> 00716 EIGEN_DEVICE_FUNC 00717 typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type 00718 isinf_impl(const T& x) 00719 { 00720 #if EIGEN_USE_STD_FPCLASSIFY 00721 using std::isinf; 00722 return isinf EIGEN_NOT_A_MACRO (x); 00723 #else 00724 return x>NumTraits<T>::highest() || x<NumTraits<T>::lowest(); 00725 #endif 00726 } 00727 00728 template<typename T> 00729 EIGEN_DEVICE_FUNC 00730 typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type 00731 isnan_impl(const T& x) 00732 { 00733 #if EIGEN_USE_STD_FPCLASSIFY 00734 using std::isnan; 00735 return isnan EIGEN_NOT_A_MACRO (x); 00736 #else 00737 return x != x; 00738 #endif 00739 } 00740 00741 #if (!EIGEN_USE_STD_FPCLASSIFY) 00742 00743 #if EIGEN_COMP_MSVC 00744 00745 template<typename T> EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x) 00746 { 00747 return _fpclass(x)==_FPCLASS_NINF || _fpclass(x)==_FPCLASS_PINF; 00748 } 00749 00750 //MSVC defines a _isnan builtin function, but for double only 00751 EIGEN_DEVICE_FUNC inline bool isnan_impl(const long double& x) { return _isnan(x)!=0; } 00752 EIGEN_DEVICE_FUNC inline bool isnan_impl(const double& x) { return _isnan(x)!=0; } 00753 EIGEN_DEVICE_FUNC inline bool isnan_impl(const float& x) { return _isnan(x)!=0; } 00754 00755 EIGEN_DEVICE_FUNC inline bool isinf_impl(const long double& x) { return isinf_msvc_helper(x); } 00756 EIGEN_DEVICE_FUNC inline bool isinf_impl(const double& x) { return isinf_msvc_helper(x); } 00757 EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_msvc_helper(x); } 00758 00759 #elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC) 00760 00761 #if EIGEN_GNUC_AT_LEAST(5,0) 00762 #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((optimize("no-finite-math-only"))) 00763 #else 00764 // NOTE the inline qualifier and noinline attribute are both needed: the former is to avoid linking issue (duplicate symbol), 00765 // while the second prevent too aggressive optimizations in fast-math mode: 00766 #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((noinline,optimize("no-finite-math-only"))) 00767 #endif 00768 00769 template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const long double& x) { return __builtin_isnan(x); } 00770 template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const double& x) { return __builtin_isnan(x); } 00771 template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const float& x) { return __builtin_isnan(x); } 00772 template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const double& x) { return __builtin_isinf(x); } 00773 template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const float& x) { return __builtin_isinf(x); } 00774 template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const long double& x) { return __builtin_isinf(x); } 00775 00776 #undef EIGEN_TMP_NOOPT_ATTRIB 00777 00778 #endif 00779 00780 #endif 00781 00782 // The following overload are defined at the end of this file 00783 template<typename T> bool isfinite_impl(const std::complex<T>& x); 00784 template<typename T> bool isnan_impl(const std::complex<T>& x); 00785 template<typename T> bool isinf_impl(const std::complex<T>& x); 00786 00787 } // end namespace internal 00788 00789 /**************************************************************************** 00790 * Generic math functions * 00791 ****************************************************************************/ 00792 00793 namespace numext { 00794 00795 #ifndef __CUDA_ARCH__ 00796 template<typename T> 00797 EIGEN_DEVICE_FUNC 00798 EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y) 00799 { 00800 EIGEN_USING_STD_MATH(min); 00801 return min EIGEN_NOT_A_MACRO (x,y); 00802 } 00803 00804 template<typename T> 00805 EIGEN_DEVICE_FUNC 00806 EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y) 00807 { 00808 EIGEN_USING_STD_MATH(max); 00809 return max EIGEN_NOT_A_MACRO (x,y); 00810 } 00811 #else 00812 template<typename T> 00813 EIGEN_DEVICE_FUNC 00814 EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y) 00815 { 00816 return y < x ? y : x; 00817 } 00818 template<> 00819 EIGEN_DEVICE_FUNC 00820 EIGEN_ALWAYS_INLINE float mini(const float& x, const float& y) 00821 { 00822 return fmin(x, y); 00823 } 00824 template<typename T> 00825 EIGEN_DEVICE_FUNC 00826 EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y) 00827 { 00828 return x < y ? y : x; 00829 } 00830 template<> 00831 EIGEN_DEVICE_FUNC 00832 EIGEN_ALWAYS_INLINE float maxi(const float& x, const float& y) 00833 { 00834 return fmax(x, y); 00835 } 00836 #endif 00837 00838 00839 template<typename Scalar> 00840 EIGEN_DEVICE_FUNC 00841 inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) 00842 { 00843 return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x); 00844 } 00845 00846 template<typename Scalar> 00847 EIGEN_DEVICE_FUNC 00848 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x) 00849 { 00850 return internal::real_ref_impl<Scalar>::run(x); 00851 } 00852 00853 template<typename Scalar> 00854 EIGEN_DEVICE_FUNC 00855 inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) 00856 { 00857 return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x); 00858 } 00859 00860 template<typename Scalar> 00861 EIGEN_DEVICE_FUNC 00862 inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) 00863 { 00864 return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x); 00865 } 00866 00867 template<typename Scalar> 00868 EIGEN_DEVICE_FUNC 00869 inline EIGEN_MATHFUNC_RETVAL(arg, Scalar) arg(const Scalar& x) 00870 { 00871 return EIGEN_MATHFUNC_IMPL(arg, Scalar)::run(x); 00872 } 00873 00874 template<typename Scalar> 00875 EIGEN_DEVICE_FUNC 00876 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x) 00877 { 00878 return internal::imag_ref_impl<Scalar>::run(x); 00879 } 00880 00881 template<typename Scalar> 00882 EIGEN_DEVICE_FUNC 00883 inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x) 00884 { 00885 return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x); 00886 } 00887 00888 template<typename Scalar> 00889 EIGEN_DEVICE_FUNC 00890 inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x) 00891 { 00892 return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x); 00893 } 00894 00895 template<typename Scalar> 00896 EIGEN_DEVICE_FUNC 00897 inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) 00898 { 00899 return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); 00900 } 00901 00902 template<typename Scalar> 00903 EIGEN_DEVICE_FUNC 00904 inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) 00905 { 00906 return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x); 00907 } 00908 00909 template<typename Scalar> 00910 EIGEN_DEVICE_FUNC 00911 inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y) 00912 { 00913 return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y); 00914 } 00915 00916 template<typename Scalar> 00917 EIGEN_DEVICE_FUNC 00918 inline EIGEN_MATHFUNC_RETVAL(log1p, Scalar) log1p(const Scalar& x) 00919 { 00920 return EIGEN_MATHFUNC_IMPL(log1p, Scalar)::run(x); 00921 } 00922 00923 template<typename Scalar> 00924 EIGEN_DEVICE_FUNC 00925 inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y) 00926 { 00927 return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y); 00928 } 00929 00930 template<typename T> EIGEN_DEVICE_FUNC bool (isnan) (const T &x) { return internal::isnan_impl(x); } 00931 template<typename T> EIGEN_DEVICE_FUNC bool (isinf) (const T &x) { return internal::isinf_impl(x); } 00932 template<typename T> EIGEN_DEVICE_FUNC bool (isfinite)(const T &x) { return internal::isfinite_impl(x); } 00933 00934 template<typename Scalar> 00935 EIGEN_DEVICE_FUNC 00936 inline EIGEN_MATHFUNC_RETVAL(round, Scalar) round(const Scalar& x) 00937 { 00938 return EIGEN_MATHFUNC_IMPL(round, Scalar)::run(x); 00939 } 00940 00941 template<typename T> 00942 EIGEN_DEVICE_FUNC 00943 T (floor)(const T& x) 00944 { 00945 EIGEN_USING_STD_MATH(floor); 00946 return floor(x); 00947 } 00948 00949 template<typename T> 00950 EIGEN_DEVICE_FUNC 00951 T (ceil)(const T& x) 00952 { 00953 EIGEN_USING_STD_MATH(ceil); 00954 return ceil(x); 00955 } 00956 00959 inline int log2(int x) 00960 { 00961 eigen_assert(x>=0); 00962 unsigned int v(x); 00963 static const int table[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; 00964 v |= v >> 1; 00965 v |= v >> 2; 00966 v |= v >> 4; 00967 v |= v >> 8; 00968 v |= v >> 16; 00969 return table[(v * 0x07C4ACDDU) >> 27]; 00970 } 00971 00980 template<typename T> 00981 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE 00982 T sqrt(const T &x) 00983 { 00984 EIGEN_USING_STD_MATH(sqrt); 00985 return sqrt(x); 00986 } 00987 00988 } // end namespace numext 00989 00990 namespace internal { 00991 00992 template<typename T> 00993 bool isfinite_impl(const std::complex<T>& x) 00994 { 00995 return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x)); 00996 } 00997 00998 template<typename T> 00999 bool isnan_impl(const std::complex<T>& x) 01000 { 01001 return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x)); 01002 } 01003 01004 template<typename T> 01005 bool isinf_impl(const std::complex<T>& x) 01006 { 01007 return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x)); 01008 } 01009 01010 /**************************************************************************** 01011 * Implementation of fuzzy comparisons * 01012 ****************************************************************************/ 01013 01014 template<typename Scalar, 01015 bool IsComplex, 01016 bool IsInteger> 01017 struct scalar_fuzzy_default_impl {}; 01018 01019 template<typename Scalar> 01020 struct scalar_fuzzy_default_impl<Scalar, false, false> 01021 { 01022 typedef typename NumTraits<Scalar>::Real RealScalar; 01023 template<typename OtherScalar> EIGEN_DEVICE_FUNC 01024 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) 01025 { 01026 EIGEN_USING_STD_MATH(abs); 01027 return abs(x) <= abs(y) * prec; 01028 } 01029 EIGEN_DEVICE_FUNC 01030 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) 01031 { 01032 EIGEN_USING_STD_MATH(abs); 01033 return abs(x - y) <= numext::mini(abs(x), abs(y)) * prec; 01034 } 01035 EIGEN_DEVICE_FUNC 01036 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec) 01037 { 01038 return x <= y || isApprox(x, y, prec); 01039 } 01040 }; 01041 01042 template<typename Scalar> 01043 struct scalar_fuzzy_default_impl<Scalar, false, true> 01044 { 01045 typedef typename NumTraits<Scalar>::Real RealScalar; 01046 template<typename OtherScalar> EIGEN_DEVICE_FUNC 01047 static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&) 01048 { 01049 return x == Scalar(0); 01050 } 01051 EIGEN_DEVICE_FUNC 01052 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&) 01053 { 01054 return x == y; 01055 } 01056 EIGEN_DEVICE_FUNC 01057 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&) 01058 { 01059 return x <= y; 01060 } 01061 }; 01062 01063 template<typename Scalar> 01064 struct scalar_fuzzy_default_impl<Scalar, true, false> 01065 { 01066 typedef typename NumTraits<Scalar>::Real RealScalar; 01067 template<typename OtherScalar> 01068 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) 01069 { 01070 return numext::abs2(x) <= numext::abs2(y) * prec * prec; 01071 } 01072 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) 01073 { 01074 return numext::abs2(x - y) <= numext::mini(numext::abs2(x), numext::abs2(y)) * prec * prec; 01075 } 01076 }; 01077 01078 template<typename Scalar> 01079 struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 01080 01081 template<typename Scalar, typename OtherScalar> EIGEN_DEVICE_FUNC 01082 inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, 01083 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) 01084 { 01085 return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision); 01086 } 01087 01088 template<typename Scalar> EIGEN_DEVICE_FUNC 01089 inline bool isApprox(const Scalar& x, const Scalar& y, 01090 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) 01091 { 01092 return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision); 01093 } 01094 01095 template<typename Scalar> EIGEN_DEVICE_FUNC 01096 inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, 01097 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) 01098 { 01099 return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision); 01100 } 01101 01102 /****************************************** 01103 *** The special case of the bool type *** 01104 ******************************************/ 01105 01106 template<> struct random_impl<bool> 01107 { 01108 static inline bool run() 01109 { 01110 return random<int>(0,1)==0 ? false : true; 01111 } 01112 }; 01113 01114 template<> struct scalar_fuzzy_impl<bool> 01115 { 01116 typedef bool RealScalar; 01117 01118 template<typename OtherScalar> EIGEN_DEVICE_FUNC 01119 static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&) 01120 { 01121 return !x; 01122 } 01123 01124 EIGEN_DEVICE_FUNC 01125 static inline bool isApprox(bool x, bool y, bool) 01126 { 01127 return x == y; 01128 } 01129 01130 EIGEN_DEVICE_FUNC 01131 static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&) 01132 { 01133 return (!x) || y; 01134 } 01135 01136 }; 01137 01138 01139 } // end namespace internal 01140 01141 } // end namespace Eigen 01142 01143 #endif // EIGEN_MATHFUNCTIONS_H