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