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