1// This file is part of Eigen, a lightweight C++ template library 2// for linear algebra. 3// 4// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> 5// 6// This Source Code Form is subject to the terms of the Mozilla 7// Public License v. 2.0. If a copy of the MPL was not distributed 8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10#ifndef EIGEN_MATHFUNCTIONS_H 11#define EIGEN_MATHFUNCTIONS_H 12 13namespace Eigen { 14 15namespace 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 37template<typename T, typename dummy = void> 38struct global_math_functions_filtering_base 39{ 40 typedef T type; 41}; 42 43template<typename T> struct always_void { typedef void type; }; 44 45template<typename T> 46struct 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) func##_impl<typename global_math_functions_filtering_base<scalar>::type> 55#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename func##_retval<typename global_math_functions_filtering_base<scalar>::type>::type 56 57 58/**************************************************************************** 59* Implementation of real * 60****************************************************************************/ 61 62template<typename Scalar> 63struct real_impl 64{ 65 typedef typename NumTraits<Scalar>::Real RealScalar; 66 static inline RealScalar run(const Scalar& x) 67 { 68 return x; 69 } 70}; 71 72template<typename RealScalar> 73struct real_impl<std::complex<RealScalar> > 74{ 75 static inline RealScalar run(const std::complex<RealScalar>& x) 76 { 77 using std::real; 78 return real(x); 79 } 80}; 81 82template<typename Scalar> 83struct real_retval 84{ 85 typedef typename NumTraits<Scalar>::Real type; 86}; 87 88template<typename Scalar> 89inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) 90{ 91 return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x); 92} 93 94/**************************************************************************** 95* Implementation of imag * 96****************************************************************************/ 97 98template<typename Scalar> 99struct imag_impl 100{ 101 typedef typename NumTraits<Scalar>::Real RealScalar; 102 static inline RealScalar run(const Scalar&) 103 { 104 return RealScalar(0); 105 } 106}; 107 108template<typename RealScalar> 109struct imag_impl<std::complex<RealScalar> > 110{ 111 static inline RealScalar run(const std::complex<RealScalar>& x) 112 { 113 using std::imag; 114 return imag(x); 115 } 116}; 117 118template<typename Scalar> 119struct imag_retval 120{ 121 typedef typename NumTraits<Scalar>::Real type; 122}; 123 124template<typename Scalar> 125inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) 126{ 127 return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x); 128} 129 130/**************************************************************************** 131* Implementation of real_ref * 132****************************************************************************/ 133 134template<typename Scalar> 135struct real_ref_impl 136{ 137 typedef typename NumTraits<Scalar>::Real RealScalar; 138 static inline RealScalar& run(Scalar& x) 139 { 140 return reinterpret_cast<RealScalar*>(&x)[0]; 141 } 142 static inline const RealScalar& run(const Scalar& x) 143 { 144 return reinterpret_cast<const RealScalar*>(&x)[0]; 145 } 146}; 147 148template<typename Scalar> 149struct real_ref_retval 150{ 151 typedef typename NumTraits<Scalar>::Real & type; 152}; 153 154template<typename Scalar> 155inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x) 156{ 157 return real_ref_impl<Scalar>::run(x); 158} 159 160template<typename Scalar> 161inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) 162{ 163 return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x); 164} 165 166/**************************************************************************** 167* Implementation of imag_ref * 168****************************************************************************/ 169 170template<typename Scalar, bool IsComplex> 171struct imag_ref_default_impl 172{ 173 typedef typename NumTraits<Scalar>::Real RealScalar; 174 static inline RealScalar& run(Scalar& x) 175 { 176 return reinterpret_cast<RealScalar*>(&x)[1]; 177 } 178 static inline const RealScalar& run(const Scalar& x) 179 { 180 return reinterpret_cast<RealScalar*>(&x)[1]; 181 } 182}; 183 184template<typename Scalar> 185struct imag_ref_default_impl<Scalar, false> 186{ 187 static inline Scalar run(Scalar&) 188 { 189 return Scalar(0); 190 } 191 static inline const Scalar run(const Scalar&) 192 { 193 return Scalar(0); 194 } 195}; 196 197template<typename Scalar> 198struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 199 200template<typename Scalar> 201struct imag_ref_retval 202{ 203 typedef typename NumTraits<Scalar>::Real & type; 204}; 205 206template<typename Scalar> 207inline typename add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x) 208{ 209 return imag_ref_impl<Scalar>::run(x); 210} 211 212template<typename Scalar> 213inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x) 214{ 215 return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x); 216} 217 218/**************************************************************************** 219* Implementation of conj * 220****************************************************************************/ 221 222template<typename Scalar> 223struct conj_impl 224{ 225 static inline Scalar run(const Scalar& x) 226 { 227 return x; 228 } 229}; 230 231template<typename RealScalar> 232struct conj_impl<std::complex<RealScalar> > 233{ 234 static inline std::complex<RealScalar> run(const std::complex<RealScalar>& x) 235 { 236 using std::conj; 237 return conj(x); 238 } 239}; 240 241template<typename Scalar> 242struct conj_retval 243{ 244 typedef Scalar type; 245}; 246 247template<typename Scalar> 248inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x) 249{ 250 return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x); 251} 252 253/**************************************************************************** 254* Implementation of abs * 255****************************************************************************/ 256 257template<typename Scalar> 258struct abs_impl 259{ 260 typedef typename NumTraits<Scalar>::Real RealScalar; 261 static inline RealScalar run(const Scalar& x) 262 { 263 using std::abs; 264 return abs(x); 265 } 266}; 267 268template<typename Scalar> 269struct abs_retval 270{ 271 typedef typename NumTraits<Scalar>::Real type; 272}; 273 274template<typename Scalar> 275inline EIGEN_MATHFUNC_RETVAL(abs, Scalar) abs(const Scalar& x) 276{ 277 return EIGEN_MATHFUNC_IMPL(abs, Scalar)::run(x); 278} 279 280/**************************************************************************** 281* Implementation of abs2 * 282****************************************************************************/ 283 284template<typename Scalar> 285struct abs2_impl 286{ 287 typedef typename NumTraits<Scalar>::Real RealScalar; 288 static inline RealScalar run(const Scalar& x) 289 { 290 return x*x; 291 } 292}; 293 294template<typename RealScalar> 295struct abs2_impl<std::complex<RealScalar> > 296{ 297 static inline RealScalar run(const std::complex<RealScalar>& x) 298 { 299 return real(x)*real(x) + imag(x)*imag(x); 300 } 301}; 302 303template<typename Scalar> 304struct abs2_retval 305{ 306 typedef typename NumTraits<Scalar>::Real type; 307}; 308 309template<typename Scalar> 310inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) 311{ 312 return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); 313} 314 315/**************************************************************************** 316* Implementation of norm1 * 317****************************************************************************/ 318 319template<typename Scalar, bool IsComplex> 320struct norm1_default_impl 321{ 322 typedef typename NumTraits<Scalar>::Real RealScalar; 323 static inline RealScalar run(const Scalar& x) 324 { 325 return abs(real(x)) + abs(imag(x)); 326 } 327}; 328 329template<typename Scalar> 330struct norm1_default_impl<Scalar, false> 331{ 332 static inline Scalar run(const Scalar& x) 333 { 334 return abs(x); 335 } 336}; 337 338template<typename Scalar> 339struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 340 341template<typename Scalar> 342struct norm1_retval 343{ 344 typedef typename NumTraits<Scalar>::Real type; 345}; 346 347template<typename Scalar> 348inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) 349{ 350 return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x); 351} 352 353/**************************************************************************** 354* Implementation of hypot * 355****************************************************************************/ 356 357template<typename Scalar> 358struct hypot_impl 359{ 360 typedef typename NumTraits<Scalar>::Real RealScalar; 361 static inline RealScalar run(const Scalar& x, const Scalar& y) 362 { 363 using std::max; 364 using std::min; 365 RealScalar _x = abs(x); 366 RealScalar _y = abs(y); 367 RealScalar p = (max)(_x, _y); 368 RealScalar q = (min)(_x, _y); 369 RealScalar qp = q/p; 370 return p * sqrt(RealScalar(1) + qp*qp); 371 } 372}; 373 374template<typename Scalar> 375struct hypot_retval 376{ 377 typedef typename NumTraits<Scalar>::Real type; 378}; 379 380template<typename Scalar> 381inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y) 382{ 383 return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y); 384} 385 386/**************************************************************************** 387* Implementation of cast * 388****************************************************************************/ 389 390template<typename OldType, typename NewType> 391struct cast_impl 392{ 393 static inline NewType run(const OldType& x) 394 { 395 return static_cast<NewType>(x); 396 } 397}; 398 399// here, for once, we're plainly returning NewType: we don't want cast to do weird things. 400 401template<typename OldType, typename NewType> 402inline NewType cast(const OldType& x) 403{ 404 return cast_impl<OldType, NewType>::run(x); 405} 406 407/**************************************************************************** 408* Implementation of sqrt * 409****************************************************************************/ 410 411template<typename Scalar, bool IsInteger> 412struct sqrt_default_impl 413{ 414 static inline Scalar run(const Scalar& x) 415 { 416 using std::sqrt; 417 return sqrt(x); 418 } 419}; 420 421template<typename Scalar> 422struct sqrt_default_impl<Scalar, true> 423{ 424 static inline Scalar run(const Scalar&) 425 { 426#ifdef EIGEN2_SUPPORT 427 eigen_assert(!NumTraits<Scalar>::IsInteger); 428#else 429 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) 430#endif 431 return Scalar(0); 432 } 433}; 434 435template<typename Scalar> 436struct sqrt_impl : sqrt_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 437 438template<typename Scalar> 439struct sqrt_retval 440{ 441 typedef Scalar type; 442}; 443 444template<typename Scalar> 445inline EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x) 446{ 447 return EIGEN_MATHFUNC_IMPL(sqrt, Scalar)::run(x); 448} 449 450/**************************************************************************** 451* Implementation of standard unary real functions (exp, log, sin, cos, ... * 452****************************************************************************/ 453 454// This macro instanciate all the necessary template mechanism which is common to all unary real functions. 455#define EIGEN_MATHFUNC_STANDARD_REAL_UNARY(NAME) \ 456 template<typename Scalar, bool IsInteger> struct NAME##_default_impl { \ 457 static inline Scalar run(const Scalar& x) { using std::NAME; return NAME(x); } \ 458 }; \ 459 template<typename Scalar> struct NAME##_default_impl<Scalar, true> { \ 460 static inline Scalar run(const Scalar&) { \ 461 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) \ 462 return Scalar(0); \ 463 } \ 464 }; \ 465 template<typename Scalar> struct NAME##_impl \ 466 : NAME##_default_impl<Scalar, NumTraits<Scalar>::IsInteger> \ 467 {}; \ 468 template<typename Scalar> struct NAME##_retval { typedef Scalar type; }; \ 469 template<typename Scalar> \ 470 inline EIGEN_MATHFUNC_RETVAL(NAME, Scalar) NAME(const Scalar& x) { \ 471 return EIGEN_MATHFUNC_IMPL(NAME, Scalar)::run(x); \ 472 } 473 474EIGEN_MATHFUNC_STANDARD_REAL_UNARY(exp) 475EIGEN_MATHFUNC_STANDARD_REAL_UNARY(log) 476EIGEN_MATHFUNC_STANDARD_REAL_UNARY(sin) 477EIGEN_MATHFUNC_STANDARD_REAL_UNARY(cos) 478EIGEN_MATHFUNC_STANDARD_REAL_UNARY(tan) 479EIGEN_MATHFUNC_STANDARD_REAL_UNARY(asin) 480EIGEN_MATHFUNC_STANDARD_REAL_UNARY(acos) 481 482/**************************************************************************** 483* Implementation of atan2 * 484****************************************************************************/ 485 486template<typename Scalar, bool IsInteger> 487struct atan2_default_impl 488{ 489 typedef Scalar retval; 490 static inline Scalar run(const Scalar& x, const Scalar& y) 491 { 492 using std::atan2; 493 return atan2(x, y); 494 } 495}; 496 497template<typename Scalar> 498struct atan2_default_impl<Scalar, true> 499{ 500 static inline Scalar run(const Scalar&, const Scalar&) 501 { 502 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) 503 return Scalar(0); 504 } 505}; 506 507template<typename Scalar> 508struct atan2_impl : atan2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 509 510template<typename Scalar> 511struct atan2_retval 512{ 513 typedef Scalar type; 514}; 515 516template<typename Scalar> 517inline EIGEN_MATHFUNC_RETVAL(atan2, Scalar) atan2(const Scalar& x, const Scalar& y) 518{ 519 return EIGEN_MATHFUNC_IMPL(atan2, Scalar)::run(x, y); 520} 521 522/**************************************************************************** 523* Implementation of pow * 524****************************************************************************/ 525 526template<typename Scalar, bool IsInteger> 527struct pow_default_impl 528{ 529 typedef Scalar retval; 530 static inline Scalar run(const Scalar& x, const Scalar& y) 531 { 532 using std::pow; 533 return pow(x, y); 534 } 535}; 536 537template<typename Scalar> 538struct pow_default_impl<Scalar, true> 539{ 540 static inline Scalar run(Scalar x, Scalar y) 541 { 542 Scalar res(1); 543 eigen_assert(!NumTraits<Scalar>::IsSigned || y >= 0); 544 if(y & 1) res *= x; 545 y >>= 1; 546 while(y) 547 { 548 x *= x; 549 if(y&1) res *= x; 550 y >>= 1; 551 } 552 return res; 553 } 554}; 555 556template<typename Scalar> 557struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 558 559template<typename Scalar> 560struct pow_retval 561{ 562 typedef Scalar type; 563}; 564 565template<typename Scalar> 566inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y) 567{ 568 return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y); 569} 570 571/**************************************************************************** 572* Implementation of random * 573****************************************************************************/ 574 575template<typename Scalar, 576 bool IsComplex, 577 bool IsInteger> 578struct random_default_impl {}; 579 580template<typename Scalar> 581struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 582 583template<typename Scalar> 584struct random_retval 585{ 586 typedef Scalar type; 587}; 588 589template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y); 590template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(); 591 592template<typename Scalar> 593struct random_default_impl<Scalar, false, false> 594{ 595 static inline Scalar run(const Scalar& x, const Scalar& y) 596 { 597 return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX); 598 } 599 static inline Scalar run() 600 { 601 return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1)); 602 } 603}; 604 605enum { 606 floor_log2_terminate, 607 floor_log2_move_up, 608 floor_log2_move_down, 609 floor_log2_bogus 610}; 611 612template<unsigned int n, int lower, int upper> struct floor_log2_selector 613{ 614 enum { middle = (lower + upper) / 2, 615 value = (upper <= lower + 1) ? int(floor_log2_terminate) 616 : (n < (1 << middle)) ? int(floor_log2_move_down) 617 : (n==0) ? int(floor_log2_bogus) 618 : int(floor_log2_move_up) 619 }; 620}; 621 622template<unsigned int n, 623 int lower = 0, 624 int upper = sizeof(unsigned int) * CHAR_BIT - 1, 625 int selector = floor_log2_selector<n, lower, upper>::value> 626struct floor_log2 {}; 627 628template<unsigned int n, int lower, int upper> 629struct floor_log2<n, lower, upper, floor_log2_move_down> 630{ 631 enum { value = floor_log2<n, lower, floor_log2_selector<n, lower, upper>::middle>::value }; 632}; 633 634template<unsigned int n, int lower, int upper> 635struct floor_log2<n, lower, upper, floor_log2_move_up> 636{ 637 enum { value = floor_log2<n, floor_log2_selector<n, lower, upper>::middle, upper>::value }; 638}; 639 640template<unsigned int n, int lower, int upper> 641struct floor_log2<n, lower, upper, floor_log2_terminate> 642{ 643 enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; 644}; 645 646template<unsigned int n, int lower, int upper> 647struct floor_log2<n, lower, upper, floor_log2_bogus> 648{ 649 // no value, error at compile time 650}; 651 652template<typename Scalar> 653struct random_default_impl<Scalar, false, true> 654{ 655 typedef typename NumTraits<Scalar>::NonInteger NonInteger; 656 657 static inline Scalar run(const Scalar& x, const Scalar& y) 658 { 659 return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1))); 660 } 661 662 static inline Scalar run() 663 { 664#ifdef EIGEN_MAKING_DOCS 665 return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10)); 666#else 667 enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value, 668 scalar_bits = sizeof(Scalar) * CHAR_BIT, 669 shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)) 670 }; 671 Scalar x = Scalar(std::rand() >> shift); 672 Scalar offset = NumTraits<Scalar>::IsSigned ? Scalar(1 << (rand_bits-1)) : Scalar(0); 673 return x - offset; 674#endif 675 } 676}; 677 678template<typename Scalar> 679struct random_default_impl<Scalar, true, false> 680{ 681 static inline Scalar run(const Scalar& x, const Scalar& y) 682 { 683 return Scalar(random(real(x), real(y)), 684 random(imag(x), imag(y))); 685 } 686 static inline Scalar run() 687 { 688 typedef typename NumTraits<Scalar>::Real RealScalar; 689 return Scalar(random<RealScalar>(), random<RealScalar>()); 690 } 691}; 692 693template<typename Scalar> 694inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y) 695{ 696 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y); 697} 698 699template<typename Scalar> 700inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() 701{ 702 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(); 703} 704 705/**************************************************************************** 706* Implementation of fuzzy comparisons * 707****************************************************************************/ 708 709template<typename Scalar, 710 bool IsComplex, 711 bool IsInteger> 712struct scalar_fuzzy_default_impl {}; 713 714template<typename Scalar> 715struct scalar_fuzzy_default_impl<Scalar, false, false> 716{ 717 typedef typename NumTraits<Scalar>::Real RealScalar; 718 template<typename OtherScalar> 719 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) 720 { 721 return abs(x) <= abs(y) * prec; 722 } 723 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) 724 { 725 using std::min; 726 return abs(x - y) <= (min)(abs(x), abs(y)) * prec; 727 } 728 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec) 729 { 730 return x <= y || isApprox(x, y, prec); 731 } 732}; 733 734template<typename Scalar> 735struct scalar_fuzzy_default_impl<Scalar, false, true> 736{ 737 typedef typename NumTraits<Scalar>::Real RealScalar; 738 template<typename OtherScalar> 739 static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&) 740 { 741 return x == Scalar(0); 742 } 743 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&) 744 { 745 return x == y; 746 } 747 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&) 748 { 749 return x <= y; 750 } 751}; 752 753template<typename Scalar> 754struct scalar_fuzzy_default_impl<Scalar, true, false> 755{ 756 typedef typename NumTraits<Scalar>::Real RealScalar; 757 template<typename OtherScalar> 758 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) 759 { 760 return abs2(x) <= abs2(y) * prec * prec; 761 } 762 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) 763 { 764 using std::min; 765 return abs2(x - y) <= (min)(abs2(x), abs2(y)) * prec * prec; 766 } 767}; 768 769template<typename Scalar> 770struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 771 772template<typename Scalar, typename OtherScalar> 773inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, 774 typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) 775{ 776 return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision); 777} 778 779template<typename Scalar> 780inline bool isApprox(const Scalar& x, const Scalar& y, 781 typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) 782{ 783 return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision); 784} 785 786template<typename Scalar> 787inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, 788 typename NumTraits<Scalar>::Real precision = NumTraits<Scalar>::dummy_precision()) 789{ 790 return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision); 791} 792 793/****************************************** 794*** The special case of the bool type *** 795******************************************/ 796 797template<> struct random_impl<bool> 798{ 799 static inline bool run() 800 { 801 return random<int>(0,1)==0 ? false : true; 802 } 803}; 804 805template<> struct scalar_fuzzy_impl<bool> 806{ 807 typedef bool RealScalar; 808 809 template<typename OtherScalar> 810 static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&) 811 { 812 return !x; 813 } 814 815 static inline bool isApprox(bool x, bool y, bool) 816 { 817 return x == y; 818 } 819 820 static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&) 821 { 822 return (!x) || y; 823 } 824 825}; 826 827/**************************************************************************** 828* Special functions * 829****************************************************************************/ 830 831// std::isfinite is non standard, so let's define our own version, 832// even though it is not very efficient. 833template<typename T> bool (isfinite)(const T& x) 834{ 835 return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest(); 836} 837 838} // end namespace internal 839 840} // end namespace Eigen 841 842#endif // EIGEN_MATHFUNCTIONS_H 843