Eigen  3.2.9
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
MathFunctions.h
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 
13 namespace Eigen {
14 
15 namespace internal {
16 
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,bool IsComplex>
222 struct abs2_impl_default
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 Scalar>
232 struct abs2_impl_default<Scalar, true> // IsComplex
233 {
234  typedef typename NumTraits<Scalar>::Real RealScalar;
235  static inline RealScalar run(const Scalar& x)
236  {
237  return real(x)*real(x) + imag(x)*imag(x);
238  }
239 };
240 
241 template<typename Scalar>
242 struct abs2_impl
243 {
244  typedef typename NumTraits<Scalar>::Real RealScalar;
245  static inline RealScalar run(const Scalar& x)
246  {
247  return abs2_impl_default<Scalar,NumTraits<Scalar>::IsComplex>::run(x);
248  }
249 };
250 
251 template<typename Scalar>
252 struct abs2_retval
253 {
254  typedef typename NumTraits<Scalar>::Real type;
255 };
256 
257 /****************************************************************************
258 * Implementation of norm1 *
259 ****************************************************************************/
260 
261 template<typename Scalar, bool IsComplex>
262 struct norm1_default_impl
263 {
264  typedef typename NumTraits<Scalar>::Real RealScalar;
265  static inline RealScalar run(const Scalar& x)
266  {
267  using std::abs;
268  return abs(real(x)) + abs(imag(x));
269  }
270 };
271 
272 template<typename Scalar>
273 struct norm1_default_impl<Scalar, false>
274 {
275  static inline Scalar run(const Scalar& x)
276  {
277  using std::abs;
278  return abs(x);
279  }
280 };
281 
282 template<typename Scalar>
283 struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {};
284 
285 template<typename Scalar>
286 struct norm1_retval
287 {
288  typedef typename NumTraits<Scalar>::Real type;
289 };
290 
291 /****************************************************************************
292 * Implementation of hypot *
293 ****************************************************************************/
294 
295 template<typename Scalar>
296 struct hypot_impl
297 {
298  typedef typename NumTraits<Scalar>::Real RealScalar;
299  static inline RealScalar run(const Scalar& x, const Scalar& y)
300  {
301  using std::max;
302  using std::min;
303  using std::abs;
304  using std::sqrt;
305  RealScalar _x = abs(x);
306  RealScalar _y = abs(y);
307  RealScalar p = (max)(_x, _y);
308  if(p==RealScalar(0)) return RealScalar(0);
309  RealScalar q = (min)(_x, _y);
310  RealScalar qp = q/p;
311  return p * sqrt(RealScalar(1) + qp*qp);
312  }
313 };
314 
315 template<typename Scalar>
316 struct hypot_retval
317 {
318  typedef typename NumTraits<Scalar>::Real type;
319 };
320 
321 /****************************************************************************
322 * Implementation of cast *
323 ****************************************************************************/
324 
325 template<typename OldType, typename NewType>
326 struct cast_impl
327 {
328  static inline NewType run(const OldType& x)
329  {
330  return static_cast<NewType>(x);
331  }
332 };
333 
334 // here, for once, we're plainly returning NewType: we don't want cast to do weird things.
335 
336 template<typename OldType, typename NewType>
337 inline NewType cast(const OldType& x)
338 {
339  return cast_impl<OldType, NewType>::run(x);
340 }
341 
342 /****************************************************************************
343 * Implementation of atanh2 *
344 ****************************************************************************/
345 
346 template<typename Scalar, bool IsInteger>
347 struct atanh2_default_impl
348 {
349  typedef Scalar retval;
350  typedef typename NumTraits<Scalar>::Real RealScalar;
351  static inline Scalar run(const Scalar& x, const Scalar& y)
352  {
353  using std::abs;
354  using std::log;
355  using std::sqrt;
356  Scalar z = x / y;
357  if (y == Scalar(0) || abs(z) > sqrt(NumTraits<RealScalar>::epsilon()))
358  return RealScalar(0.5) * log((y + x) / (y - x));
359  else
360  return z + z*z*z / RealScalar(3);
361  }
362 };
363 
364 template<typename Scalar>
365 struct atanh2_default_impl<Scalar, true>
366 {
367  static inline Scalar run(const Scalar&, const Scalar&)
368  {
369  EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
370  return Scalar(0);
371  }
372 };
373 
374 template<typename Scalar>
375 struct atanh2_impl : atanh2_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
376 
377 template<typename Scalar>
378 struct atanh2_retval
379 {
380  typedef Scalar type;
381 };
382 
383 /****************************************************************************
384 * Implementation of pow *
385 ****************************************************************************/
386 
387 template<typename Scalar, bool IsInteger>
388 struct pow_default_impl
389 {
390  typedef Scalar retval;
391  static inline Scalar run(const Scalar& x, const Scalar& y)
392  {
393  using std::pow;
394  return pow(x, y);
395  }
396 };
397 
398 template<typename Scalar>
399 struct pow_default_impl<Scalar, true>
400 {
401  static inline Scalar run(Scalar x, Scalar y)
402  {
403  Scalar res(1);
404  eigen_assert(!NumTraits<Scalar>::IsSigned || y >= 0);
405  if(y & 1) res *= x;
406  y >>= 1;
407  while(y)
408  {
409  x *= x;
410  if(y&1) res *= x;
411  y >>= 1;
412  }
413  return res;
414  }
415 };
416 
417 template<typename Scalar>
418 struct pow_impl : pow_default_impl<Scalar, NumTraits<Scalar>::IsInteger> {};
419 
420 template<typename Scalar>
421 struct pow_retval
422 {
423  typedef Scalar type;
424 };
425 
426 /****************************************************************************
427 * Implementation of random *
428 ****************************************************************************/
429 
430 template<typename Scalar,
431  bool IsComplex,
432  bool IsInteger>
433 struct random_default_impl {};
434 
435 template<typename Scalar>
436 struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
437 
438 template<typename Scalar>
439 struct random_retval
440 {
441  typedef Scalar type;
442 };
443 
444 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y);
445 template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random();
446 
447 template<typename Scalar>
448 struct random_default_impl<Scalar, false, false>
449 {
450  static inline Scalar run(const Scalar& x, const Scalar& y)
451  {
452  return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX);
453  }
454  static inline Scalar run()
455  {
456  return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1));
457  }
458 };
459 
460 enum {
461  floor_log2_terminate,
462  floor_log2_move_up,
463  floor_log2_move_down,
464  floor_log2_bogus
465 };
466 
467 template<unsigned int n, int lower, int upper> struct floor_log2_selector
468 {
469  enum { middle = (lower + upper) / 2,
470  value = (upper <= lower + 1) ? int(floor_log2_terminate)
471  : (n < (1 << middle)) ? int(floor_log2_move_down)
472  : (n==0) ? int(floor_log2_bogus)
473  : int(floor_log2_move_up)
474  };
475 };
476 
477 template<unsigned int n,
478  int lower = 0,
479  int upper = sizeof(unsigned int) * CHAR_BIT - 1,
480  int selector = floor_log2_selector<n, lower, upper>::value>
481 struct floor_log2 {};
482 
483 template<unsigned int n, int lower, int upper>
484 struct floor_log2<n, lower, upper, floor_log2_move_down>
485 {
486  enum { value = floor_log2<n, lower, floor_log2_selector<n, lower, upper>::middle>::value };
487 };
488 
489 template<unsigned int n, int lower, int upper>
490 struct floor_log2<n, lower, upper, floor_log2_move_up>
491 {
492  enum { value = floor_log2<n, floor_log2_selector<n, lower, upper>::middle, upper>::value };
493 };
494 
495 template<unsigned int n, int lower, int upper>
496 struct floor_log2<n, lower, upper, floor_log2_terminate>
497 {
498  enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower };
499 };
500 
501 template<unsigned int n, int lower, int upper>
502 struct floor_log2<n, lower, upper, floor_log2_bogus>
503 {
504  // no value, error at compile time
505 };
506 
507 template<typename Scalar>
508 struct random_default_impl<Scalar, false, true>
509 {
510  typedef typename NumTraits<Scalar>::NonInteger NonInteger;
511 
512  static inline Scalar run(const Scalar& x, const Scalar& y)
513  {
514  return x + Scalar((NonInteger(y)-x+1) * std::rand() / (RAND_MAX + NonInteger(1)));
515  }
516 
517  static inline Scalar run()
518  {
519 #ifdef EIGEN_MAKING_DOCS
520  return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10));
521 #else
522  enum { rand_bits = floor_log2<(unsigned int)(RAND_MAX)+1>::value,
523  scalar_bits = sizeof(Scalar) * CHAR_BIT,
524  shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)),
525  offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0
526  };
527  return Scalar((std::rand() >> shift) - offset);
528 #endif
529  }
530 };
531 
532 template<typename Scalar>
533 struct random_default_impl<Scalar, true, false>
534 {
535  static inline Scalar run(const Scalar& x, const Scalar& y)
536  {
537  return Scalar(random(real(x), real(y)),
538  random(imag(x), imag(y)));
539  }
540  static inline Scalar run()
541  {
542  typedef typename NumTraits<Scalar>::Real RealScalar;
543  return Scalar(random<RealScalar>(), random<RealScalar>());
544  }
545 };
546 
547 template<typename Scalar>
548 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y)
549 {
550  return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y);
551 }
552 
553 template<typename Scalar>
554 inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
555 {
556  return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
557 }
558 
559 } // end namespace internal
560 
561 /****************************************************************************
562 * Generic math function *
563 ****************************************************************************/
564 
565 namespace numext {
566 
567 template<typename Scalar>
568 inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
569 {
570  return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
571 }
572 
573 template<typename Scalar>
574 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
575 {
576  return internal::real_ref_impl<Scalar>::run(x);
577 }
578 
579 template<typename Scalar>
580 inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
581 {
582  return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
583 }
584 
585 template<typename Scalar>
586 inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
587 {
588  return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
589 }
590 
591 template<typename Scalar>
592 inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
593 {
594  return internal::imag_ref_impl<Scalar>::run(x);
595 }
596 
597 template<typename Scalar>
598 inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
599 {
600  return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
601 }
602 
603 template<typename Scalar>
604 inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
605 {
606  return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
607 }
608 
609 template<typename Scalar>
610 inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
611 {
612  return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
613 }
614 
615 template<typename Scalar>
616 inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
617 {
618  return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
619 }
620 
621 template<typename Scalar>
622 inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
623 {
624  return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
625 }
626 
627 template<typename Scalar>
628 inline EIGEN_MATHFUNC_RETVAL(atanh2, Scalar) atanh2(const Scalar& x, const Scalar& y)
629 {
630  return EIGEN_MATHFUNC_IMPL(atanh2, Scalar)::run(x, y);
631 }
632 
633 template<typename Scalar>
634 inline EIGEN_MATHFUNC_RETVAL(pow, Scalar) pow(const Scalar& x, const Scalar& y)
635 {
636  return EIGEN_MATHFUNC_IMPL(pow, Scalar)::run(x, y);
637 }
638 
639 // std::isfinite is non standard, so let's define our own version,
640 // even though it is not very efficient.
641 template<typename T> bool (isfinite)(const T& x)
642 {
643  return x<NumTraits<T>::highest() && x>NumTraits<T>::lowest();
644 }
645 
646 } // end namespace numext
647 
648 namespace internal {
649 
650 /****************************************************************************
651 * Implementation of fuzzy comparisons *
652 ****************************************************************************/
653 
654 template<typename Scalar,
655  bool IsComplex,
656  bool IsInteger>
657 struct scalar_fuzzy_default_impl {};
658 
659 template<typename Scalar>
660 struct scalar_fuzzy_default_impl<Scalar, false, false>
661 {
662  typedef typename NumTraits<Scalar>::Real RealScalar;
663  template<typename OtherScalar>
664  static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
665  {
666  using std::abs;
667  return abs(x) <= abs(y) * prec;
668  }
669  static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
670  {
671  using std::min;
672  using std::abs;
673  return abs(x - y) <= (min)(abs(x), abs(y)) * prec;
674  }
675  static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
676  {
677  return x <= y || isApprox(x, y, prec);
678  }
679 };
680 
681 template<typename Scalar>
682 struct scalar_fuzzy_default_impl<Scalar, false, true>
683 {
684  typedef typename NumTraits<Scalar>::Real RealScalar;
685  template<typename OtherScalar>
686  static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&)
687  {
688  return x == Scalar(0);
689  }
690  static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&)
691  {
692  return x == y;
693  }
694  static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&)
695  {
696  return x <= y;
697  }
698 };
699 
700 template<typename Scalar>
701 struct scalar_fuzzy_default_impl<Scalar, true, false>
702 {
703  typedef typename NumTraits<Scalar>::Real RealScalar;
704  template<typename OtherScalar>
705  static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
706  {
707  return numext::abs2(x) <= numext::abs2(y) * prec * prec;
708  }
709  static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
710  {
711  using std::min;
712  return numext::abs2(x - y) <= (min)(numext::abs2(x), numext::abs2(y)) * prec * prec;
713  }
714 };
715 
716 template<typename Scalar>
717 struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
718 
719 template<typename Scalar, typename OtherScalar>
720 inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
721  const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
722 {
723  return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
724 }
725 
726 template<typename Scalar>
727 inline bool isApprox(const Scalar& x, const Scalar& y,
728  const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
729 {
730  return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
731 }
732 
733 template<typename Scalar>
734 inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
735  const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
736 {
737  return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
738 }
739 
740 /******************************************
741 *** The special case of the bool type ***
742 ******************************************/
743 
744 template<> struct random_impl<bool>
745 {
746  static inline bool run()
747  {
748  return random<int>(0,1)==0 ? false : true;
749  }
750 };
751 
752 template<> struct scalar_fuzzy_impl<bool>
753 {
754  typedef bool RealScalar;
755 
756  template<typename OtherScalar>
757  static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&)
758  {
759  return !x;
760  }
761 
762  static inline bool isApprox(bool x, bool y, bool)
763  {
764  return x == y;
765  }
766 
767  static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&)
768  {
769  return (!x) || y;
770  }
771 
772 };
773 
774 
775 } // end namespace internal
776 
777 } // end namespace Eigen
778 
779 #endif // EIGEN_MATHFUNCTIONS_H