00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef EIGEN_MATHFUNCTIONS_H
00011 #define EIGEN_MATHFUNCTIONS_H
00012
00013 namespace Eigen {
00014
00015 namespace internal {
00016
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
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
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
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
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
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
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
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
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 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
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
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
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
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
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
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 }
00549
00550
00551
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
00629
00630 template<typename T> bool (isfinite)(const T& x)
00631 {
00632 return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
00633 }
00634
00635 }
00636
00637 namespace internal {
00638
00639
00640
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 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 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 typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision())
00725 {
00726 return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
00727 }
00728
00729
00730
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 }
00765
00766 }
00767
00768 #endif // EIGEN_MATHFUNCTIONS_H