1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1 (at) gmail.com> 5 // 6 // This Source Code Form is subject to the terms of the Mozilla 7 // Public License v. 2.0. If a copy of the MPL was not distributed 8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10 #ifndef EIGEN_MATHFUNCTIONS_H 11 #define EIGEN_MATHFUNCTIONS_H 12 13 namespace Eigen { 14 15 namespace internal { 16 17 /** \internal \struct global_math_functions_filtering_base 18 * 19 * What it does: 20 * Defines a typedef 'type' as follows: 21 * - if type T has a member typedef Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then 22 * global_math_functions_filtering_base<T>::type is a typedef for it. 23 * - otherwise, global_math_functions_filtering_base<T>::type is a typedef for T. 24 * 25 * How it's used: 26 * To allow to defined the global math functions (like sin...) in certain cases, like the Array expressions. 27 * When you do sin(array1+array2), the object array1+array2 has a complicated expression type, all what you want to know 28 * is that it inherits ArrayBase. So we implement a partial specialization of sin_impl for ArrayBase<Derived>. 29 * So we must make sure to use sin_impl<ArrayBase<Derived> > and not sin_impl<Derived>, otherwise our partial specialization 30 * won't be used. How does sin know that? That's exactly what global_math_functions_filtering_base tells it. 31 * 32 * How it's implemented: 33 * SFINAE in the style of enable_if. Highly susceptible of breaking compilers. With GCC, it sure does work, but if you replace 34 * the typename dummy by an integer template parameter, it doesn't work anymore! 35 */ 36 37 template<typename T, typename dummy = void> 38 struct global_math_functions_filtering_base 39 { 40 typedef T type; 41 }; 42 43 template<typename T> struct always_void { typedef void type; }; 44 45 template<typename T> 46 struct global_math_functions_filtering_base 47 <T, 48 typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type 49 > 50 { 51 typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type; 52 }; 53 54 #define EIGEN_MATHFUNC_IMPL(func, scalar) 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 62 template<typename Scalar> 63 struct 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 72 template<typename RealScalar> 73 struct 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 82 template<typename Scalar> 83 struct real_retval 84 { 85 typedef typename NumTraits<Scalar>::Real type; 86 }; 87 88 template<typename Scalar> 89 inline 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 98 template<typename Scalar> 99 struct 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 108 template<typename RealScalar> 109 struct 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 118 template<typename Scalar> 119 struct imag_retval 120 { 121 typedef typename NumTraits<Scalar>::Real type; 122 }; 123 124 template<typename Scalar> 125 inline 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 134 template<typename Scalar> 135 struct 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 148 template<typename Scalar> 149 struct real_ref_retval 150 { 151 typedef typename NumTraits<Scalar>::Real & type; 152 }; 153 154 template<typename Scalar> 155 inline 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 160 template<typename Scalar> 161 inline 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 170 template<typename Scalar, bool IsComplex> 171 struct 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 184 template<typename Scalar> 185 struct 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 197 template<typename Scalar> 198 struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 199 200 template<typename Scalar> 201 struct imag_ref_retval 202 { 203 typedef typename NumTraits<Scalar>::Real & type; 204 }; 205 206 template<typename Scalar> 207 inline 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 212 template<typename Scalar> 213 inline 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 222 template<typename Scalar> 223 struct conj_impl 224 { 225 static inline Scalar run(const Scalar& x) 226 { 227 return x; 228 } 229 }; 230 231 template<typename RealScalar> 232 struct 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 241 template<typename Scalar> 242 struct conj_retval 243 { 244 typedef Scalar type; 245 }; 246 247 template<typename Scalar> 248 inline 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 257 template<typename Scalar> 258 struct 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 268 template<typename Scalar> 269 struct abs_retval 270 { 271 typedef typename NumTraits<Scalar>::Real type; 272 }; 273 274 template<typename Scalar> 275 inline 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 284 template<typename Scalar> 285 struct 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 294 template<typename RealScalar> 295 struct 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 303 template<typename Scalar> 304 struct abs2_retval 305 { 306 typedef typename NumTraits<Scalar>::Real type; 307 }; 308 309 template<typename Scalar> 310 inline 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 319 template<typename Scalar, bool IsComplex> 320 struct 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 329 template<typename Scalar> 330 struct norm1_default_impl<Scalar, false> 331 { 332 static inline Scalar run(const Scalar& x) 333 { 334 return abs(x); 335 } 336 }; 337 338 template<typename Scalar> 339 struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; 340 341 template<typename Scalar> 342 struct norm1_retval 343 { 344 typedef typename NumTraits<Scalar>::Real type; 345 }; 346 347 template<typename Scalar> 348 inline 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 357 template<typename Scalar> 358 struct 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 374 template<typename Scalar> 375 struct hypot_retval 376 { 377 typedef typename NumTraits<Scalar>::Real type; 378 }; 379 380 template<typename Scalar> 381 inline 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 390 template<typename OldType, typename NewType> 391 struct 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 401 template<typename OldType, typename NewType> 402 inline NewType cast(const OldType& x) 403 { 404 return cast_impl<OldType, NewType>::run(x); 405 } 406 407 /**************************************************************************** 408 * Implementation of sqrt * 409 ****************************************************************************/ 410 411 template<typename Scalar, bool IsInteger> 412 struct sqrt_default_impl 413 { 414 static inline Scalar run(const Scalar& x) 415 { 416 using std::sqrt; 417 return sqrt(x); 418 } 419 }; 420 421 template<typename Scalar> 422 struct 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 435 template<typename Scalar> 436 struct sqrt_impl : sqrt_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 437 438 template<typename Scalar> 439 struct sqrt_retval 440 { 441 typedef Scalar type; 442 }; 443 444 template<typename Scalar> 445 inline 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 474 EIGEN_MATHFUNC_STANDARD_REAL_UNARY(exp) 475 EIGEN_MATHFUNC_STANDARD_REAL_UNARY(log) 476 EIGEN_MATHFUNC_STANDARD_REAL_UNARY(sin) 477 EIGEN_MATHFUNC_STANDARD_REAL_UNARY(cos) 478 EIGEN_MATHFUNC_STANDARD_REAL_UNARY(tan) 479 EIGEN_MATHFUNC_STANDARD_REAL_UNARY(asin) 480 EIGEN_MATHFUNC_STANDARD_REAL_UNARY(acos) 481 482 /**************************************************************************** 483 * Implementation of atan2 * 484 ****************************************************************************/ 485 486 template<typename Scalar, bool IsInteger> 487 struct 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 497 template<typename Scalar> 498 struct 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 507 template<typename Scalar> 508 struct atan2_impl : atan2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 509 510 template<typename Scalar> 511 struct atan2_retval 512 { 513 typedef Scalar type; 514 }; 515 516 template<typename Scalar> 517 inline 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 526 template<typename Scalar, bool IsInteger> 527 struct 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 537 template<typename Scalar> 538 struct 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 556 template<typename Scalar> 557 struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {}; 558 559 template<typename Scalar> 560 struct pow_retval 561 { 562 typedef Scalar type; 563 }; 564 565 template<typename Scalar> 566 inline 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 575 template<typename Scalar, 576 bool IsComplex, 577 bool IsInteger> 578 struct random_default_impl {}; 579 580 template<typename Scalar> 581 struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 582 583 template<typename Scalar> 584 struct random_retval 585 { 586 typedef Scalar type; 587 }; 588 589 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y); 590 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(); 591 592 template<typename Scalar> 593 struct 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 605 enum { 606 floor_log2_terminate, 607 floor_log2_move_up, 608 floor_log2_move_down, 609 floor_log2_bogus 610 }; 611 612 template<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 622 template<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> 626 struct floor_log2 {}; 627 628 template<unsigned int n, int lower, int upper> 629 struct 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 634 template<unsigned int n, int lower, int upper> 635 struct 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 640 template<unsigned int n, int lower, int upper> 641 struct floor_log2<n, lower, upper, floor_log2_terminate> 642 { 643 enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; 644 }; 645 646 template<unsigned int n, int lower, int upper> 647 struct floor_log2<n, lower, upper, floor_log2_bogus> 648 { 649 // no value, error at compile time 650 }; 651 652 template<typename Scalar> 653 struct 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 678 template<typename Scalar> 679 struct 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 693 template<typename Scalar> 694 inline 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 699 template<typename Scalar> 700 inline 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 709 template<typename Scalar, 710 bool IsComplex, 711 bool IsInteger> 712 struct scalar_fuzzy_default_impl {}; 713 714 template<typename Scalar> 715 struct 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 734 template<typename Scalar> 735 struct 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 753 template<typename Scalar> 754 struct 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 769 template<typename Scalar> 770 struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; 771 772 template<typename Scalar, typename OtherScalar> 773 inline 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 779 template<typename Scalar> 780 inline 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 786 template<typename Scalar> 787 inline 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 797 template<> struct random_impl<bool> 798 { 799 static inline bool run() 800 { 801 return random<int>(0,1)==0 ? false : true; 802 } 803 }; 804 805 template<> 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. 833 template<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