Please, help us to better know about our user community by answering the following short survey: https://forms.gle/wpyrxWi18ox9Z5ae9
Eigen  3.4.0
 
Loading...
Searching...
No Matches
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// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11#ifndef EIGEN_MATHFUNCTIONS_H
12#define EIGEN_MATHFUNCTIONS_H
13
14// TODO this should better be moved to NumTraits
15// Source: WolframAlpha
16#define EIGEN_PI 3.141592653589793238462643383279502884197169399375105820974944592307816406L
17#define EIGEN_LOG2E 1.442695040888963407359924681001892137426645954152985934135449406931109219L
18#define EIGEN_LN2 0.693147180559945309417232121458176568075500134360255254120680009493393621L
19
20namespace Eigen {
21
22// On WINCE, std::abs is defined for int only, so let's defined our own overloads:
23// This issue has been confirmed with MSVC 2008 only, but the issue might exist for more recent versions too.
24#if EIGEN_OS_WINCE && EIGEN_COMP_MSVC && EIGEN_COMP_MSVC<=1500
25long abs(long x) { return (labs(x)); }
26double abs(double x) { return (fabs(x)); }
27float abs(float x) { return (fabsf(x)); }
28long double abs(long double x) { return (fabsl(x)); }
29#endif
30
31namespace internal {
32
53template<typename T, typename dummy = void>
54struct global_math_functions_filtering_base
55{
56 typedef T type;
57};
58
59template<typename T> struct always_void { typedef void type; };
60
61template<typename T>
62struct global_math_functions_filtering_base
63 <T,
64 typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type
65 >
66{
67 typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type;
68};
69
70#define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>
71#define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type
72
73/****************************************************************************
74* Implementation of real *
75****************************************************************************/
76
77template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
78struct real_default_impl
79{
80 typedef typename NumTraits<Scalar>::Real RealScalar;
81 EIGEN_DEVICE_FUNC
82 static inline RealScalar run(const Scalar& x)
83 {
84 return x;
85 }
86};
87
88template<typename Scalar>
89struct real_default_impl<Scalar,true>
90{
91 typedef typename NumTraits<Scalar>::Real RealScalar;
92 EIGEN_DEVICE_FUNC
93 static inline RealScalar run(const Scalar& x)
94 {
95 using std::real;
96 return real(x);
97 }
98};
99
100template<typename Scalar> struct real_impl : real_default_impl<Scalar> {};
101
102#if defined(EIGEN_GPU_COMPILE_PHASE)
103template<typename T>
104struct real_impl<std::complex<T> >
105{
106 typedef T RealScalar;
107 EIGEN_DEVICE_FUNC
108 static inline T run(const std::complex<T>& x)
109 {
110 return x.real();
111 }
112};
113#endif
114
115template<typename Scalar>
116struct real_retval
117{
118 typedef typename NumTraits<Scalar>::Real type;
119};
120
121/****************************************************************************
122* Implementation of imag *
123****************************************************************************/
124
125template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
126struct imag_default_impl
127{
128 typedef typename NumTraits<Scalar>::Real RealScalar;
129 EIGEN_DEVICE_FUNC
130 static inline RealScalar run(const Scalar&)
131 {
132 return RealScalar(0);
133 }
134};
135
136template<typename Scalar>
137struct imag_default_impl<Scalar,true>
138{
139 typedef typename NumTraits<Scalar>::Real RealScalar;
140 EIGEN_DEVICE_FUNC
141 static inline RealScalar run(const Scalar& x)
142 {
143 using std::imag;
144 return imag(x);
145 }
146};
147
148template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {};
149
150#if defined(EIGEN_GPU_COMPILE_PHASE)
151template<typename T>
152struct imag_impl<std::complex<T> >
153{
154 typedef T RealScalar;
155 EIGEN_DEVICE_FUNC
156 static inline T run(const std::complex<T>& x)
157 {
158 return x.imag();
159 }
160};
161#endif
162
163template<typename Scalar>
164struct imag_retval
165{
166 typedef typename NumTraits<Scalar>::Real type;
167};
168
169/****************************************************************************
170* Implementation of real_ref *
171****************************************************************************/
172
173template<typename Scalar>
174struct real_ref_impl
175{
176 typedef typename NumTraits<Scalar>::Real RealScalar;
177 EIGEN_DEVICE_FUNC
178 static inline RealScalar& run(Scalar& x)
179 {
180 return reinterpret_cast<RealScalar*>(&x)[0];
181 }
182 EIGEN_DEVICE_FUNC
183 static inline const RealScalar& run(const Scalar& x)
184 {
185 return reinterpret_cast<const RealScalar*>(&x)[0];
186 }
187};
188
189template<typename Scalar>
190struct real_ref_retval
191{
192 typedef typename NumTraits<Scalar>::Real & type;
193};
194
195/****************************************************************************
196* Implementation of imag_ref *
197****************************************************************************/
198
199template<typename Scalar, bool IsComplex>
200struct imag_ref_default_impl
201{
202 typedef typename NumTraits<Scalar>::Real RealScalar;
203 EIGEN_DEVICE_FUNC
204 static inline RealScalar& run(Scalar& x)
205 {
206 return reinterpret_cast<RealScalar*>(&x)[1];
207 }
208 EIGEN_DEVICE_FUNC
209 static inline const RealScalar& run(const Scalar& x)
210 {
211 return reinterpret_cast<RealScalar*>(&x)[1];
212 }
213};
214
215template<typename Scalar>
216struct imag_ref_default_impl<Scalar, false>
217{
218 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
219 static inline Scalar run(Scalar&)
220 {
221 return Scalar(0);
222 }
223 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
224 static inline const Scalar run(const Scalar&)
225 {
226 return Scalar(0);
227 }
228};
229
230template<typename Scalar>
231struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {};
232
233template<typename Scalar>
234struct imag_ref_retval
235{
236 typedef typename NumTraits<Scalar>::Real & type;
237};
238
239/****************************************************************************
240* Implementation of conj *
241****************************************************************************/
242
243template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
244struct conj_default_impl
245{
246 EIGEN_DEVICE_FUNC
247 static inline Scalar run(const Scalar& x)
248 {
249 return x;
250 }
251};
252
253template<typename Scalar>
254struct conj_default_impl<Scalar,true>
255{
256 EIGEN_DEVICE_FUNC
257 static inline Scalar run(const Scalar& x)
258 {
259 using std::conj;
260 return conj(x);
261 }
262};
263
264template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
265struct conj_impl : conj_default_impl<Scalar, IsComplex> {};
266
267template<typename Scalar>
268struct conj_retval
269{
270 typedef Scalar type;
271};
272
273/****************************************************************************
274* Implementation of abs2 *
275****************************************************************************/
276
277template<typename Scalar,bool IsComplex>
278struct abs2_impl_default
279{
280 typedef typename NumTraits<Scalar>::Real RealScalar;
281 EIGEN_DEVICE_FUNC
282 static inline RealScalar run(const Scalar& x)
283 {
284 return x*x;
285 }
286};
287
288template<typename Scalar>
289struct abs2_impl_default<Scalar, true> // IsComplex
290{
291 typedef typename NumTraits<Scalar>::Real RealScalar;
292 EIGEN_DEVICE_FUNC
293 static inline RealScalar run(const Scalar& x)
294 {
295 return x.real()*x.real() + x.imag()*x.imag();
296 }
297};
298
299template<typename Scalar>
300struct abs2_impl
301{
302 typedef typename NumTraits<Scalar>::Real RealScalar;
303 EIGEN_DEVICE_FUNC
304 static inline RealScalar run(const Scalar& x)
305 {
306 return abs2_impl_default<Scalar,NumTraits<Scalar>::IsComplex>::run(x);
307 }
308};
309
310template<typename Scalar>
311struct abs2_retval
312{
313 typedef typename NumTraits<Scalar>::Real type;
314};
315
316/****************************************************************************
317* Implementation of sqrt/rsqrt *
318****************************************************************************/
319
320template<typename Scalar>
321struct sqrt_impl
322{
323 EIGEN_DEVICE_FUNC
324 static EIGEN_ALWAYS_INLINE Scalar run(const Scalar& x)
325 {
326 EIGEN_USING_STD(sqrt);
327 return sqrt(x);
328 }
329};
330
331// Complex sqrt defined in MathFunctionsImpl.h.
332template<typename T> EIGEN_DEVICE_FUNC std::complex<T> complex_sqrt(const std::complex<T>& a_x);
333
334// Custom implementation is faster than `std::sqrt`, works on
335// GPU, and correctly handles special cases (unlike MSVC).
336template<typename T>
337struct sqrt_impl<std::complex<T> >
338{
339 EIGEN_DEVICE_FUNC
340 static EIGEN_ALWAYS_INLINE std::complex<T> run(const std::complex<T>& x)
341 {
342 return complex_sqrt<T>(x);
343 }
344};
345
346template<typename Scalar>
347struct sqrt_retval
348{
349 typedef Scalar type;
350};
351
352// Default implementation relies on numext::sqrt, at bottom of file.
353template<typename T>
354struct rsqrt_impl;
355
356// Complex rsqrt defined in MathFunctionsImpl.h.
357template<typename T> EIGEN_DEVICE_FUNC std::complex<T> complex_rsqrt(const std::complex<T>& a_x);
358
359template<typename T>
360struct rsqrt_impl<std::complex<T> >
361{
362 EIGEN_DEVICE_FUNC
363 static EIGEN_ALWAYS_INLINE std::complex<T> run(const std::complex<T>& x)
364 {
365 return complex_rsqrt<T>(x);
366 }
367};
368
369template<typename Scalar>
370struct rsqrt_retval
371{
372 typedef Scalar type;
373};
374
375/****************************************************************************
376* Implementation of norm1 *
377****************************************************************************/
378
379template<typename Scalar, bool IsComplex>
380struct norm1_default_impl;
381
382template<typename Scalar>
383struct norm1_default_impl<Scalar,true>
384{
385 typedef typename NumTraits<Scalar>::Real RealScalar;
386 EIGEN_DEVICE_FUNC
387 static inline RealScalar run(const Scalar& x)
388 {
389 EIGEN_USING_STD(abs);
390 return abs(x.real()) + abs(x.imag());
391 }
392};
393
394template<typename Scalar>
395struct norm1_default_impl<Scalar, false>
396{
397 EIGEN_DEVICE_FUNC
398 static inline Scalar run(const Scalar& x)
399 {
400 EIGEN_USING_STD(abs);
401 return abs(x);
402 }
403};
404
405template<typename Scalar>
406struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {};
407
408template<typename Scalar>
409struct norm1_retval
410{
411 typedef typename NumTraits<Scalar>::Real type;
412};
413
414/****************************************************************************
415* Implementation of hypot *
416****************************************************************************/
417
418template<typename Scalar> struct hypot_impl;
419
420template<typename Scalar>
421struct hypot_retval
422{
423 typedef typename NumTraits<Scalar>::Real type;
424};
425
426/****************************************************************************
427* Implementation of cast *
428****************************************************************************/
429
430template<typename OldType, typename NewType, typename EnableIf = void>
431struct cast_impl
432{
433 EIGEN_DEVICE_FUNC
434 static inline NewType run(const OldType& x)
435 {
436 return static_cast<NewType>(x);
437 }
438};
439
440// Casting from S -> Complex<T> leads to an implicit conversion from S to T,
441// generating warnings on clang. Here we explicitly cast the real component.
442template<typename OldType, typename NewType>
443struct cast_impl<OldType, NewType,
444 typename internal::enable_if<
445 !NumTraits<OldType>::IsComplex && NumTraits<NewType>::IsComplex
446 >::type>
447{
448 EIGEN_DEVICE_FUNC
449 static inline NewType run(const OldType& x)
450 {
451 typedef typename NumTraits<NewType>::Real NewReal;
452 return static_cast<NewType>(static_cast<NewReal>(x));
453 }
454};
455
456// here, for once, we're plainly returning NewType: we don't want cast to do weird things.
457
458template<typename OldType, typename NewType>
459EIGEN_DEVICE_FUNC
460inline NewType cast(const OldType& x)
461{
462 return cast_impl<OldType, NewType>::run(x);
463}
464
465/****************************************************************************
466* Implementation of round *
467****************************************************************************/
468
469template<typename Scalar>
470struct round_impl
471{
472 EIGEN_DEVICE_FUNC
473 static inline Scalar run(const Scalar& x)
474 {
475 EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
476#if EIGEN_HAS_CXX11_MATH
477 EIGEN_USING_STD(round);
478#endif
479 return Scalar(round(x));
480 }
481};
482
483#if !EIGEN_HAS_CXX11_MATH
484#if EIGEN_HAS_C99_MATH
485// Use ::roundf for float.
486template<>
487struct round_impl<float> {
488 EIGEN_DEVICE_FUNC
489 static inline float run(const float& x)
490 {
491 return ::roundf(x);
492 }
493};
494#else
495template<typename Scalar>
496struct round_using_floor_ceil_impl
497{
498 EIGEN_DEVICE_FUNC
499 static inline Scalar run(const Scalar& x)
500 {
501 EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
502 // Without C99 round/roundf, resort to floor/ceil.
503 EIGEN_USING_STD(floor);
504 EIGEN_USING_STD(ceil);
505 // If not enough precision to resolve a decimal at all, return the input.
506 // Otherwise, adding 0.5 can trigger an increment by 1.
507 const Scalar limit = Scalar(1ull << (NumTraits<Scalar>::digits() - 1));
508 if (x >= limit || x <= -limit) {
509 return x;
510 }
511 return (x > Scalar(0)) ? Scalar(floor(x + Scalar(0.5))) : Scalar(ceil(x - Scalar(0.5)));
512 }
513};
514
515template<>
516struct round_impl<float> : round_using_floor_ceil_impl<float> {};
517
518template<>
519struct round_impl<double> : round_using_floor_ceil_impl<double> {};
520#endif // EIGEN_HAS_C99_MATH
521#endif // !EIGEN_HAS_CXX11_MATH
522
523template<typename Scalar>
524struct round_retval
525{
526 typedef Scalar type;
527};
528
529/****************************************************************************
530* Implementation of rint *
531****************************************************************************/
532
533template<typename Scalar>
534struct rint_impl {
535 EIGEN_DEVICE_FUNC
536 static inline Scalar run(const Scalar& x)
537 {
538 EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL)
539#if EIGEN_HAS_CXX11_MATH
540 EIGEN_USING_STD(rint);
541#endif
542 return rint(x);
543 }
544};
545
546#if !EIGEN_HAS_CXX11_MATH
547template<>
548struct rint_impl<double> {
549 EIGEN_DEVICE_FUNC
550 static inline double run(const double& x)
551 {
552 return ::rint(x);
553 }
554};
555template<>
556struct rint_impl<float> {
557 EIGEN_DEVICE_FUNC
558 static inline float run(const float& x)
559 {
560 return ::rintf(x);
561 }
562};
563#endif
564
565template<typename Scalar>
566struct rint_retval
567{
568 typedef Scalar type;
569};
570
571/****************************************************************************
572* Implementation of arg *
573****************************************************************************/
574
575// Visual Studio 2017 has a bug where arg(float) returns 0 for negative inputs.
576// This seems to be fixed in VS 2019.
577#if EIGEN_HAS_CXX11_MATH && (!EIGEN_COMP_MSVC || EIGEN_COMP_MSVC >= 1920)
578// std::arg is only defined for types of std::complex, or integer types or float/double/long double
579template<typename Scalar,
580 bool HasStdImpl = NumTraits<Scalar>::IsComplex || is_integral<Scalar>::value
581 || is_same<Scalar, float>::value || is_same<Scalar, double>::value
582 || is_same<Scalar, long double>::value >
583struct arg_default_impl;
584
585template<typename Scalar>
586struct arg_default_impl<Scalar, true> {
587 typedef typename NumTraits<Scalar>::Real RealScalar;
588 EIGEN_DEVICE_FUNC
589 static inline RealScalar run(const Scalar& x)
590 {
591 #if defined(EIGEN_HIP_DEVICE_COMPILE)
592 // HIP does not seem to have a native device side implementation for the math routine "arg"
593 using std::arg;
594 #else
595 EIGEN_USING_STD(arg);
596 #endif
597 return static_cast<RealScalar>(arg(x));
598 }
599};
600
601// Must be non-complex floating-point type (e.g. half/bfloat16).
602template<typename Scalar>
603struct arg_default_impl<Scalar, false> {
604 typedef typename NumTraits<Scalar>::Real RealScalar;
605 EIGEN_DEVICE_FUNC
606 static inline RealScalar run(const Scalar& x)
607 {
608 return (x < Scalar(0)) ? RealScalar(EIGEN_PI) : RealScalar(0);
609 }
610};
611#else
612template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
613struct arg_default_impl
614{
615 typedef typename NumTraits<Scalar>::Real RealScalar;
616 EIGEN_DEVICE_FUNC
617 static inline RealScalar run(const Scalar& x)
618 {
619 return (x < RealScalar(0)) ? RealScalar(EIGEN_PI) : RealScalar(0);
620 }
621};
622
623template<typename Scalar>
624struct arg_default_impl<Scalar,true>
625{
626 typedef typename NumTraits<Scalar>::Real RealScalar;
627 EIGEN_DEVICE_FUNC
628 static inline RealScalar run(const Scalar& x)
629 {
630 EIGEN_USING_STD(arg);
631 return arg(x);
632 }
633};
634#endif
635template<typename Scalar> struct arg_impl : arg_default_impl<Scalar> {};
636
637template<typename Scalar>
638struct arg_retval
639{
640 typedef typename NumTraits<Scalar>::Real type;
641};
642
643/****************************************************************************
644* Implementation of expm1 *
645****************************************************************************/
646
647// This implementation is based on GSL Math's expm1.
648namespace std_fallback {
649 // fallback expm1 implementation in case there is no expm1(Scalar) function in namespace of Scalar,
650 // or that there is no suitable std::expm1 function available. Implementation
651 // attributed to Kahan. See: http://www.plunk.org/~hatch/rightway.php.
652 template<typename Scalar>
653 EIGEN_DEVICE_FUNC inline Scalar expm1(const Scalar& x) {
654 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
655 typedef typename NumTraits<Scalar>::Real RealScalar;
656
657 EIGEN_USING_STD(exp);
658 Scalar u = exp(x);
659 if (numext::equal_strict(u, Scalar(1))) {
660 return x;
661 }
662 Scalar um1 = u - RealScalar(1);
663 if (numext::equal_strict(um1, Scalar(-1))) {
664 return RealScalar(-1);
665 }
666
667 EIGEN_USING_STD(log);
668 Scalar logu = log(u);
669 return numext::equal_strict(u, logu) ? u : (u - RealScalar(1)) * x / logu;
670 }
671}
672
673template<typename Scalar>
674struct expm1_impl {
675 EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
676 {
677 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
678 #if EIGEN_HAS_CXX11_MATH
679 using std::expm1;
680 #else
681 using std_fallback::expm1;
682 #endif
683 return expm1(x);
684 }
685};
686
687template<typename Scalar>
688struct expm1_retval
689{
690 typedef Scalar type;
691};
692
693/****************************************************************************
694* Implementation of log *
695****************************************************************************/
696
697// Complex log defined in MathFunctionsImpl.h.
698template<typename T> EIGEN_DEVICE_FUNC std::complex<T> complex_log(const std::complex<T>& z);
699
700template<typename Scalar>
701struct log_impl {
702 EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
703 {
704 EIGEN_USING_STD(log);
705 return static_cast<Scalar>(log(x));
706 }
707};
708
709template<typename Scalar>
710struct log_impl<std::complex<Scalar> > {
711 EIGEN_DEVICE_FUNC static inline std::complex<Scalar> run(const std::complex<Scalar>& z)
712 {
713 return complex_log(z);
714 }
715};
716
717/****************************************************************************
718* Implementation of log1p *
719****************************************************************************/
720
721namespace std_fallback {
722 // fallback log1p implementation in case there is no log1p(Scalar) function in namespace of Scalar,
723 // or that there is no suitable std::log1p function available
724 template<typename Scalar>
725 EIGEN_DEVICE_FUNC inline Scalar log1p(const Scalar& x) {
726 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
727 typedef typename NumTraits<Scalar>::Real RealScalar;
728 EIGEN_USING_STD(log);
729 Scalar x1p = RealScalar(1) + x;
730 Scalar log_1p = log_impl<Scalar>::run(x1p);
731 const bool is_small = numext::equal_strict(x1p, Scalar(1));
732 const bool is_inf = numext::equal_strict(x1p, log_1p);
733 return (is_small || is_inf) ? x : x * (log_1p / (x1p - RealScalar(1)));
734 }
735}
736
737template<typename Scalar>
738struct log1p_impl {
739 EIGEN_DEVICE_FUNC static inline Scalar run(const Scalar& x)
740 {
741 EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar)
742 #if EIGEN_HAS_CXX11_MATH
743 using std::log1p;
744 #else
745 using std_fallback::log1p;
746 #endif
747 return log1p(x);
748 }
749};
750
751// Specialization for complex types that are not supported by std::log1p.
752template <typename RealScalar>
753struct log1p_impl<std::complex<RealScalar> > {
754 EIGEN_DEVICE_FUNC static inline std::complex<RealScalar> run(
755 const std::complex<RealScalar>& x) {
756 EIGEN_STATIC_ASSERT_NON_INTEGER(RealScalar)
757 return std_fallback::log1p(x);
758 }
759};
760
761template<typename Scalar>
762struct log1p_retval
763{
764 typedef Scalar type;
765};
766
767/****************************************************************************
768* Implementation of pow *
769****************************************************************************/
770
771template<typename ScalarX,typename ScalarY, bool IsInteger = NumTraits<ScalarX>::IsInteger&&NumTraits<ScalarY>::IsInteger>
772struct pow_impl
773{
774 //typedef Scalar retval;
775 typedef typename ScalarBinaryOpTraits<ScalarX,ScalarY,internal::scalar_pow_op<ScalarX,ScalarY> >::ReturnType result_type;
776 static EIGEN_DEVICE_FUNC inline result_type run(const ScalarX& x, const ScalarY& y)
777 {
778 EIGEN_USING_STD(pow);
779 return pow(x, y);
780 }
781};
782
783template<typename ScalarX,typename ScalarY>
784struct pow_impl<ScalarX,ScalarY, true>
785{
786 typedef ScalarX result_type;
787 static EIGEN_DEVICE_FUNC inline ScalarX run(ScalarX x, ScalarY y)
788 {
789 ScalarX res(1);
790 eigen_assert(!NumTraits<ScalarY>::IsSigned || y >= 0);
791 if(y & 1) res *= x;
792 y >>= 1;
793 while(y)
794 {
795 x *= x;
796 if(y&1) res *= x;
797 y >>= 1;
798 }
799 return res;
800 }
801};
802
803/****************************************************************************
804* Implementation of random *
805****************************************************************************/
806
807template<typename Scalar,
808 bool IsComplex,
809 bool IsInteger>
810struct random_default_impl {};
811
812template<typename Scalar>
813struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
814
815template<typename Scalar>
816struct random_retval
817{
818 typedef Scalar type;
819};
820
821template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y);
822template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random();
823
824template<typename Scalar>
825struct random_default_impl<Scalar, false, false>
826{
827 static inline Scalar run(const Scalar& x, const Scalar& y)
828 {
829 return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX);
830 }
831 static inline Scalar run()
832 {
833 return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1));
834 }
835};
836
837enum {
838 meta_floor_log2_terminate,
839 meta_floor_log2_move_up,
840 meta_floor_log2_move_down,
841 meta_floor_log2_bogus
842};
843
844template<unsigned int n, int lower, int upper> struct meta_floor_log2_selector
845{
846 enum { middle = (lower + upper) / 2,
847 value = (upper <= lower + 1) ? int(meta_floor_log2_terminate)
848 : (n < (1 << middle)) ? int(meta_floor_log2_move_down)
849 : (n==0) ? int(meta_floor_log2_bogus)
850 : int(meta_floor_log2_move_up)
851 };
852};
853
854template<unsigned int n,
855 int lower = 0,
856 int upper = sizeof(unsigned int) * CHAR_BIT - 1,
857 int selector = meta_floor_log2_selector<n, lower, upper>::value>
858struct meta_floor_log2 {};
859
860template<unsigned int n, int lower, int upper>
861struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_down>
862{
863 enum { value = meta_floor_log2<n, lower, meta_floor_log2_selector<n, lower, upper>::middle>::value };
864};
865
866template<unsigned int n, int lower, int upper>
867struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_up>
868{
869 enum { value = meta_floor_log2<n, meta_floor_log2_selector<n, lower, upper>::middle, upper>::value };
870};
871
872template<unsigned int n, int lower, int upper>
873struct meta_floor_log2<n, lower, upper, meta_floor_log2_terminate>
874{
875 enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower };
876};
877
878template<unsigned int n, int lower, int upper>
879struct meta_floor_log2<n, lower, upper, meta_floor_log2_bogus>
880{
881 // no value, error at compile time
882};
883
884template<typename Scalar>
885struct random_default_impl<Scalar, false, true>
886{
887 static inline Scalar run(const Scalar& x, const Scalar& y)
888 {
889 if (y <= x)
890 return x;
891 // ScalarU is the unsigned counterpart of Scalar, possibly Scalar itself.
892 typedef typename make_unsigned<Scalar>::type ScalarU;
893 // ScalarX is the widest of ScalarU and unsigned int.
894 // We'll deal only with ScalarX and unsigned int below thus avoiding signed
895 // types and arithmetic and signed overflows (which are undefined behavior).
896 typedef typename conditional<(ScalarU(-1) > unsigned(-1)), ScalarU, unsigned>::type ScalarX;
897 // The following difference doesn't overflow, provided our integer types are two's
898 // complement and have the same number of padding bits in signed and unsigned variants.
899 // This is the case in most modern implementations of C++.
900 ScalarX range = ScalarX(y) - ScalarX(x);
901 ScalarX offset = 0;
902 ScalarX divisor = 1;
903 ScalarX multiplier = 1;
904 const unsigned rand_max = RAND_MAX;
905 if (range <= rand_max) divisor = (rand_max + 1) / (range + 1);
906 else multiplier = 1 + range / (rand_max + 1);
907 // Rejection sampling.
908 do {
909 offset = (unsigned(std::rand()) * multiplier) / divisor;
910 } while (offset > range);
911 return Scalar(ScalarX(x) + offset);
912 }
913
914 static inline Scalar run()
915 {
916#ifdef EIGEN_MAKING_DOCS
917 return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10));
918#else
919 enum { rand_bits = meta_floor_log2<(unsigned int)(RAND_MAX)+1>::value,
920 scalar_bits = sizeof(Scalar) * CHAR_BIT,
921 shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)),
922 offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0
923 };
924 return Scalar((std::rand() >> shift) - offset);
925#endif
926 }
927};
928
929template<typename Scalar>
930struct random_default_impl<Scalar, true, false>
931{
932 static inline Scalar run(const Scalar& x, const Scalar& y)
933 {
934 return Scalar(random(x.real(), y.real()),
935 random(x.imag(), y.imag()));
936 }
937 static inline Scalar run()
938 {
939 typedef typename NumTraits<Scalar>::Real RealScalar;
940 return Scalar(random<RealScalar>(), random<RealScalar>());
941 }
942};
943
944template<typename Scalar>
945inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y)
946{
947 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y);
948}
949
950template<typename Scalar>
951inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random()
952{
953 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
954}
955
956// Implementation of is* functions
957
958// std::is* do not work with fast-math and gcc, std::is* are available on MSVC 2013 and newer, as well as in clang.
959#if (EIGEN_HAS_CXX11_MATH && !(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || (EIGEN_COMP_MSVC>=1800) || (EIGEN_COMP_CLANG)
960#define EIGEN_USE_STD_FPCLASSIFY 1
961#else
962#define EIGEN_USE_STD_FPCLASSIFY 0
963#endif
964
965template<typename T>
966EIGEN_DEVICE_FUNC
967typename internal::enable_if<internal::is_integral<T>::value,bool>::type
968isnan_impl(const T&) { return false; }
969
970template<typename T>
971EIGEN_DEVICE_FUNC
972typename internal::enable_if<internal::is_integral<T>::value,bool>::type
973isinf_impl(const T&) { return false; }
974
975template<typename T>
976EIGEN_DEVICE_FUNC
977typename internal::enable_if<internal::is_integral<T>::value,bool>::type
978isfinite_impl(const T&) { return true; }
979
980template<typename T>
981EIGEN_DEVICE_FUNC
982typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type
983isfinite_impl(const T& x)
984{
985 #if defined(EIGEN_GPU_COMPILE_PHASE)
986 return (::isfinite)(x);
987 #elif EIGEN_USE_STD_FPCLASSIFY
988 using std::isfinite;
989 return isfinite EIGEN_NOT_A_MACRO (x);
990 #else
991 return x<=NumTraits<T>::highest() && x>=NumTraits<T>::lowest();
992 #endif
993}
994
995template<typename T>
996EIGEN_DEVICE_FUNC
997typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type
998isinf_impl(const T& x)
999{
1000 #if defined(EIGEN_GPU_COMPILE_PHASE)
1001 return (::isinf)(x);
1002 #elif EIGEN_USE_STD_FPCLASSIFY
1003 using std::isinf;
1004 return isinf EIGEN_NOT_A_MACRO (x);
1005 #else
1006 return x>NumTraits<T>::highest() || x<NumTraits<T>::lowest();
1007 #endif
1008}
1009
1010template<typename T>
1011EIGEN_DEVICE_FUNC
1012typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type
1013isnan_impl(const T& x)
1014{
1015 #if defined(EIGEN_GPU_COMPILE_PHASE)
1016 return (::isnan)(x);
1017 #elif EIGEN_USE_STD_FPCLASSIFY
1018 using std::isnan;
1019 return isnan EIGEN_NOT_A_MACRO (x);
1020 #else
1021 return x != x;
1022 #endif
1023}
1024
1025#if (!EIGEN_USE_STD_FPCLASSIFY)
1026
1027#if EIGEN_COMP_MSVC
1028
1029template<typename T> EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x)
1030{
1031 return _fpclass(x)==_FPCLASS_NINF || _fpclass(x)==_FPCLASS_PINF;
1032}
1033
1034//MSVC defines a _isnan builtin function, but for double only
1035EIGEN_DEVICE_FUNC inline bool isnan_impl(const long double& x) { return _isnan(x)!=0; }
1036EIGEN_DEVICE_FUNC inline bool isnan_impl(const double& x) { return _isnan(x)!=0; }
1037EIGEN_DEVICE_FUNC inline bool isnan_impl(const float& x) { return _isnan(x)!=0; }
1038
1039EIGEN_DEVICE_FUNC inline bool isinf_impl(const long double& x) { return isinf_msvc_helper(x); }
1040EIGEN_DEVICE_FUNC inline bool isinf_impl(const double& x) { return isinf_msvc_helper(x); }
1041EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_msvc_helper(x); }
1042
1043#elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC)
1044
1045#if EIGEN_GNUC_AT_LEAST(5,0)
1046 #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((optimize("no-finite-math-only")))
1047#else
1048 // NOTE the inline qualifier and noinline attribute are both needed: the former is to avoid linking issue (duplicate symbol),
1049 // while the second prevent too aggressive optimizations in fast-math mode:
1050 #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((noinline,optimize("no-finite-math-only")))
1051#endif
1052
1053template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const long double& x) { return __builtin_isnan(x); }
1054template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const double& x) { return __builtin_isnan(x); }
1055template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const float& x) { return __builtin_isnan(x); }
1056template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const double& x) { return __builtin_isinf(x); }
1057template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const float& x) { return __builtin_isinf(x); }
1058template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const long double& x) { return __builtin_isinf(x); }
1059
1060#undef EIGEN_TMP_NOOPT_ATTRIB
1061
1062#endif
1063
1064#endif
1065
1066// The following overload are defined at the end of this file
1067template<typename T> EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex<T>& x);
1068template<typename T> EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex<T>& x);
1069template<typename T> EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex<T>& x);
1070
1071template<typename T> T generic_fast_tanh_float(const T& a_x);
1072} // end namespace internal
1073
1074/****************************************************************************
1075* Generic math functions *
1076****************************************************************************/
1077
1078namespace numext {
1079
1080#if (!defined(EIGEN_GPUCC) || defined(EIGEN_CONSTEXPR_ARE_DEVICE_FUNC))
1081template<typename T>
1082EIGEN_DEVICE_FUNC
1083EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y)
1084{
1085 EIGEN_USING_STD(min)
1086 return min EIGEN_NOT_A_MACRO (x,y);
1087}
1088
1089template<typename T>
1090EIGEN_DEVICE_FUNC
1091EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y)
1092{
1093 EIGEN_USING_STD(max)
1094 return max EIGEN_NOT_A_MACRO (x,y);
1095}
1096#else
1097template<typename T>
1098EIGEN_DEVICE_FUNC
1099EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y)
1100{
1101 return y < x ? y : x;
1102}
1103template<>
1104EIGEN_DEVICE_FUNC
1105EIGEN_ALWAYS_INLINE float mini(const float& x, const float& y)
1106{
1107 return fminf(x, y);
1108}
1109template<>
1110EIGEN_DEVICE_FUNC
1111EIGEN_ALWAYS_INLINE double mini(const double& x, const double& y)
1112{
1113 return fmin(x, y);
1114}
1115template<>
1116EIGEN_DEVICE_FUNC
1117EIGEN_ALWAYS_INLINE long double mini(const long double& x, const long double& y)
1118{
1119#if defined(EIGEN_HIPCC)
1120 // no "fminl" on HIP yet
1121 return (x < y) ? x : y;
1122#else
1123 return fminl(x, y);
1124#endif
1125}
1126
1127template<typename T>
1128EIGEN_DEVICE_FUNC
1129EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y)
1130{
1131 return x < y ? y : x;
1132}
1133template<>
1134EIGEN_DEVICE_FUNC
1135EIGEN_ALWAYS_INLINE float maxi(const float& x, const float& y)
1136{
1137 return fmaxf(x, y);
1138}
1139template<>
1140EIGEN_DEVICE_FUNC
1141EIGEN_ALWAYS_INLINE double maxi(const double& x, const double& y)
1142{
1143 return fmax(x, y);
1144}
1145template<>
1146EIGEN_DEVICE_FUNC
1147EIGEN_ALWAYS_INLINE long double maxi(const long double& x, const long double& y)
1148{
1149#if defined(EIGEN_HIPCC)
1150 // no "fmaxl" on HIP yet
1151 return (x > y) ? x : y;
1152#else
1153 return fmaxl(x, y);
1154#endif
1155}
1156#endif
1157
1158#if defined(SYCL_DEVICE_ONLY)
1159
1160
1161#define SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \
1162 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_char) \
1163 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_short) \
1164 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_int) \
1165 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_long)
1166#define SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \
1167 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_char) \
1168 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_short) \
1169 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_int) \
1170 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_long)
1171#define SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \
1172 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_uchar) \
1173 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_ushort) \
1174 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_uint) \
1175 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_ulong)
1176#define SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \
1177 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_uchar) \
1178 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_ushort) \
1179 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_uint) \
1180 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_ulong)
1181#define SYCL_SPECIALIZE_INTEGER_TYPES_BINARY(NAME, FUNC) \
1182 SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY(NAME, FUNC) \
1183 SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY(NAME, FUNC)
1184#define SYCL_SPECIALIZE_INTEGER_TYPES_UNARY(NAME, FUNC) \
1185 SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY(NAME, FUNC) \
1186 SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY(NAME, FUNC)
1187#define SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(NAME, FUNC) \
1188 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, cl::sycl::cl_float) \
1189 SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC,cl::sycl::cl_double)
1190#define SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(NAME, FUNC) \
1191 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, cl::sycl::cl_float) \
1192 SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC,cl::sycl::cl_double)
1193#define SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(NAME, FUNC, RET_TYPE) \
1194 SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, cl::sycl::cl_float) \
1195 SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, cl::sycl::cl_double)
1196
1197#define SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE) \
1198template<> \
1199 EIGEN_DEVICE_FUNC \
1200 EIGEN_ALWAYS_INLINE RET_TYPE NAME(const ARG_TYPE& x) { \
1201 return cl::sycl::FUNC(x); \
1202 }
1203
1204#define SYCL_SPECIALIZE_UNARY_FUNC(NAME, FUNC, TYPE) \
1205 SYCL_SPECIALIZE_GEN_UNARY_FUNC(NAME, FUNC, TYPE, TYPE)
1206
1207#define SYCL_SPECIALIZE_GEN1_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE1, ARG_TYPE2) \
1208 template<> \
1209 EIGEN_DEVICE_FUNC \
1210 EIGEN_ALWAYS_INLINE RET_TYPE NAME(const ARG_TYPE1& x, const ARG_TYPE2& y) { \
1211 return cl::sycl::FUNC(x, y); \
1212 }
1213
1214#define SYCL_SPECIALIZE_GEN2_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE) \
1215 SYCL_SPECIALIZE_GEN1_BINARY_FUNC(NAME, FUNC, RET_TYPE, ARG_TYPE, ARG_TYPE)
1216
1217#define SYCL_SPECIALIZE_BINARY_FUNC(NAME, FUNC, TYPE) \
1218 SYCL_SPECIALIZE_GEN2_BINARY_FUNC(NAME, FUNC, TYPE, TYPE)
1219
1220SYCL_SPECIALIZE_INTEGER_TYPES_BINARY(mini, min)
1221SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(mini, fmin)
1222SYCL_SPECIALIZE_INTEGER_TYPES_BINARY(maxi, max)
1223SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(maxi, fmax)
1224
1225#endif
1226
1227
1228template<typename Scalar>
1229EIGEN_DEVICE_FUNC
1230inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x)
1231{
1232 return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x);
1233}
1234
1235template<typename Scalar>
1236EIGEN_DEVICE_FUNC
1237inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x)
1238{
1239 return internal::real_ref_impl<Scalar>::run(x);
1240}
1241
1242template<typename Scalar>
1243EIGEN_DEVICE_FUNC
1244inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x)
1245{
1246 return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x);
1247}
1248
1249template<typename Scalar>
1250EIGEN_DEVICE_FUNC
1251inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x)
1252{
1253 return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x);
1254}
1255
1256template<typename Scalar>
1257EIGEN_DEVICE_FUNC
1258inline EIGEN_MATHFUNC_RETVAL(arg, Scalar) arg(const Scalar& x)
1259{
1260 return EIGEN_MATHFUNC_IMPL(arg, Scalar)::run(x);
1261}
1262
1263template<typename Scalar>
1264EIGEN_DEVICE_FUNC
1265inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x)
1266{
1267 return internal::imag_ref_impl<Scalar>::run(x);
1268}
1269
1270template<typename Scalar>
1271EIGEN_DEVICE_FUNC
1272inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x)
1273{
1274 return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x);
1275}
1276
1277template<typename Scalar>
1278EIGEN_DEVICE_FUNC
1279inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x)
1280{
1281 return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x);
1282}
1283
1284template<typename Scalar>
1285EIGEN_DEVICE_FUNC
1286inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x)
1287{
1288 return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x);
1289}
1290
1291EIGEN_DEVICE_FUNC
1292inline bool abs2(bool x) { return x; }
1293
1294template<typename T>
1295EIGEN_DEVICE_FUNC
1296EIGEN_ALWAYS_INLINE T absdiff(const T& x, const T& y)
1297{
1298 return x > y ? x - y : y - x;
1299}
1300template<>
1301EIGEN_DEVICE_FUNC
1302EIGEN_ALWAYS_INLINE float absdiff(const float& x, const float& y)
1303{
1304 return fabsf(x - y);
1305}
1306template<>
1307EIGEN_DEVICE_FUNC
1308EIGEN_ALWAYS_INLINE double absdiff(const double& x, const double& y)
1309{
1310 return fabs(x - y);
1311}
1312
1313#if !defined(EIGEN_GPUCC)
1314// HIP and CUDA do not support long double.
1315template<>
1316EIGEN_DEVICE_FUNC
1317EIGEN_ALWAYS_INLINE long double absdiff(const long double& x, const long double& y) {
1318 return fabsl(x - y);
1319}
1320#endif
1321
1322template<typename Scalar>
1323EIGEN_DEVICE_FUNC
1324inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x)
1325{
1326 return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x);
1327}
1328
1329template<typename Scalar>
1330EIGEN_DEVICE_FUNC
1331inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y)
1332{
1333 return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y);
1334}
1335
1336#if defined(SYCL_DEVICE_ONLY)
1337 SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(hypot, hypot)
1338#endif
1339
1340template<typename Scalar>
1341EIGEN_DEVICE_FUNC
1342inline EIGEN_MATHFUNC_RETVAL(log1p, Scalar) log1p(const Scalar& x)
1343{
1344 return EIGEN_MATHFUNC_IMPL(log1p, Scalar)::run(x);
1345}
1346
1347#if defined(SYCL_DEVICE_ONLY)
1348SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(log1p, log1p)
1349#endif
1350
1351#if defined(EIGEN_GPUCC)
1352template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1353float log1p(const float &x) { return ::log1pf(x); }
1354
1355template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1356double log1p(const double &x) { return ::log1p(x); }
1357#endif
1358
1359template<typename ScalarX,typename ScalarY>
1360EIGEN_DEVICE_FUNC
1361inline typename internal::pow_impl<ScalarX,ScalarY>::result_type pow(const ScalarX& x, const ScalarY& y)
1362{
1363 return internal::pow_impl<ScalarX,ScalarY>::run(x, y);
1364}
1365
1366#if defined(SYCL_DEVICE_ONLY)
1367SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(pow, pow)
1368#endif
1369
1370template<typename T> EIGEN_DEVICE_FUNC bool (isnan) (const T &x) { return internal::isnan_impl(x); }
1371template<typename T> EIGEN_DEVICE_FUNC bool (isinf) (const T &x) { return internal::isinf_impl(x); }
1372template<typename T> EIGEN_DEVICE_FUNC bool (isfinite)(const T &x) { return internal::isfinite_impl(x); }
1373
1374#if defined(SYCL_DEVICE_ONLY)
1375SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(isnan, isnan, bool)
1376SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(isinf, isinf, bool)
1377SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE(isfinite, isfinite, bool)
1378#endif
1379
1380template<typename Scalar>
1381EIGEN_DEVICE_FUNC
1382inline EIGEN_MATHFUNC_RETVAL(rint, Scalar) rint(const Scalar& x)
1383{
1384 return EIGEN_MATHFUNC_IMPL(rint, Scalar)::run(x);
1385}
1386
1387template<typename Scalar>
1388EIGEN_DEVICE_FUNC
1389inline EIGEN_MATHFUNC_RETVAL(round, Scalar) round(const Scalar& x)
1390{
1391 return EIGEN_MATHFUNC_IMPL(round, Scalar)::run(x);
1392}
1393
1394#if defined(SYCL_DEVICE_ONLY)
1395SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(round, round)
1396#endif
1397
1398template<typename T>
1399EIGEN_DEVICE_FUNC
1400T (floor)(const T& x)
1401{
1402 EIGEN_USING_STD(floor)
1403 return floor(x);
1404}
1405
1406#if defined(SYCL_DEVICE_ONLY)
1407SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(floor, floor)
1408#endif
1409
1410#if defined(EIGEN_GPUCC)
1411template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1412float floor(const float &x) { return ::floorf(x); }
1413
1414template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1415double floor(const double &x) { return ::floor(x); }
1416#endif
1417
1418template<typename T>
1419EIGEN_DEVICE_FUNC
1420T (ceil)(const T& x)
1421{
1422 EIGEN_USING_STD(ceil);
1423 return ceil(x);
1424}
1425
1426#if defined(SYCL_DEVICE_ONLY)
1427SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(ceil, ceil)
1428#endif
1429
1430#if defined(EIGEN_GPUCC)
1431template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1432float ceil(const float &x) { return ::ceilf(x); }
1433
1434template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1435double ceil(const double &x) { return ::ceil(x); }
1436#endif
1437
1438
1441inline int log2(int x)
1442{
1443 eigen_assert(x>=0);
1444 unsigned int v(x);
1445 static const int table[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
1446 v |= v >> 1;
1447 v |= v >> 2;
1448 v |= v >> 4;
1449 v |= v >> 8;
1450 v |= v >> 16;
1451 return table[(v * 0x07C4ACDDU) >> 27];
1452}
1453
1463template<typename Scalar>
1464EIGEN_DEVICE_FUNC
1465EIGEN_ALWAYS_INLINE EIGEN_MATHFUNC_RETVAL(sqrt, Scalar) sqrt(const Scalar& x)
1466{
1467 return EIGEN_MATHFUNC_IMPL(sqrt, Scalar)::run(x);
1468}
1469
1470// Boolean specialization, avoids implicit float to bool conversion (-Wimplicit-conversion-floating-point-to-bool).
1471template<>
1472EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_DEVICE_FUNC
1473bool sqrt<bool>(const bool &x) { return x; }
1474
1475#if defined(SYCL_DEVICE_ONLY)
1476SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(sqrt, sqrt)
1477#endif
1478
1480template<typename T>
1481EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1482T rsqrt(const T& x)
1483{
1484 return internal::rsqrt_impl<T>::run(x);
1485}
1486
1487template<typename T>
1488EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1489T log(const T &x) {
1490 return internal::log_impl<T>::run(x);
1491}
1492
1493#if defined(SYCL_DEVICE_ONLY)
1494SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(log, log)
1495#endif
1496
1497
1498#if defined(EIGEN_GPUCC)
1499template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1500float log(const float &x) { return ::logf(x); }
1501
1502template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1503double log(const double &x) { return ::log(x); }
1504#endif
1505
1506template<typename T>
1507EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1508typename internal::enable_if<NumTraits<T>::IsSigned || NumTraits<T>::IsComplex,typename NumTraits<T>::Real>::type
1509abs(const T &x) {
1510 EIGEN_USING_STD(abs);
1511 return abs(x);
1512}
1513
1514template<typename T>
1515EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1516typename internal::enable_if<!(NumTraits<T>::IsSigned || NumTraits<T>::IsComplex),typename NumTraits<T>::Real>::type
1517abs(const T &x) {
1518 return x;
1519}
1520
1521#if defined(SYCL_DEVICE_ONLY)
1522SYCL_SPECIALIZE_INTEGER_TYPES_UNARY(abs, abs)
1523SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(abs, fabs)
1524#endif
1525
1526#if defined(EIGEN_GPUCC)
1527template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1528float abs(const float &x) { return ::fabsf(x); }
1529
1530template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1531double abs(const double &x) { return ::fabs(x); }
1532
1533template <> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1534float abs(const std::complex<float>& x) {
1535 return ::hypotf(x.real(), x.imag());
1536}
1537
1538template <> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1539double abs(const std::complex<double>& x) {
1540 return ::hypot(x.real(), x.imag());
1541}
1542#endif
1543
1544template<typename T>
1545EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1546T exp(const T &x) {
1547 EIGEN_USING_STD(exp);
1548 return exp(x);
1549}
1550
1551#if defined(SYCL_DEVICE_ONLY)
1552SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(exp, exp)
1553#endif
1554
1555#if defined(EIGEN_GPUCC)
1556template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1557float exp(const float &x) { return ::expf(x); }
1558
1559template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1560double exp(const double &x) { return ::exp(x); }
1561
1562template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1563std::complex<float> exp(const std::complex<float>& x) {
1564 float com = ::expf(x.real());
1565 float res_real = com * ::cosf(x.imag());
1566 float res_imag = com * ::sinf(x.imag());
1567 return std::complex<float>(res_real, res_imag);
1568}
1569
1570template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1571std::complex<double> exp(const std::complex<double>& x) {
1572 double com = ::exp(x.real());
1573 double res_real = com * ::cos(x.imag());
1574 double res_imag = com * ::sin(x.imag());
1575 return std::complex<double>(res_real, res_imag);
1576}
1577#endif
1578
1579template<typename Scalar>
1580EIGEN_DEVICE_FUNC
1581inline EIGEN_MATHFUNC_RETVAL(expm1, Scalar) expm1(const Scalar& x)
1582{
1583 return EIGEN_MATHFUNC_IMPL(expm1, Scalar)::run(x);
1584}
1585
1586#if defined(SYCL_DEVICE_ONLY)
1587SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(expm1, expm1)
1588#endif
1589
1590#if defined(EIGEN_GPUCC)
1591template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1592float expm1(const float &x) { return ::expm1f(x); }
1593
1594template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1595double expm1(const double &x) { return ::expm1(x); }
1596#endif
1597
1598template<typename T>
1599EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1600T cos(const T &x) {
1601 EIGEN_USING_STD(cos);
1602 return cos(x);
1603}
1604
1605#if defined(SYCL_DEVICE_ONLY)
1606SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(cos,cos)
1607#endif
1608
1609#if defined(EIGEN_GPUCC)
1610template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1611float cos(const float &x) { return ::cosf(x); }
1612
1613template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1614double cos(const double &x) { return ::cos(x); }
1615#endif
1616
1617template<typename T>
1618EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1619T sin(const T &x) {
1620 EIGEN_USING_STD(sin);
1621 return sin(x);
1622}
1623
1624#if defined(SYCL_DEVICE_ONLY)
1625SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(sin, sin)
1626#endif
1627
1628#if defined(EIGEN_GPUCC)
1629template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1630float sin(const float &x) { return ::sinf(x); }
1631
1632template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1633double sin(const double &x) { return ::sin(x); }
1634#endif
1635
1636template<typename T>
1637EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1638T tan(const T &x) {
1639 EIGEN_USING_STD(tan);
1640 return tan(x);
1641}
1642
1643#if defined(SYCL_DEVICE_ONLY)
1644SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(tan, tan)
1645#endif
1646
1647#if defined(EIGEN_GPUCC)
1648template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1649float tan(const float &x) { return ::tanf(x); }
1650
1651template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1652double tan(const double &x) { return ::tan(x); }
1653#endif
1654
1655template<typename T>
1656EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1657T acos(const T &x) {
1658 EIGEN_USING_STD(acos);
1659 return acos(x);
1660}
1661
1662#if EIGEN_HAS_CXX11_MATH
1663template<typename T>
1664EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1665T acosh(const T &x) {
1666 EIGEN_USING_STD(acosh);
1667 return static_cast<T>(acosh(x));
1668}
1669#endif
1670
1671#if defined(SYCL_DEVICE_ONLY)
1672SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(acos, acos)
1673SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(acosh, acosh)
1674#endif
1675
1676#if defined(EIGEN_GPUCC)
1677template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1678float acos(const float &x) { return ::acosf(x); }
1679
1680template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1681double acos(const double &x) { return ::acos(x); }
1682#endif
1683
1684template<typename T>
1685EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1686T asin(const T &x) {
1687 EIGEN_USING_STD(asin);
1688 return asin(x);
1689}
1690
1691#if EIGEN_HAS_CXX11_MATH
1692template<typename T>
1693EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1694T asinh(const T &x) {
1695 EIGEN_USING_STD(asinh);
1696 return static_cast<T>(asinh(x));
1697}
1698#endif
1699
1700#if defined(SYCL_DEVICE_ONLY)
1701SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(asin, asin)
1702SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(asinh, asinh)
1703#endif
1704
1705#if defined(EIGEN_GPUCC)
1706template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1707float asin(const float &x) { return ::asinf(x); }
1708
1709template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1710double asin(const double &x) { return ::asin(x); }
1711#endif
1712
1713template<typename T>
1714EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1715T atan(const T &x) {
1716 EIGEN_USING_STD(atan);
1717 return static_cast<T>(atan(x));
1718}
1719
1720#if EIGEN_HAS_CXX11_MATH
1721template<typename T>
1722EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1723T atanh(const T &x) {
1724 EIGEN_USING_STD(atanh);
1725 return static_cast<T>(atanh(x));
1726}
1727#endif
1728
1729#if defined(SYCL_DEVICE_ONLY)
1730SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(atan, atan)
1731SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(atanh, atanh)
1732#endif
1733
1734#if defined(EIGEN_GPUCC)
1735template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1736float atan(const float &x) { return ::atanf(x); }
1737
1738template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1739double atan(const double &x) { return ::atan(x); }
1740#endif
1741
1742
1743template<typename T>
1744EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1745T cosh(const T &x) {
1746 EIGEN_USING_STD(cosh);
1747 return static_cast<T>(cosh(x));
1748}
1749
1750#if defined(SYCL_DEVICE_ONLY)
1751SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(cosh, cosh)
1752#endif
1753
1754#if defined(EIGEN_GPUCC)
1755template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1756float cosh(const float &x) { return ::coshf(x); }
1757
1758template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1759double cosh(const double &x) { return ::cosh(x); }
1760#endif
1761
1762template<typename T>
1763EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1764T sinh(const T &x) {
1765 EIGEN_USING_STD(sinh);
1766 return static_cast<T>(sinh(x));
1767}
1768
1769#if defined(SYCL_DEVICE_ONLY)
1770SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(sinh, sinh)
1771#endif
1772
1773#if defined(EIGEN_GPUCC)
1774template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1775float sinh(const float &x) { return ::sinhf(x); }
1776
1777template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1778double sinh(const double &x) { return ::sinh(x); }
1779#endif
1780
1781template<typename T>
1782EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1783T tanh(const T &x) {
1784 EIGEN_USING_STD(tanh);
1785 return tanh(x);
1786}
1787
1788#if (!defined(EIGEN_GPUCC)) && EIGEN_FAST_MATH && !defined(SYCL_DEVICE_ONLY)
1789EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1790float tanh(float x) { return internal::generic_fast_tanh_float(x); }
1791#endif
1792
1793#if defined(SYCL_DEVICE_ONLY)
1794SYCL_SPECIALIZE_FLOATING_TYPES_UNARY(tanh, tanh)
1795#endif
1796
1797#if defined(EIGEN_GPUCC)
1798template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1799float tanh(const float &x) { return ::tanhf(x); }
1800
1801template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1802double tanh(const double &x) { return ::tanh(x); }
1803#endif
1804
1805template <typename T>
1806EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1807T fmod(const T& a, const T& b) {
1808 EIGEN_USING_STD(fmod);
1809 return fmod(a, b);
1810}
1811
1812#if defined(SYCL_DEVICE_ONLY)
1813SYCL_SPECIALIZE_FLOATING_TYPES_BINARY(fmod, fmod)
1814#endif
1815
1816#if defined(EIGEN_GPUCC)
1817template <>
1818EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1819float fmod(const float& a, const float& b) {
1820 return ::fmodf(a, b);
1821}
1822
1823template <>
1824EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
1825double fmod(const double& a, const double& b) {
1826 return ::fmod(a, b);
1827}
1828#endif
1829
1830#if defined(SYCL_DEVICE_ONLY)
1831#undef SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_BINARY
1832#undef SYCL_SPECIALIZE_SIGNED_INTEGER_TYPES_UNARY
1833#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_BINARY
1834#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY
1835#undef SYCL_SPECIALIZE_INTEGER_TYPES_BINARY
1836#undef SYCL_SPECIALIZE_UNSIGNED_INTEGER_TYPES_UNARY
1837#undef SYCL_SPECIALIZE_FLOATING_TYPES_BINARY
1838#undef SYCL_SPECIALIZE_FLOATING_TYPES_UNARY
1839#undef SYCL_SPECIALIZE_FLOATING_TYPES_UNARY_FUNC_RET_TYPE
1840#undef SYCL_SPECIALIZE_GEN_UNARY_FUNC
1841#undef SYCL_SPECIALIZE_UNARY_FUNC
1842#undef SYCL_SPECIALIZE_GEN1_BINARY_FUNC
1843#undef SYCL_SPECIALIZE_GEN2_BINARY_FUNC
1844#undef SYCL_SPECIALIZE_BINARY_FUNC
1845#endif
1846
1847} // end namespace numext
1848
1849namespace internal {
1850
1851template<typename T>
1852EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex<T>& x)
1853{
1854 return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x));
1855}
1856
1857template<typename T>
1858EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex<T>& x)
1859{
1860 return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x));
1861}
1862
1863template<typename T>
1864EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex<T>& x)
1865{
1866 return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x));
1867}
1868
1869/****************************************************************************
1870* Implementation of fuzzy comparisons *
1871****************************************************************************/
1872
1873template<typename Scalar,
1874 bool IsComplex,
1875 bool IsInteger>
1876struct scalar_fuzzy_default_impl {};
1877
1878template<typename Scalar>
1879struct scalar_fuzzy_default_impl<Scalar, false, false>
1880{
1881 typedef typename NumTraits<Scalar>::Real RealScalar;
1882 template<typename OtherScalar> EIGEN_DEVICE_FUNC
1883 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
1884 {
1885 return numext::abs(x) <= numext::abs(y) * prec;
1886 }
1887 EIGEN_DEVICE_FUNC
1888 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
1889 {
1890 return numext::abs(x - y) <= numext::mini(numext::abs(x), numext::abs(y)) * prec;
1891 }
1892 EIGEN_DEVICE_FUNC
1893 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec)
1894 {
1895 return x <= y || isApprox(x, y, prec);
1896 }
1897};
1898
1899template<typename Scalar>
1900struct scalar_fuzzy_default_impl<Scalar, false, true>
1901{
1902 typedef typename NumTraits<Scalar>::Real RealScalar;
1903 template<typename OtherScalar> EIGEN_DEVICE_FUNC
1904 static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&)
1905 {
1906 return x == Scalar(0);
1907 }
1908 EIGEN_DEVICE_FUNC
1909 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&)
1910 {
1911 return x == y;
1912 }
1913 EIGEN_DEVICE_FUNC
1914 static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&)
1915 {
1916 return x <= y;
1917 }
1918};
1919
1920template<typename Scalar>
1921struct scalar_fuzzy_default_impl<Scalar, true, false>
1922{
1923 typedef typename NumTraits<Scalar>::Real RealScalar;
1924 template<typename OtherScalar> EIGEN_DEVICE_FUNC
1925 static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec)
1926 {
1927 return numext::abs2(x) <= numext::abs2(y) * prec * prec;
1928 }
1929 EIGEN_DEVICE_FUNC
1930 static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec)
1931 {
1932 return numext::abs2(x - y) <= numext::mini(numext::abs2(x), numext::abs2(y)) * prec * prec;
1933 }
1934};
1935
1936template<typename Scalar>
1937struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
1938
1939template<typename Scalar, typename OtherScalar> EIGEN_DEVICE_FUNC
1940inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y,
1941 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
1942{
1943 return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision);
1944}
1945
1946template<typename Scalar> EIGEN_DEVICE_FUNC
1947inline bool isApprox(const Scalar& x, const Scalar& y,
1948 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
1949{
1950 return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision);
1951}
1952
1953template<typename Scalar> EIGEN_DEVICE_FUNC
1954inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y,
1955 const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision())
1956{
1957 return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision);
1958}
1959
1960/******************************************
1961*** The special case of the bool type ***
1962******************************************/
1963
1964template<> struct random_impl<bool>
1965{
1966 static inline bool run()
1967 {
1968 return random<int>(0,1)==0 ? false : true;
1969 }
1970
1971 static inline bool run(const bool& a, const bool& b)
1972 {
1973 return random<int>(a, b)==0 ? false : true;
1974 }
1975};
1976
1977template<> struct scalar_fuzzy_impl<bool>
1978{
1979 typedef bool RealScalar;
1980
1981 template<typename OtherScalar> EIGEN_DEVICE_FUNC
1982 static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&)
1983 {
1984 return !x;
1985 }
1986
1987 EIGEN_DEVICE_FUNC
1988 static inline bool isApprox(bool x, bool y, bool)
1989 {
1990 return x == y;
1991 }
1992
1993 EIGEN_DEVICE_FUNC
1994 static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&)
1995 {
1996 return (!x) || y;
1997 }
1998
1999};
2000
2001} // end namespace internal
2002
2003// Default implementations that rely on other numext implementations
2004namespace internal {
2005
2006// Specialization for complex types that are not supported by std::expm1.
2007template <typename RealScalar>
2008struct expm1_impl<std::complex<RealScalar> > {
2009 EIGEN_DEVICE_FUNC static inline std::complex<RealScalar> run(
2010 const std::complex<RealScalar>& x) {
2011 EIGEN_STATIC_ASSERT_NON_INTEGER(RealScalar)
2012 RealScalar xr = x.real();
2013 RealScalar xi = x.imag();
2014 // expm1(z) = exp(z) - 1
2015 // = exp(x + i * y) - 1
2016 // = exp(x) * (cos(y) + i * sin(y)) - 1
2017 // = exp(x) * cos(y) - 1 + i * exp(x) * sin(y)
2018 // Imag(expm1(z)) = exp(x) * sin(y)
2019 // Real(expm1(z)) = exp(x) * cos(y) - 1
2020 // = exp(x) * cos(y) - 1.
2021 // = expm1(x) + exp(x) * (cos(y) - 1)
2022 // = expm1(x) + exp(x) * (2 * sin(y / 2) ** 2)
2023 RealScalar erm1 = numext::expm1<RealScalar>(xr);
2024 RealScalar er = erm1 + RealScalar(1.);
2025 RealScalar sin2 = numext::sin(xi / RealScalar(2.));
2026 sin2 = sin2 * sin2;
2027 RealScalar s = numext::sin(xi);
2028 RealScalar real_part = erm1 - RealScalar(2.) * er * sin2;
2029 return std::complex<RealScalar>(real_part, er * s);
2030 }
2031};
2032
2033template<typename T>
2034struct rsqrt_impl {
2035 EIGEN_DEVICE_FUNC
2036 static EIGEN_ALWAYS_INLINE T run(const T& x) {
2037 return T(1)/numext::sqrt(x);
2038 }
2039};
2040
2041#if defined(EIGEN_GPU_COMPILE_PHASE)
2042template<typename T>
2043struct conj_impl<std::complex<T>, true>
2044{
2045 EIGEN_DEVICE_FUNC
2046 static inline std::complex<T> run(const std::complex<T>& x)
2047 {
2048 return std::complex<T>(numext::real(x), -numext::imag(x));
2049 }
2050};
2051#endif
2052
2053} // end namespace internal
2054
2055} // end namespace Eigen
2056
2057#endif // EIGEN_MATHFUNCTIONS_H
Namespace containing all symbols from the Eigen library.
Definition: Core:141
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_real_op< typename Derived::Scalar >, const Derived > real(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_rsqrt_op< typename Derived::Scalar >, const Derived > rsqrt(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs2_op< typename Derived::Scalar >, const Derived > abs2(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_isinf_op< typename Derived::Scalar >, const Derived > isinf(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_imag_op< typename Derived::Scalar >, const Derived > imag(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_isfinite_op< typename Derived::Scalar >, const Derived > isfinite(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_arg_op< typename Derived::Scalar >, const Derived > arg(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_isnan_op< typename Derived::Scalar >, const Derived > isnan(const Eigen::ArrayBase< Derived > &x)