1 | // This file is part of Eigen, a lightweight C++ template library |
2 | // for linear algebra. |
3 | // |
4 | // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> |
5 | // |
6 | // This Source Code Form is subject to the terms of the Mozilla |
7 | // Public License v. 2.0. If a copy of the MPL was not distributed |
8 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
9 | |
10 | #ifndef EIGEN_MATHFUNCTIONS_H |
11 | #define EIGEN_MATHFUNCTIONS_H |
12 | |
13 | // source: http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html |
14 | // TODO this should better be moved to NumTraits |
15 | #define EIGEN_PI 3.141592653589793238462643383279502884197169399375105820974944592307816406L |
16 | |
17 | |
18 | namespace Eigen { |
19 | |
20 | // On WINCE, std::abs is defined for int only, so let's defined our own overloads: |
21 | // This issue has been confirmed with MSVC 2008 only, but the issue might exist for more recent versions too. |
22 | #if EIGEN_OS_WINCE && EIGEN_COMP_MSVC && EIGEN_COMP_MSVC<=1500 |
23 | long abs(long x) { return (labs(x)); } |
24 | double abs(double x) { return (fabs(x)); } |
25 | float abs(float x) { return (fabsf(x)); } |
26 | long double abs(long double x) { return (fabsl(x)); } |
27 | #endif |
28 | |
29 | namespace internal { |
30 | |
31 | /** \internal \class global_math_functions_filtering_base |
32 | * |
33 | * What it does: |
34 | * Defines a typedef 'type' as follows: |
35 | * - if type T has a member typedef Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl, then |
36 | * global_math_functions_filtering_base<T>::type is a typedef for it. |
37 | * - otherwise, global_math_functions_filtering_base<T>::type is a typedef for T. |
38 | * |
39 | * How it's used: |
40 | * To allow to defined the global math functions (like sin...) in certain cases, like the Array expressions. |
41 | * When you do sin(array1+array2), the object array1+array2 has a complicated expression type, all what you want to know |
42 | * is that it inherits ArrayBase. So we implement a partial specialization of sin_impl for ArrayBase<Derived>. |
43 | * So we must make sure to use sin_impl<ArrayBase<Derived> > and not sin_impl<Derived>, otherwise our partial specialization |
44 | * won't be used. How does sin know that? That's exactly what global_math_functions_filtering_base tells it. |
45 | * |
46 | * How it's implemented: |
47 | * SFINAE in the style of enable_if. Highly susceptible of breaking compilers. With GCC, it sure does work, but if you replace |
48 | * the typename dummy by an integer template parameter, it doesn't work anymore! |
49 | */ |
50 | |
51 | template<typename T, typename dummy = void> |
52 | struct global_math_functions_filtering_base |
53 | { |
54 | typedef T type; |
55 | }; |
56 | |
57 | template<typename T> struct always_void { typedef void type; }; |
58 | |
59 | template<typename T> |
60 | struct global_math_functions_filtering_base |
61 | <T, |
62 | typename always_void<typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl>::type |
63 | > |
64 | { |
65 | typedef typename T::Eigen_BaseClassForSpecializationOfGlobalMathFuncImpl type; |
66 | }; |
67 | |
68 | #define EIGEN_MATHFUNC_IMPL(func, scalar) Eigen::internal::func##_impl<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type> |
69 | #define EIGEN_MATHFUNC_RETVAL(func, scalar) typename Eigen::internal::func##_retval<typename Eigen::internal::global_math_functions_filtering_base<scalar>::type>::type |
70 | |
71 | /**************************************************************************** |
72 | * Implementation of real * |
73 | ****************************************************************************/ |
74 | |
75 | template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> |
76 | struct real_default_impl |
77 | { |
78 | typedef typename NumTraits<Scalar>::Real RealScalar; |
79 | EIGEN_DEVICE_FUNC |
80 | static inline RealScalar run(const Scalar& x) |
81 | { |
82 | return x; |
83 | } |
84 | }; |
85 | |
86 | template<typename Scalar> |
87 | struct real_default_impl<Scalar,true> |
88 | { |
89 | typedef typename NumTraits<Scalar>::Real RealScalar; |
90 | EIGEN_DEVICE_FUNC |
91 | static inline RealScalar run(const Scalar& x) |
92 | { |
93 | using std::real; |
94 | return real(x); |
95 | } |
96 | }; |
97 | |
98 | template<typename Scalar> struct real_impl : real_default_impl<Scalar> {}; |
99 | |
100 | #ifdef __CUDA_ARCH__ |
101 | template<typename T> |
102 | struct real_impl<std::complex<T> > |
103 | { |
104 | typedef T RealScalar; |
105 | EIGEN_DEVICE_FUNC |
106 | static inline T run(const std::complex<T>& x) |
107 | { |
108 | return x.real(); |
109 | } |
110 | }; |
111 | #endif |
112 | |
113 | template<typename Scalar> |
114 | struct real_retval |
115 | { |
116 | typedef typename NumTraits<Scalar>::Real type; |
117 | }; |
118 | |
119 | /**************************************************************************** |
120 | * Implementation of imag * |
121 | ****************************************************************************/ |
122 | |
123 | template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> |
124 | struct imag_default_impl |
125 | { |
126 | typedef typename NumTraits<Scalar>::Real RealScalar; |
127 | EIGEN_DEVICE_FUNC |
128 | static inline RealScalar run(const Scalar&) |
129 | { |
130 | return RealScalar(0); |
131 | } |
132 | }; |
133 | |
134 | template<typename Scalar> |
135 | struct imag_default_impl<Scalar,true> |
136 | { |
137 | typedef typename NumTraits<Scalar>::Real RealScalar; |
138 | EIGEN_DEVICE_FUNC |
139 | static inline RealScalar run(const Scalar& x) |
140 | { |
141 | using std::imag; |
142 | return imag(x); |
143 | } |
144 | }; |
145 | |
146 | template<typename Scalar> struct imag_impl : imag_default_impl<Scalar> {}; |
147 | |
148 | #ifdef __CUDA_ARCH__ |
149 | template<typename T> |
150 | struct imag_impl<std::complex<T> > |
151 | { |
152 | typedef T RealScalar; |
153 | EIGEN_DEVICE_FUNC |
154 | static inline T run(const std::complex<T>& x) |
155 | { |
156 | return x.imag(); |
157 | } |
158 | }; |
159 | #endif |
160 | |
161 | template<typename Scalar> |
162 | struct imag_retval |
163 | { |
164 | typedef typename NumTraits<Scalar>::Real type; |
165 | }; |
166 | |
167 | /**************************************************************************** |
168 | * Implementation of real_ref * |
169 | ****************************************************************************/ |
170 | |
171 | template<typename Scalar> |
172 | struct real_ref_impl |
173 | { |
174 | typedef typename NumTraits<Scalar>::Real RealScalar; |
175 | EIGEN_DEVICE_FUNC |
176 | static inline RealScalar& run(Scalar& x) |
177 | { |
178 | return reinterpret_cast<RealScalar*>(&x)[0]; |
179 | } |
180 | EIGEN_DEVICE_FUNC |
181 | static inline const RealScalar& run(const Scalar& x) |
182 | { |
183 | return reinterpret_cast<const RealScalar*>(&x)[0]; |
184 | } |
185 | }; |
186 | |
187 | template<typename Scalar> |
188 | struct real_ref_retval |
189 | { |
190 | typedef typename NumTraits<Scalar>::Real & type; |
191 | }; |
192 | |
193 | /**************************************************************************** |
194 | * Implementation of imag_ref * |
195 | ****************************************************************************/ |
196 | |
197 | template<typename Scalar, bool IsComplex> |
198 | struct imag_ref_default_impl |
199 | { |
200 | typedef typename NumTraits<Scalar>::Real RealScalar; |
201 | EIGEN_DEVICE_FUNC |
202 | static inline RealScalar& run(Scalar& x) |
203 | { |
204 | return reinterpret_cast<RealScalar*>(&x)[1]; |
205 | } |
206 | EIGEN_DEVICE_FUNC |
207 | static inline const RealScalar& run(const Scalar& x) |
208 | { |
209 | return reinterpret_cast<RealScalar*>(&x)[1]; |
210 | } |
211 | }; |
212 | |
213 | template<typename Scalar> |
214 | struct imag_ref_default_impl<Scalar, false> |
215 | { |
216 | EIGEN_DEVICE_FUNC |
217 | static inline Scalar run(Scalar&) |
218 | { |
219 | return Scalar(0); |
220 | } |
221 | EIGEN_DEVICE_FUNC |
222 | static inline const Scalar run(const Scalar&) |
223 | { |
224 | return Scalar(0); |
225 | } |
226 | }; |
227 | |
228 | template<typename Scalar> |
229 | struct imag_ref_impl : imag_ref_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; |
230 | |
231 | template<typename Scalar> |
232 | struct imag_ref_retval |
233 | { |
234 | typedef typename NumTraits<Scalar>::Real & type; |
235 | }; |
236 | |
237 | /**************************************************************************** |
238 | * Implementation of conj * |
239 | ****************************************************************************/ |
240 | |
241 | template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> |
242 | struct conj_impl |
243 | { |
244 | EIGEN_DEVICE_FUNC |
245 | static inline Scalar run(const Scalar& x) |
246 | { |
247 | return x; |
248 | } |
249 | }; |
250 | |
251 | template<typename Scalar> |
252 | struct conj_impl<Scalar,true> |
253 | { |
254 | EIGEN_DEVICE_FUNC |
255 | static inline Scalar run(const Scalar& x) |
256 | { |
257 | using std::conj; |
258 | return conj(x); |
259 | } |
260 | }; |
261 | |
262 | template<typename Scalar> |
263 | struct conj_retval |
264 | { |
265 | typedef Scalar type; |
266 | }; |
267 | |
268 | /**************************************************************************** |
269 | * Implementation of abs2 * |
270 | ****************************************************************************/ |
271 | |
272 | template<typename Scalar,bool IsComplex> |
273 | struct abs2_impl_default |
274 | { |
275 | typedef typename NumTraits<Scalar>::Real RealScalar; |
276 | EIGEN_DEVICE_FUNC |
277 | static inline RealScalar run(const Scalar& x) |
278 | { |
279 | return x*x; |
280 | } |
281 | }; |
282 | |
283 | template<typename Scalar> |
284 | struct abs2_impl_default<Scalar, true> // IsComplex |
285 | { |
286 | typedef typename NumTraits<Scalar>::Real RealScalar; |
287 | EIGEN_DEVICE_FUNC |
288 | static inline RealScalar run(const Scalar& x) |
289 | { |
290 | return real(x)*real(x) + imag(x)*imag(x); |
291 | } |
292 | }; |
293 | |
294 | template<typename Scalar> |
295 | struct abs2_impl |
296 | { |
297 | typedef typename NumTraits<Scalar>::Real RealScalar; |
298 | EIGEN_DEVICE_FUNC |
299 | static inline RealScalar run(const Scalar& x) |
300 | { |
301 | return abs2_impl_default<Scalar,NumTraits<Scalar>::IsComplex>::run(x); |
302 | } |
303 | }; |
304 | |
305 | template<typename Scalar> |
306 | struct abs2_retval |
307 | { |
308 | typedef typename NumTraits<Scalar>::Real type; |
309 | }; |
310 | |
311 | /**************************************************************************** |
312 | * Implementation of norm1 * |
313 | ****************************************************************************/ |
314 | |
315 | template<typename Scalar, bool IsComplex> |
316 | struct norm1_default_impl |
317 | { |
318 | typedef typename NumTraits<Scalar>::Real RealScalar; |
319 | EIGEN_DEVICE_FUNC |
320 | static inline RealScalar run(const Scalar& x) |
321 | { |
322 | EIGEN_USING_STD_MATH(abs); |
323 | return abs(real(x)) + abs(imag(x)); |
324 | } |
325 | }; |
326 | |
327 | template<typename Scalar> |
328 | struct norm1_default_impl<Scalar, false> |
329 | { |
330 | EIGEN_DEVICE_FUNC |
331 | static inline Scalar run(const Scalar& x) |
332 | { |
333 | EIGEN_USING_STD_MATH(abs); |
334 | return abs(x); |
335 | } |
336 | }; |
337 | |
338 | template<typename Scalar> |
339 | struct norm1_impl : norm1_default_impl<Scalar, NumTraits<Scalar>::IsComplex> {}; |
340 | |
341 | template<typename Scalar> |
342 | struct norm1_retval |
343 | { |
344 | typedef typename NumTraits<Scalar>::Real type; |
345 | }; |
346 | |
347 | /**************************************************************************** |
348 | * Implementation of hypot * |
349 | ****************************************************************************/ |
350 | |
351 | template<typename Scalar> struct hypot_impl; |
352 | |
353 | template<typename Scalar> |
354 | struct hypot_retval |
355 | { |
356 | typedef typename NumTraits<Scalar>::Real type; |
357 | }; |
358 | |
359 | /**************************************************************************** |
360 | * Implementation of cast * |
361 | ****************************************************************************/ |
362 | |
363 | template<typename OldType, typename NewType> |
364 | struct cast_impl |
365 | { |
366 | EIGEN_DEVICE_FUNC |
367 | static inline NewType run(const OldType& x) |
368 | { |
369 | return static_cast<NewType>(x); |
370 | } |
371 | }; |
372 | |
373 | // here, for once, we're plainly returning NewType: we don't want cast to do weird things. |
374 | |
375 | template<typename OldType, typename NewType> |
376 | EIGEN_DEVICE_FUNC |
377 | inline NewType cast(const OldType& x) |
378 | { |
379 | return cast_impl<OldType, NewType>::run(x); |
380 | } |
381 | |
382 | /**************************************************************************** |
383 | * Implementation of round * |
384 | ****************************************************************************/ |
385 | |
386 | #if EIGEN_HAS_CXX11_MATH |
387 | template<typename Scalar> |
388 | struct round_impl { |
389 | static inline Scalar run(const Scalar& x) |
390 | { |
391 | EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL) |
392 | using std::round; |
393 | return round(x); |
394 | } |
395 | }; |
396 | #else |
397 | template<typename Scalar> |
398 | struct round_impl |
399 | { |
400 | static inline Scalar run(const Scalar& x) |
401 | { |
402 | EIGEN_STATIC_ASSERT((!NumTraits<Scalar>::IsComplex), NUMERIC_TYPE_MUST_BE_REAL) |
403 | EIGEN_USING_STD_MATH(floor); |
404 | EIGEN_USING_STD_MATH(ceil); |
405 | return (x > Scalar(0)) ? floor(x + Scalar(0.5)) : ceil(x - Scalar(0.5)); |
406 | } |
407 | }; |
408 | #endif |
409 | |
410 | template<typename Scalar> |
411 | struct round_retval |
412 | { |
413 | typedef Scalar type; |
414 | }; |
415 | |
416 | /**************************************************************************** |
417 | * Implementation of arg * |
418 | ****************************************************************************/ |
419 | |
420 | #if EIGEN_HAS_CXX11_MATH |
421 | template<typename Scalar> |
422 | struct arg_impl { |
423 | static inline Scalar run(const Scalar& x) |
424 | { |
425 | EIGEN_USING_STD_MATH(arg); |
426 | return arg(x); |
427 | } |
428 | }; |
429 | #else |
430 | template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> |
431 | struct arg_default_impl |
432 | { |
433 | typedef typename NumTraits<Scalar>::Real RealScalar; |
434 | EIGEN_DEVICE_FUNC |
435 | static inline RealScalar run(const Scalar& x) |
436 | { |
437 | return (x < Scalar(0)) ? Scalar(EIGEN_PI) : Scalar(0); } |
438 | }; |
439 | |
440 | template<typename Scalar> |
441 | struct arg_default_impl<Scalar,true> |
442 | { |
443 | typedef typename NumTraits<Scalar>::Real RealScalar; |
444 | EIGEN_DEVICE_FUNC |
445 | static inline RealScalar run(const Scalar& x) |
446 | { |
447 | EIGEN_USING_STD_MATH(arg); |
448 | return arg(x); |
449 | } |
450 | }; |
451 | |
452 | template<typename Scalar> struct arg_impl : arg_default_impl<Scalar> {}; |
453 | #endif |
454 | |
455 | template<typename Scalar> |
456 | struct arg_retval |
457 | { |
458 | typedef typename NumTraits<Scalar>::Real type; |
459 | }; |
460 | |
461 | /**************************************************************************** |
462 | * Implementation of log1p * |
463 | ****************************************************************************/ |
464 | |
465 | namespace std_fallback { |
466 | // fallback log1p implementation in case there is no log1p(Scalar) function in namespace of Scalar, |
467 | // or that there is no suitable std::log1p function available |
468 | template<typename Scalar> |
469 | EIGEN_DEVICE_FUNC inline Scalar log1p(const Scalar& x) { |
470 | EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) |
471 | typedef typename NumTraits<Scalar>::Real RealScalar; |
472 | EIGEN_USING_STD_MATH(log); |
473 | Scalar x1p = RealScalar(1) + x; |
474 | return numext::equal_strict(x1p, Scalar(1)) ? x : x * ( log(x1p) / (x1p - RealScalar(1)) ); |
475 | } |
476 | } |
477 | |
478 | template<typename Scalar> |
479 | struct log1p_impl { |
480 | static inline Scalar run(const Scalar& x) |
481 | { |
482 | EIGEN_STATIC_ASSERT_NON_INTEGER(Scalar) |
483 | #if EIGEN_HAS_CXX11_MATH |
484 | using std::log1p; |
485 | #endif |
486 | using std_fallback::log1p; |
487 | return log1p(x); |
488 | } |
489 | }; |
490 | |
491 | |
492 | template<typename Scalar> |
493 | struct log1p_retval |
494 | { |
495 | typedef Scalar type; |
496 | }; |
497 | |
498 | /**************************************************************************** |
499 | * Implementation of pow * |
500 | ****************************************************************************/ |
501 | |
502 | template<typename ScalarX,typename ScalarY, bool IsInteger = NumTraits<ScalarX>::IsInteger&&NumTraits<ScalarY>::IsInteger> |
503 | struct pow_impl |
504 | { |
505 | //typedef Scalar retval; |
506 | typedef typename ScalarBinaryOpTraits<ScalarX,ScalarY,internal::scalar_pow_op<ScalarX,ScalarY> >::ReturnType result_type; |
507 | static EIGEN_DEVICE_FUNC inline result_type run(const ScalarX& x, const ScalarY& y) |
508 | { |
509 | EIGEN_USING_STD_MATH(pow); |
510 | return pow(x, y); |
511 | } |
512 | }; |
513 | |
514 | template<typename ScalarX,typename ScalarY> |
515 | struct pow_impl<ScalarX,ScalarY, true> |
516 | { |
517 | typedef ScalarX result_type; |
518 | static EIGEN_DEVICE_FUNC inline ScalarX run(ScalarX x, ScalarY y) |
519 | { |
520 | ScalarX res(1); |
521 | eigen_assert(!NumTraits<ScalarY>::IsSigned || y >= 0); |
522 | if(y & 1) res *= x; |
523 | y >>= 1; |
524 | while(y) |
525 | { |
526 | x *= x; |
527 | if(y&1) res *= x; |
528 | y >>= 1; |
529 | } |
530 | return res; |
531 | } |
532 | }; |
533 | |
534 | /**************************************************************************** |
535 | * Implementation of random * |
536 | ****************************************************************************/ |
537 | |
538 | template<typename Scalar, |
539 | bool IsComplex, |
540 | bool IsInteger> |
541 | struct random_default_impl {}; |
542 | |
543 | template<typename Scalar> |
544 | struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; |
545 | |
546 | template<typename Scalar> |
547 | struct random_retval |
548 | { |
549 | typedef Scalar type; |
550 | }; |
551 | |
552 | template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y); |
553 | template<typename Scalar> inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(); |
554 | |
555 | template<typename Scalar> |
556 | struct random_default_impl<Scalar, false, false> |
557 | { |
558 | static inline Scalar run(const Scalar& x, const Scalar& y) |
559 | { |
560 | return x + (y-x) * Scalar(std::rand()) / Scalar(RAND_MAX); |
561 | } |
562 | static inline Scalar run() |
563 | { |
564 | return run(Scalar(NumTraits<Scalar>::IsSigned ? -1 : 0), Scalar(1)); |
565 | } |
566 | }; |
567 | |
568 | enum { |
569 | meta_floor_log2_terminate, |
570 | meta_floor_log2_move_up, |
571 | meta_floor_log2_move_down, |
572 | meta_floor_log2_bogus |
573 | }; |
574 | |
575 | template<unsigned int n, int lower, int upper> struct meta_floor_log2_selector |
576 | { |
577 | enum { middle = (lower + upper) / 2, |
578 | value = (upper <= lower + 1) ? int(meta_floor_log2_terminate) |
579 | : (n < (1 << middle)) ? int(meta_floor_log2_move_down) |
580 | : (n==0) ? int(meta_floor_log2_bogus) |
581 | : int(meta_floor_log2_move_up) |
582 | }; |
583 | }; |
584 | |
585 | template<unsigned int n, |
586 | int lower = 0, |
587 | int upper = sizeof(unsigned int) * CHAR_BIT - 1, |
588 | int selector = meta_floor_log2_selector<n, lower, upper>::value> |
589 | struct meta_floor_log2 {}; |
590 | |
591 | template<unsigned int n, int lower, int upper> |
592 | struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_down> |
593 | { |
594 | enum { value = meta_floor_log2<n, lower, meta_floor_log2_selector<n, lower, upper>::middle>::value }; |
595 | }; |
596 | |
597 | template<unsigned int n, int lower, int upper> |
598 | struct meta_floor_log2<n, lower, upper, meta_floor_log2_move_up> |
599 | { |
600 | enum { value = meta_floor_log2<n, meta_floor_log2_selector<n, lower, upper>::middle, upper>::value }; |
601 | }; |
602 | |
603 | template<unsigned int n, int lower, int upper> |
604 | struct meta_floor_log2<n, lower, upper, meta_floor_log2_terminate> |
605 | { |
606 | enum { value = (n >= ((unsigned int)(1) << (lower+1))) ? lower+1 : lower }; |
607 | }; |
608 | |
609 | template<unsigned int n, int lower, int upper> |
610 | struct meta_floor_log2<n, lower, upper, meta_floor_log2_bogus> |
611 | { |
612 | // no value, error at compile time |
613 | }; |
614 | |
615 | template<typename Scalar> |
616 | struct random_default_impl<Scalar, false, true> |
617 | { |
618 | static inline Scalar run(const Scalar& x, const Scalar& y) |
619 | { |
620 | if (y <= x) |
621 | return x; |
622 | // ScalarU is the unsigned counterpart of Scalar, possibly Scalar itself. |
623 | typedef typename make_unsigned<Scalar>::type ScalarU; |
624 | // ScalarX is the widest of ScalarU and unsigned int. |
625 | // We'll deal only with ScalarX and unsigned int below thus avoiding signed |
626 | // types and arithmetic and signed overflows (which are undefined behavior). |
627 | typedef typename conditional<(ScalarU(-1) > unsigned(-1)), ScalarU, unsigned>::type ScalarX; |
628 | // The following difference doesn't overflow, provided our integer types are two's |
629 | // complement and have the same number of padding bits in signed and unsigned variants. |
630 | // This is the case in most modern implementations of C++. |
631 | ScalarX range = ScalarX(y) - ScalarX(x); |
632 | ScalarX offset = 0; |
633 | ScalarX divisor = 1; |
634 | ScalarX multiplier = 1; |
635 | const unsigned rand_max = RAND_MAX; |
636 | if (range <= rand_max) divisor = (rand_max + 1) / (range + 1); |
637 | else multiplier = 1 + range / (rand_max + 1); |
638 | // Rejection sampling. |
639 | do { |
640 | offset = (unsigned(std::rand()) * multiplier) / divisor; |
641 | } while (offset > range); |
642 | return Scalar(ScalarX(x) + offset); |
643 | } |
644 | |
645 | static inline Scalar run() |
646 | { |
647 | #ifdef EIGEN_MAKING_DOCS |
648 | return run(Scalar(NumTraits<Scalar>::IsSigned ? -10 : 0), Scalar(10)); |
649 | #else |
650 | enum { rand_bits = meta_floor_log2<(unsigned int)(RAND_MAX)+1>::value, |
651 | scalar_bits = sizeof(Scalar) * CHAR_BIT, |
652 | shift = EIGEN_PLAIN_ENUM_MAX(0, int(rand_bits) - int(scalar_bits)), |
653 | offset = NumTraits<Scalar>::IsSigned ? (1 << (EIGEN_PLAIN_ENUM_MIN(rand_bits,scalar_bits)-1)) : 0 |
654 | }; |
655 | return Scalar((std::rand() >> shift) - offset); |
656 | #endif |
657 | } |
658 | }; |
659 | |
660 | template<typename Scalar> |
661 | struct random_default_impl<Scalar, true, false> |
662 | { |
663 | static inline Scalar run(const Scalar& x, const Scalar& y) |
664 | { |
665 | return Scalar(random(real(x), real(y)), |
666 | random(imag(x), imag(y))); |
667 | } |
668 | static inline Scalar run() |
669 | { |
670 | typedef typename NumTraits<Scalar>::Real RealScalar; |
671 | return Scalar(random<RealScalar>(), random<RealScalar>()); |
672 | } |
673 | }; |
674 | |
675 | template<typename Scalar> |
676 | inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(const Scalar& x, const Scalar& y) |
677 | { |
678 | return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y); |
679 | } |
680 | |
681 | template<typename Scalar> |
682 | inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() |
683 | { |
684 | return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(); |
685 | } |
686 | |
687 | // Implementatin of is* functions |
688 | |
689 | // std::is* do not work with fast-math and gcc, std::is* are available on MSVC 2013 and newer, as well as in clang. |
690 | #if (EIGEN_HAS_CXX11_MATH && !(EIGEN_COMP_GNUC_STRICT && __FINITE_MATH_ONLY__)) || (EIGEN_COMP_MSVC>=1800) || (EIGEN_COMP_CLANG) |
691 | #define EIGEN_USE_STD_FPCLASSIFY 1 |
692 | #else |
693 | #define EIGEN_USE_STD_FPCLASSIFY 0 |
694 | #endif |
695 | |
696 | template<typename T> |
697 | EIGEN_DEVICE_FUNC |
698 | typename internal::enable_if<internal::is_integral<T>::value,bool>::type |
699 | isnan_impl(const T&) { return false; } |
700 | |
701 | template<typename T> |
702 | EIGEN_DEVICE_FUNC |
703 | typename internal::enable_if<internal::is_integral<T>::value,bool>::type |
704 | isinf_impl(const T&) { return false; } |
705 | |
706 | template<typename T> |
707 | EIGEN_DEVICE_FUNC |
708 | typename internal::enable_if<internal::is_integral<T>::value,bool>::type |
709 | isfinite_impl(const T&) { return true; } |
710 | |
711 | template<typename T> |
712 | EIGEN_DEVICE_FUNC |
713 | typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type |
714 | isfinite_impl(const T& x) |
715 | { |
716 | #ifdef __CUDA_ARCH__ |
717 | return (::isfinite)(x); |
718 | #elif EIGEN_USE_STD_FPCLASSIFY |
719 | using std::isfinite; |
720 | return isfinite EIGEN_NOT_A_MACRO (x); |
721 | #else |
722 | return x<=NumTraits<T>::highest() && x>=NumTraits<T>::lowest(); |
723 | #endif |
724 | } |
725 | |
726 | template<typename T> |
727 | EIGEN_DEVICE_FUNC |
728 | typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type |
729 | isinf_impl(const T& x) |
730 | { |
731 | #ifdef __CUDA_ARCH__ |
732 | return (::isinf)(x); |
733 | #elif EIGEN_USE_STD_FPCLASSIFY |
734 | using std::isinf; |
735 | return isinf EIGEN_NOT_A_MACRO (x); |
736 | #else |
737 | return x>NumTraits<T>::highest() || x<NumTraits<T>::lowest(); |
738 | #endif |
739 | } |
740 | |
741 | template<typename T> |
742 | EIGEN_DEVICE_FUNC |
743 | typename internal::enable_if<(!internal::is_integral<T>::value)&&(!NumTraits<T>::IsComplex),bool>::type |
744 | isnan_impl(const T& x) |
745 | { |
746 | #ifdef __CUDA_ARCH__ |
747 | return (::isnan)(x); |
748 | #elif EIGEN_USE_STD_FPCLASSIFY |
749 | using std::isnan; |
750 | return isnan EIGEN_NOT_A_MACRO (x); |
751 | #else |
752 | return x != x; |
753 | #endif |
754 | } |
755 | |
756 | #if (!EIGEN_USE_STD_FPCLASSIFY) |
757 | |
758 | #if EIGEN_COMP_MSVC |
759 | |
760 | template<typename T> EIGEN_DEVICE_FUNC bool isinf_msvc_helper(T x) |
761 | { |
762 | return _fpclass(x)==_FPCLASS_NINF || _fpclass(x)==_FPCLASS_PINF; |
763 | } |
764 | |
765 | //MSVC defines a _isnan builtin function, but for double only |
766 | EIGEN_DEVICE_FUNC inline bool isnan_impl(const long double& x) { return _isnan(x)!=0; } |
767 | EIGEN_DEVICE_FUNC inline bool isnan_impl(const double& x) { return _isnan(x)!=0; } |
768 | EIGEN_DEVICE_FUNC inline bool isnan_impl(const float& x) { return _isnan(x)!=0; } |
769 | |
770 | EIGEN_DEVICE_FUNC inline bool isinf_impl(const long double& x) { return isinf_msvc_helper(x); } |
771 | EIGEN_DEVICE_FUNC inline bool isinf_impl(const double& x) { return isinf_msvc_helper(x); } |
772 | EIGEN_DEVICE_FUNC inline bool isinf_impl(const float& x) { return isinf_msvc_helper(x); } |
773 | |
774 | #elif (defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ && EIGEN_COMP_GNUC) |
775 | |
776 | #if EIGEN_GNUC_AT_LEAST(5,0) |
777 | #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((optimize("no-finite-math-only"))) |
778 | #else |
779 | // NOTE the inline qualifier and noinline attribute are both needed: the former is to avoid linking issue (duplicate symbol), |
780 | // while the second prevent too aggressive optimizations in fast-math mode: |
781 | #define EIGEN_TMP_NOOPT_ATTRIB EIGEN_DEVICE_FUNC inline __attribute__((noinline,optimize("no-finite-math-only"))) |
782 | #endif |
783 | |
784 | template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const long double& x) { return __builtin_isnan(x); } |
785 | template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const double& x) { return __builtin_isnan(x); } |
786 | template<> EIGEN_TMP_NOOPT_ATTRIB bool isnan_impl(const float& x) { return __builtin_isnan(x); } |
787 | template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const double& x) { return __builtin_isinf(x); } |
788 | template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const float& x) { return __builtin_isinf(x); } |
789 | template<> EIGEN_TMP_NOOPT_ATTRIB bool isinf_impl(const long double& x) { return __builtin_isinf(x); } |
790 | |
791 | #undef EIGEN_TMP_NOOPT_ATTRIB |
792 | |
793 | #endif |
794 | |
795 | #endif |
796 | |
797 | // The following overload are defined at the end of this file |
798 | template<typename T> EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex<T>& x); |
799 | template<typename T> EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex<T>& x); |
800 | template<typename T> EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex<T>& x); |
801 | |
802 | template<typename T> T generic_fast_tanh_float(const T& a_x); |
803 | |
804 | } // end namespace internal |
805 | |
806 | /**************************************************************************** |
807 | * Generic math functions * |
808 | ****************************************************************************/ |
809 | |
810 | namespace numext { |
811 | |
812 | #ifndef __CUDA_ARCH__ |
813 | template<typename T> |
814 | EIGEN_DEVICE_FUNC |
815 | EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y) |
816 | { |
817 | EIGEN_USING_STD_MATH(min); |
818 | return min EIGEN_NOT_A_MACRO (x,y); |
819 | } |
820 | |
821 | template<typename T> |
822 | EIGEN_DEVICE_FUNC |
823 | EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y) |
824 | { |
825 | EIGEN_USING_STD_MATH(max); |
826 | return max EIGEN_NOT_A_MACRO (x,y); |
827 | } |
828 | #else |
829 | template<typename T> |
830 | EIGEN_DEVICE_FUNC |
831 | EIGEN_ALWAYS_INLINE T mini(const T& x, const T& y) |
832 | { |
833 | return y < x ? y : x; |
834 | } |
835 | template<> |
836 | EIGEN_DEVICE_FUNC |
837 | EIGEN_ALWAYS_INLINE float mini(const float& x, const float& y) |
838 | { |
839 | return fminf(x, y); |
840 | } |
841 | template<typename T> |
842 | EIGEN_DEVICE_FUNC |
843 | EIGEN_ALWAYS_INLINE T maxi(const T& x, const T& y) |
844 | { |
845 | return x < y ? y : x; |
846 | } |
847 | template<> |
848 | EIGEN_DEVICE_FUNC |
849 | EIGEN_ALWAYS_INLINE float maxi(const float& x, const float& y) |
850 | { |
851 | return fmaxf(x, y); |
852 | } |
853 | #endif |
854 | |
855 | |
856 | template<typename Scalar> |
857 | EIGEN_DEVICE_FUNC |
858 | inline EIGEN_MATHFUNC_RETVAL(real, Scalar) real(const Scalar& x) |
859 | { |
860 | return EIGEN_MATHFUNC_IMPL(real, Scalar)::run(x); |
861 | } |
862 | |
863 | template<typename Scalar> |
864 | EIGEN_DEVICE_FUNC |
865 | inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) >::type real_ref(const Scalar& x) |
866 | { |
867 | return internal::real_ref_impl<Scalar>::run(x); |
868 | } |
869 | |
870 | template<typename Scalar> |
871 | EIGEN_DEVICE_FUNC |
872 | inline EIGEN_MATHFUNC_RETVAL(real_ref, Scalar) real_ref(Scalar& x) |
873 | { |
874 | return EIGEN_MATHFUNC_IMPL(real_ref, Scalar)::run(x); |
875 | } |
876 | |
877 | template<typename Scalar> |
878 | EIGEN_DEVICE_FUNC |
879 | inline EIGEN_MATHFUNC_RETVAL(imag, Scalar) imag(const Scalar& x) |
880 | { |
881 | return EIGEN_MATHFUNC_IMPL(imag, Scalar)::run(x); |
882 | } |
883 | |
884 | template<typename Scalar> |
885 | EIGEN_DEVICE_FUNC |
886 | inline EIGEN_MATHFUNC_RETVAL(arg, Scalar) arg(const Scalar& x) |
887 | { |
888 | return EIGEN_MATHFUNC_IMPL(arg, Scalar)::run(x); |
889 | } |
890 | |
891 | template<typename Scalar> |
892 | EIGEN_DEVICE_FUNC |
893 | inline typename internal::add_const_on_value_type< EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) >::type imag_ref(const Scalar& x) |
894 | { |
895 | return internal::imag_ref_impl<Scalar>::run(x); |
896 | } |
897 | |
898 | template<typename Scalar> |
899 | EIGEN_DEVICE_FUNC |
900 | inline EIGEN_MATHFUNC_RETVAL(imag_ref, Scalar) imag_ref(Scalar& x) |
901 | { |
902 | return EIGEN_MATHFUNC_IMPL(imag_ref, Scalar)::run(x); |
903 | } |
904 | |
905 | template<typename Scalar> |
906 | EIGEN_DEVICE_FUNC |
907 | inline EIGEN_MATHFUNC_RETVAL(conj, Scalar) conj(const Scalar& x) |
908 | { |
909 | return EIGEN_MATHFUNC_IMPL(conj, Scalar)::run(x); |
910 | } |
911 | |
912 | template<typename Scalar> |
913 | EIGEN_DEVICE_FUNC |
914 | inline EIGEN_MATHFUNC_RETVAL(abs2, Scalar) abs2(const Scalar& x) |
915 | { |
916 | return EIGEN_MATHFUNC_IMPL(abs2, Scalar)::run(x); |
917 | } |
918 | |
919 | template<typename Scalar> |
920 | EIGEN_DEVICE_FUNC |
921 | inline EIGEN_MATHFUNC_RETVAL(norm1, Scalar) norm1(const Scalar& x) |
922 | { |
923 | return EIGEN_MATHFUNC_IMPL(norm1, Scalar)::run(x); |
924 | } |
925 | |
926 | template<typename Scalar> |
927 | EIGEN_DEVICE_FUNC |
928 | inline EIGEN_MATHFUNC_RETVAL(hypot, Scalar) hypot(const Scalar& x, const Scalar& y) |
929 | { |
930 | return EIGEN_MATHFUNC_IMPL(hypot, Scalar)::run(x, y); |
931 | } |
932 | |
933 | template<typename Scalar> |
934 | EIGEN_DEVICE_FUNC |
935 | inline EIGEN_MATHFUNC_RETVAL(log1p, Scalar) log1p(const Scalar& x) |
936 | { |
937 | return EIGEN_MATHFUNC_IMPL(log1p, Scalar)::run(x); |
938 | } |
939 | |
940 | #ifdef __CUDACC__ |
941 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
942 | float log1p(const float &x) { return ::log1pf(x); } |
943 | |
944 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
945 | double log1p(const double &x) { return ::log1p(x); } |
946 | #endif |
947 | |
948 | template<typename ScalarX,typename ScalarY> |
949 | EIGEN_DEVICE_FUNC |
950 | inline typename internal::pow_impl<ScalarX,ScalarY>::result_type pow(const ScalarX& x, const ScalarY& y) |
951 | { |
952 | return internal::pow_impl<ScalarX,ScalarY>::run(x, y); |
953 | } |
954 | |
955 | template<typename T> EIGEN_DEVICE_FUNC bool (isnan) (const T &x) { return internal::isnan_impl(x); } |
956 | template<typename T> EIGEN_DEVICE_FUNC bool (isinf) (const T &x) { return internal::isinf_impl(x); } |
957 | template<typename T> EIGEN_DEVICE_FUNC bool (isfinite)(const T &x) { return internal::isfinite_impl(x); } |
958 | |
959 | template<typename Scalar> |
960 | EIGEN_DEVICE_FUNC |
961 | inline EIGEN_MATHFUNC_RETVAL(round, Scalar) round(const Scalar& x) |
962 | { |
963 | return EIGEN_MATHFUNC_IMPL(round, Scalar)::run(x); |
964 | } |
965 | |
966 | template<typename T> |
967 | EIGEN_DEVICE_FUNC |
968 | T (floor)(const T& x) |
969 | { |
970 | EIGEN_USING_STD_MATH(floor); |
971 | return floor(x); |
972 | } |
973 | |
974 | #ifdef __CUDACC__ |
975 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
976 | float floor(const float &x) { return ::floorf(x); } |
977 | |
978 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
979 | double floor(const double &x) { return ::floor(x); } |
980 | #endif |
981 | |
982 | template<typename T> |
983 | EIGEN_DEVICE_FUNC |
984 | T (ceil)(const T& x) |
985 | { |
986 | EIGEN_USING_STD_MATH(ceil); |
987 | return ceil(x); |
988 | } |
989 | |
990 | #ifdef __CUDACC__ |
991 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
992 | float ceil(const float &x) { return ::ceilf(x); } |
993 | |
994 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
995 | double ceil(const double &x) { return ::ceil(x); } |
996 | #endif |
997 | |
998 | |
999 | /** Log base 2 for 32 bits positive integers. |
1000 | * Conveniently returns 0 for x==0. */ |
1001 | inline int log2(int x) |
1002 | { |
1003 | eigen_assert(x>=0); |
1004 | unsigned int v(x); |
1005 | 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 }; |
1006 | v |= v >> 1; |
1007 | v |= v >> 2; |
1008 | v |= v >> 4; |
1009 | v |= v >> 8; |
1010 | v |= v >> 16; |
1011 | return table[(v * 0x07C4ACDDU) >> 27]; |
1012 | } |
1013 | |
1014 | /** \returns the square root of \a x. |
1015 | * |
1016 | * It is essentially equivalent to |
1017 | * \code using std::sqrt; return sqrt(x); \endcode |
1018 | * but slightly faster for float/double and some compilers (e.g., gcc), thanks to |
1019 | * specializations when SSE is enabled. |
1020 | * |
1021 | * It's usage is justified in performance critical functions, like norm/normalize. |
1022 | */ |
1023 | template<typename T> |
1024 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1025 | T sqrt(const T &x) |
1026 | { |
1027 | EIGEN_USING_STD_MATH(sqrt); |
1028 | return sqrt(x); |
1029 | } |
1030 | |
1031 | template<typename T> |
1032 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1033 | T log(const T &x) { |
1034 | EIGEN_USING_STD_MATH(log); |
1035 | return log(x); |
1036 | } |
1037 | |
1038 | #ifdef __CUDACC__ |
1039 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1040 | float log(const float &x) { return ::logf(x); } |
1041 | |
1042 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1043 | double log(const double &x) { return ::log(x); } |
1044 | #endif |
1045 | |
1046 | template<typename T> |
1047 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1048 | typename internal::enable_if<NumTraits<T>::IsSigned || NumTraits<T>::IsComplex,typename NumTraits<T>::Real>::type |
1049 | abs(const T &x) { |
1050 | EIGEN_USING_STD_MATH(abs); |
1051 | return abs(x); |
1052 | } |
1053 | |
1054 | template<typename T> |
1055 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1056 | typename internal::enable_if<!(NumTraits<T>::IsSigned || NumTraits<T>::IsComplex),typename NumTraits<T>::Real>::type |
1057 | abs(const T &x) { |
1058 | return x; |
1059 | } |
1060 | |
1061 | #if defined(__SYCL_DEVICE_ONLY__) |
1062 | EIGEN_ALWAYS_INLINE float abs(float x) { return cl::sycl::fabs(x); } |
1063 | EIGEN_ALWAYS_INLINE double abs(double x) { return cl::sycl::fabs(x); } |
1064 | #endif // defined(__SYCL_DEVICE_ONLY__) |
1065 | |
1066 | #ifdef __CUDACC__ |
1067 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1068 | float abs(const float &x) { return ::fabsf(x); } |
1069 | |
1070 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1071 | double abs(const double &x) { return ::fabs(x); } |
1072 | |
1073 | template <> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1074 | float abs(const std::complex<float>& x) { |
1075 | return ::hypotf(x.real(), x.imag()); |
1076 | } |
1077 | |
1078 | template <> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1079 | double abs(const std::complex<double>& x) { |
1080 | return ::hypot(x.real(), x.imag()); |
1081 | } |
1082 | #endif |
1083 | |
1084 | template<typename T> |
1085 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1086 | T exp(const T &x) { |
1087 | EIGEN_USING_STD_MATH(exp); |
1088 | return exp(x); |
1089 | } |
1090 | |
1091 | #ifdef __CUDACC__ |
1092 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1093 | float exp(const float &x) { return ::expf(x); } |
1094 | |
1095 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1096 | double exp(const double &x) { return ::exp(x); } |
1097 | #endif |
1098 | |
1099 | template<typename T> |
1100 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1101 | T cos(const T &x) { |
1102 | EIGEN_USING_STD_MATH(cos); |
1103 | return cos(x); |
1104 | } |
1105 | |
1106 | #ifdef __CUDACC__ |
1107 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1108 | float cos(const float &x) { return ::cosf(x); } |
1109 | |
1110 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1111 | double cos(const double &x) { return ::cos(x); } |
1112 | #endif |
1113 | |
1114 | template<typename T> |
1115 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1116 | T sin(const T &x) { |
1117 | EIGEN_USING_STD_MATH(sin); |
1118 | return sin(x); |
1119 | } |
1120 | |
1121 | #ifdef __CUDACC__ |
1122 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1123 | float sin(const float &x) { return ::sinf(x); } |
1124 | |
1125 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1126 | double sin(const double &x) { return ::sin(x); } |
1127 | #endif |
1128 | |
1129 | template<typename T> |
1130 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1131 | T tan(const T &x) { |
1132 | EIGEN_USING_STD_MATH(tan); |
1133 | return tan(x); |
1134 | } |
1135 | |
1136 | #ifdef __CUDACC__ |
1137 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1138 | float tan(const float &x) { return ::tanf(x); } |
1139 | |
1140 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1141 | double tan(const double &x) { return ::tan(x); } |
1142 | #endif |
1143 | |
1144 | template<typename T> |
1145 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1146 | T acos(const T &x) { |
1147 | EIGEN_USING_STD_MATH(acos); |
1148 | return acos(x); |
1149 | } |
1150 | |
1151 | #ifdef __CUDACC__ |
1152 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1153 | float acos(const float &x) { return ::acosf(x); } |
1154 | |
1155 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1156 | double acos(const double &x) { return ::acos(x); } |
1157 | #endif |
1158 | |
1159 | template<typename T> |
1160 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1161 | T asin(const T &x) { |
1162 | EIGEN_USING_STD_MATH(asin); |
1163 | return asin(x); |
1164 | } |
1165 | |
1166 | #ifdef __CUDACC__ |
1167 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1168 | float asin(const float &x) { return ::asinf(x); } |
1169 | |
1170 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1171 | double asin(const double &x) { return ::asin(x); } |
1172 | #endif |
1173 | |
1174 | template<typename T> |
1175 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1176 | T atan(const T &x) { |
1177 | EIGEN_USING_STD_MATH(atan); |
1178 | return atan(x); |
1179 | } |
1180 | |
1181 | #ifdef __CUDACC__ |
1182 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1183 | float atan(const float &x) { return ::atanf(x); } |
1184 | |
1185 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1186 | double atan(const double &x) { return ::atan(x); } |
1187 | #endif |
1188 | |
1189 | |
1190 | template<typename T> |
1191 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1192 | T cosh(const T &x) { |
1193 | EIGEN_USING_STD_MATH(cosh); |
1194 | return cosh(x); |
1195 | } |
1196 | |
1197 | #ifdef __CUDACC__ |
1198 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1199 | float cosh(const float &x) { return ::coshf(x); } |
1200 | |
1201 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1202 | double cosh(const double &x) { return ::cosh(x); } |
1203 | #endif |
1204 | |
1205 | template<typename T> |
1206 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1207 | T sinh(const T &x) { |
1208 | EIGEN_USING_STD_MATH(sinh); |
1209 | return sinh(x); |
1210 | } |
1211 | |
1212 | #ifdef __CUDACC__ |
1213 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1214 | float sinh(const float &x) { return ::sinhf(x); } |
1215 | |
1216 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1217 | double sinh(const double &x) { return ::sinh(x); } |
1218 | #endif |
1219 | |
1220 | template<typename T> |
1221 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1222 | T tanh(const T &x) { |
1223 | EIGEN_USING_STD_MATH(tanh); |
1224 | return tanh(x); |
1225 | } |
1226 | |
1227 | #if (!defined(__CUDACC__)) && EIGEN_FAST_MATH |
1228 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1229 | float tanh(float x) { return internal::generic_fast_tanh_float(x); } |
1230 | #endif |
1231 | |
1232 | #ifdef __CUDACC__ |
1233 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1234 | float tanh(const float &x) { return ::tanhf(x); } |
1235 | |
1236 | template<> EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1237 | double tanh(const double &x) { return ::tanh(x); } |
1238 | #endif |
1239 | |
1240 | template <typename T> |
1241 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1242 | T fmod(const T& a, const T& b) { |
1243 | EIGEN_USING_STD_MATH(fmod); |
1244 | return fmod(a, b); |
1245 | } |
1246 | |
1247 | #ifdef __CUDACC__ |
1248 | template <> |
1249 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1250 | float fmod(const float& a, const float& b) { |
1251 | return ::fmodf(a, b); |
1252 | } |
1253 | |
1254 | template <> |
1255 | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE |
1256 | double fmod(const double& a, const double& b) { |
1257 | return ::fmod(a, b); |
1258 | } |
1259 | #endif |
1260 | |
1261 | } // end namespace numext |
1262 | |
1263 | namespace internal { |
1264 | |
1265 | template<typename T> |
1266 | EIGEN_DEVICE_FUNC bool isfinite_impl(const std::complex<T>& x) |
1267 | { |
1268 | return (numext::isfinite)(numext::real(x)) && (numext::isfinite)(numext::imag(x)); |
1269 | } |
1270 | |
1271 | template<typename T> |
1272 | EIGEN_DEVICE_FUNC bool isnan_impl(const std::complex<T>& x) |
1273 | { |
1274 | return (numext::isnan)(numext::real(x)) || (numext::isnan)(numext::imag(x)); |
1275 | } |
1276 | |
1277 | template<typename T> |
1278 | EIGEN_DEVICE_FUNC bool isinf_impl(const std::complex<T>& x) |
1279 | { |
1280 | return ((numext::isinf)(numext::real(x)) || (numext::isinf)(numext::imag(x))) && (!(numext::isnan)(x)); |
1281 | } |
1282 | |
1283 | /**************************************************************************** |
1284 | * Implementation of fuzzy comparisons * |
1285 | ****************************************************************************/ |
1286 | |
1287 | template<typename Scalar, |
1288 | bool IsComplex, |
1289 | bool IsInteger> |
1290 | struct scalar_fuzzy_default_impl {}; |
1291 | |
1292 | template<typename Scalar> |
1293 | struct scalar_fuzzy_default_impl<Scalar, false, false> |
1294 | { |
1295 | typedef typename NumTraits<Scalar>::Real RealScalar; |
1296 | template<typename OtherScalar> EIGEN_DEVICE_FUNC |
1297 | static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) |
1298 | { |
1299 | return numext::abs(x) <= numext::abs(y) * prec; |
1300 | } |
1301 | EIGEN_DEVICE_FUNC |
1302 | static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) |
1303 | { |
1304 | return numext::abs(x - y) <= numext::mini(numext::abs(x), numext::abs(y)) * prec; |
1305 | } |
1306 | EIGEN_DEVICE_FUNC |
1307 | static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar& prec) |
1308 | { |
1309 | return x <= y || isApprox(x, y, prec); |
1310 | } |
1311 | }; |
1312 | |
1313 | template<typename Scalar> |
1314 | struct scalar_fuzzy_default_impl<Scalar, false, true> |
1315 | { |
1316 | typedef typename NumTraits<Scalar>::Real RealScalar; |
1317 | template<typename OtherScalar> EIGEN_DEVICE_FUNC |
1318 | static inline bool isMuchSmallerThan(const Scalar& x, const Scalar&, const RealScalar&) |
1319 | { |
1320 | return x == Scalar(0); |
1321 | } |
1322 | EIGEN_DEVICE_FUNC |
1323 | static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar&) |
1324 | { |
1325 | return x == y; |
1326 | } |
1327 | EIGEN_DEVICE_FUNC |
1328 | static inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, const RealScalar&) |
1329 | { |
1330 | return x <= y; |
1331 | } |
1332 | }; |
1333 | |
1334 | template<typename Scalar> |
1335 | struct scalar_fuzzy_default_impl<Scalar, true, false> |
1336 | { |
1337 | typedef typename NumTraits<Scalar>::Real RealScalar; |
1338 | template<typename OtherScalar> EIGEN_DEVICE_FUNC |
1339 | static inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, const RealScalar& prec) |
1340 | { |
1341 | return numext::abs2(x) <= numext::abs2(y) * prec * prec; |
1342 | } |
1343 | EIGEN_DEVICE_FUNC |
1344 | static inline bool isApprox(const Scalar& x, const Scalar& y, const RealScalar& prec) |
1345 | { |
1346 | return numext::abs2(x - y) <= numext::mini(numext::abs2(x), numext::abs2(y)) * prec * prec; |
1347 | } |
1348 | }; |
1349 | |
1350 | template<typename Scalar> |
1351 | struct scalar_fuzzy_impl : scalar_fuzzy_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {}; |
1352 | |
1353 | template<typename Scalar, typename OtherScalar> EIGEN_DEVICE_FUNC |
1354 | inline bool isMuchSmallerThan(const Scalar& x, const OtherScalar& y, |
1355 | const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) |
1356 | { |
1357 | return scalar_fuzzy_impl<Scalar>::template isMuchSmallerThan<OtherScalar>(x, y, precision); |
1358 | } |
1359 | |
1360 | template<typename Scalar> EIGEN_DEVICE_FUNC |
1361 | inline bool isApprox(const Scalar& x, const Scalar& y, |
1362 | const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) |
1363 | { |
1364 | return scalar_fuzzy_impl<Scalar>::isApprox(x, y, precision); |
1365 | } |
1366 | |
1367 | template<typename Scalar> EIGEN_DEVICE_FUNC |
1368 | inline bool isApproxOrLessThan(const Scalar& x, const Scalar& y, |
1369 | const typename NumTraits<Scalar>::Real &precision = NumTraits<Scalar>::dummy_precision()) |
1370 | { |
1371 | return scalar_fuzzy_impl<Scalar>::isApproxOrLessThan(x, y, precision); |
1372 | } |
1373 | |
1374 | /****************************************** |
1375 | *** The special case of the bool type *** |
1376 | ******************************************/ |
1377 | |
1378 | template<> struct random_impl<bool> |
1379 | { |
1380 | static inline bool run() |
1381 | { |
1382 | return random<int>(0,1)==0 ? false : true; |
1383 | } |
1384 | }; |
1385 | |
1386 | template<> struct scalar_fuzzy_impl<bool> |
1387 | { |
1388 | typedef bool RealScalar; |
1389 | |
1390 | template<typename OtherScalar> EIGEN_DEVICE_FUNC |
1391 | static inline bool isMuchSmallerThan(const bool& x, const bool&, const bool&) |
1392 | { |
1393 | return !x; |
1394 | } |
1395 | |
1396 | EIGEN_DEVICE_FUNC |
1397 | static inline bool isApprox(bool x, bool y, bool) |
1398 | { |
1399 | return x == y; |
1400 | } |
1401 | |
1402 | EIGEN_DEVICE_FUNC |
1403 | static inline bool isApproxOrLessThan(const bool& x, const bool& y, const bool&) |
1404 | { |
1405 | return (!x) || y; |
1406 | } |
1407 | |
1408 | }; |
1409 | |
1410 | |
1411 | } // end namespace internal |
1412 | |
1413 | } // end namespace Eigen |
1414 | |
1415 | #endif // EIGEN_MATHFUNCTIONS_H |
1416 | |