Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
functors/UnaryFunctors.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2016 Gael Guennebaud <[email protected]>
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_UNARY_FUNCTORS_H
11#define EIGEN_UNARY_FUNCTORS_H
12
13// IWYU pragma: private
14#include "../InternalHeaderCheck.h"
15
16namespace Eigen {
17
18namespace internal {
19
25template <typename Scalar>
26struct scalar_opposite_op {
27 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const { return numext::negate(a); }
28 template <typename Packet>
29 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
30 return internal::pnegate(a);
31 }
32};
33template <typename Scalar>
34struct functor_traits<scalar_opposite_op<Scalar>> {
35 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasNegate };
36};
37
43template <typename Scalar>
44struct scalar_abs_op {
45 typedef typename NumTraits<Scalar>::Real result_type;
46 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator()(const Scalar& a) const { return numext::abs(a); }
47 template <typename Packet>
48 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
49 return internal::pabs(a);
50 }
51};
52template <typename Scalar>
53struct functor_traits<scalar_abs_op<Scalar>> {
54 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAbs };
55};
56
62template <typename Scalar>
63struct scalar_score_coeff_op : scalar_abs_op<Scalar> {
64 typedef void Score_is_abs;
65};
66template <typename Scalar>
67struct functor_traits<scalar_score_coeff_op<Scalar>> : functor_traits<scalar_abs_op<Scalar>> {};
68
69/* Avoid recomputing abs when we know the score and they are the same. Not a true Eigen functor. */
70template <typename Scalar, typename = void>
71struct abs_knowing_score {
72 typedef typename NumTraits<Scalar>::Real result_type;
73 template <typename Score>
74 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator()(const Scalar& a, const Score&) const {
75 return numext::abs(a);
76 }
77};
78template <typename Scalar>
79struct abs_knowing_score<Scalar, typename scalar_score_coeff_op<Scalar>::Score_is_abs> {
80 typedef typename NumTraits<Scalar>::Real result_type;
81 template <typename Scal>
82 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator()(const Scal&, const result_type& a) const {
83 return a;
84 }
85};
86
92template <typename Scalar>
93struct scalar_abs2_op {
94 typedef typename NumTraits<Scalar>::Real result_type;
95 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator()(const Scalar& a) const { return numext::abs2(a); }
96 template <typename Packet>
97 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
98 return internal::pmul(a, a);
99 }
100};
101template <typename Scalar>
102struct functor_traits<scalar_abs2_op<Scalar>> {
103 enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 };
104};
105
111template <typename Scalar>
112struct scalar_conjugate_op {
113 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const { return numext::conj(a); }
114 template <typename Packet>
115 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
116 return internal::pconj(a);
117 }
118};
119template <typename Scalar>
120struct functor_traits<scalar_conjugate_op<Scalar>> {
121 enum {
122 Cost = 0,
123 // Yes the cost is zero even for complexes because in most cases for which
124 // the cost is used, conjugation turns to be a no-op. Some examples:
125 // cost(a*conj(b)) == cost(a*b)
126 // cost(a+conj(b)) == cost(a+b)
127 // <etc.
128 // If we don't set it to zero, then:
129 // A.conjugate().lazyProduct(B.conjugate())
130 // will bake its operands. We definitely don't want that!
131 PacketAccess = packet_traits<Scalar>::HasConj
132 };
133};
134
140template <typename Scalar>
141struct scalar_arg_op {
142 typedef typename NumTraits<Scalar>::Real result_type;
143 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator()(const Scalar& a) const { return numext::arg(a); }
144 template <typename Packet>
145 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
146 return internal::parg(a);
147 }
148};
149template <typename Scalar>
150struct functor_traits<scalar_arg_op<Scalar>> {
151 enum {
152 Cost = NumTraits<Scalar>::IsComplex ? 5 * NumTraits<Scalar>::MulCost : NumTraits<Scalar>::AddCost,
153 PacketAccess = packet_traits<Scalar>::HasArg
154 };
155};
156
162template <typename Scalar>
163struct scalar_carg_op {
164 using result_type = Scalar;
165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const {
166 return Scalar(numext::arg(a));
167 }
168 template <typename Packet>
169 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
170 return pcarg(a);
171 }
172};
173template <typename Scalar>
174struct functor_traits<scalar_carg_op<Scalar>> {
175 using RealScalar = typename NumTraits<Scalar>::Real;
176 enum { Cost = functor_traits<scalar_atan2_op<RealScalar>>::Cost, PacketAccess = packet_traits<RealScalar>::HasATan };
177};
178
184template <typename Scalar, typename NewType>
185struct scalar_cast_op {
186 typedef NewType result_type;
187 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const NewType operator()(const Scalar& a) const {
188 return cast<Scalar, NewType>(a);
189 }
190};
191
192template <typename Scalar, typename NewType>
193struct functor_traits<scalar_cast_op<Scalar, NewType>> {
194 enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false };
195};
196
203template <typename SrcType, typename DstType>
204struct core_cast_op : scalar_cast_op<SrcType, DstType> {};
205
206template <typename SrcType, typename DstType>
207struct functor_traits<core_cast_op<SrcType, DstType>> {
208 using CastingTraits = type_casting_traits<SrcType, DstType>;
209 enum {
210 Cost = is_same<SrcType, DstType>::value ? 0 : NumTraits<DstType>::AddCost,
211 PacketAccess = CastingTraits::VectorizedCast && (CastingTraits::SrcCoeffRatio <= 8)
212 };
213};
214
220template <typename Scalar, int N>
221struct scalar_shift_right_op {
222 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const {
223 return numext::arithmetic_shift_right(a);
224 }
225 template <typename Packet>
226 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
227 return internal::parithmetic_shift_right<N>(a);
228 }
229};
230template <typename Scalar, int N>
231struct functor_traits<scalar_shift_right_op<Scalar, N>> {
232 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasShift };
233};
234
240template <typename Scalar, int N>
241struct scalar_shift_left_op {
242 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const {
243 return numext::logical_shift_left(a);
244 }
245 template <typename Packet>
246 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
247 return internal::plogical_shift_left<N>(a);
248 }
249};
250template <typename Scalar, int N>
251struct functor_traits<scalar_shift_left_op<Scalar, N>> {
252 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasShift };
253};
254
260template <typename Scalar>
261struct scalar_real_op {
262 typedef typename NumTraits<Scalar>::Real result_type;
263 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const Scalar& a) const { return numext::real(a); }
264};
265template <typename Scalar>
266struct functor_traits<scalar_real_op<Scalar>> {
267 enum { Cost = 0, PacketAccess = false };
268};
269
275template <typename Scalar>
276struct scalar_imag_op {
277 typedef typename NumTraits<Scalar>::Real result_type;
278 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const Scalar& a) const { return numext::imag(a); }
279};
280template <typename Scalar>
281struct functor_traits<scalar_imag_op<Scalar>> {
282 enum { Cost = 0, PacketAccess = false };
283};
284
290template <typename Scalar>
291struct scalar_real_ref_op {
292 typedef typename NumTraits<Scalar>::Real result_type;
293 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type& operator()(const Scalar& a) const {
294 return numext::real_ref(a);
295 }
296 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type& operator()(Scalar& a) const { return numext::real_ref(a); }
297};
298template <typename Scalar>
299struct functor_traits<scalar_real_ref_op<Scalar>> {
300 enum { Cost = 0, PacketAccess = false };
301};
302
308template <typename Scalar>
309struct scalar_imag_ref_op {
310 typedef typename NumTraits<Scalar>::Real result_type;
311 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type& operator()(Scalar& a) const { return numext::imag_ref(a); }
312 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type& operator()(const Scalar& a) const {
313 return numext::imag_ref(a);
314 }
315};
316template <typename Scalar>
317struct functor_traits<scalar_imag_ref_op<Scalar>> {
318 enum { Cost = 0, PacketAccess = false };
319};
320
327template <typename Scalar>
328struct scalar_exp_op {
329 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return internal::pexp(a); }
330 template <typename Packet>
331 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
332 return internal::pexp(a);
333 }
334};
335template <typename Scalar>
336struct functor_traits<scalar_exp_op<Scalar>> {
337 enum {
338 PacketAccess = packet_traits<Scalar>::HasExp,
339 // The following numbers are based on the AVX implementation.
340#ifdef EIGEN_VECTORIZE_FMA
341 // Haswell can issue 2 add/mul/madd per cycle.
342 Cost = (sizeof(Scalar) == 4
343 // float: 8 pmadd, 4 pmul, 2 padd/psub, 6 other
344 ? (8 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost)
345 // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
346 : (14 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost +
347 scalar_div_cost<Scalar, packet_traits<Scalar>::HasDiv>::value))
348#else
349 Cost = (sizeof(Scalar) == 4
350 // float: 7 pmadd, 6 pmul, 4 padd/psub, 10 other
351 ? (21 * NumTraits<Scalar>::AddCost + 13 * NumTraits<Scalar>::MulCost)
352 // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
353 : (23 * NumTraits<Scalar>::AddCost + 12 * NumTraits<Scalar>::MulCost +
354 scalar_div_cost<Scalar, packet_traits<Scalar>::HasDiv>::value))
355#endif
356 };
357};
358
365template <typename Scalar>
366struct scalar_expm1_op {
367 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::expm1(a); }
368 template <typename Packet>
369 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
370 return internal::pexpm1(a);
371 }
372};
373template <typename Scalar>
374struct functor_traits<scalar_expm1_op<Scalar>> {
375 enum {
376 PacketAccess = packet_traits<Scalar>::HasExpm1,
377 Cost = functor_traits<scalar_exp_op<Scalar>>::Cost // TODO measure cost of expm1
378 };
379};
380
387template <typename Scalar>
388struct scalar_log_op {
389 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::log(a); }
390 template <typename Packet>
391 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
392 return internal::plog(a);
393 }
394};
395template <typename Scalar>
396struct functor_traits<scalar_log_op<Scalar>> {
397 enum {
398 PacketAccess = packet_traits<Scalar>::HasLog,
399 Cost = (PacketAccess
400 // The following numbers are based on the AVX implementation.
401#ifdef EIGEN_VECTORIZE_FMA
402 // 8 pmadd, 6 pmul, 8 padd/psub, 16 other, can issue 2 add/mul/madd per cycle.
403 ? (20 * NumTraits<Scalar>::AddCost + 7 * NumTraits<Scalar>::MulCost)
404#else
405 // 8 pmadd, 6 pmul, 8 padd/psub, 20 other
406 ? (36 * NumTraits<Scalar>::AddCost + 14 * NumTraits<Scalar>::MulCost)
407#endif
408 // Measured cost of std::log.
409 : sizeof(Scalar) == 4 ? 40 : 85)
410 };
411};
412
419template <typename Scalar>
420struct scalar_log1p_op {
421 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::log1p(a); }
422 template <typename Packet>
423 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
424 return internal::plog1p(a);
425 }
426};
427template <typename Scalar>
428struct functor_traits<scalar_log1p_op<Scalar>> {
429 enum {
430 PacketAccess = packet_traits<Scalar>::HasLog1p,
431 Cost = functor_traits<scalar_log_op<Scalar>>::Cost // TODO measure cost of log1p
432 };
433};
434
441template <typename Scalar>
442struct scalar_log10_op {
443 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { EIGEN_USING_STD(log10) return log10(a); }
444 template <typename Packet>
445 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
446 return internal::plog10(a);
447 }
448};
449template <typename Scalar>
450struct functor_traits<scalar_log10_op<Scalar>> {
451 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog10 };
452};
453
460template <typename Scalar>
461struct scalar_log2_op {
462 using RealScalar = typename NumTraits<Scalar>::Real;
463 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const {
464 return Scalar(RealScalar(EIGEN_LOG2E)) * numext::log(a);
465 }
466 template <typename Packet>
467 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
468 return internal::plog2(a);
469 }
470};
471template <typename Scalar>
472struct functor_traits<scalar_log2_op<Scalar>> {
473 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog };
474};
475
480template <typename Scalar>
481struct scalar_sqrt_op {
482 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::sqrt(a); }
483 template <typename Packet>
484 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
485 return internal::psqrt(a);
486 }
487};
488template <typename Scalar>
489struct functor_traits<scalar_sqrt_op<Scalar>> {
490 enum {
491#if EIGEN_FAST_MATH
492 // The following numbers are based on the AVX implementation.
493 Cost = (sizeof(Scalar) == 8 ? 28
494 // 4 pmul, 1 pmadd, 3 other
495 : (3 * NumTraits<Scalar>::AddCost + 5 * NumTraits<Scalar>::MulCost)),
496#else
497 // The following numbers are based on min VSQRT throughput on Haswell.
498 Cost = (sizeof(Scalar) == 8 ? 28 : 14),
499#endif
500 PacketAccess = packet_traits<Scalar>::HasSqrt
501 };
502};
503
504// Boolean specialization to eliminate -Wimplicit-conversion-floating-point-to-bool warnings.
505template <>
506struct scalar_sqrt_op<bool> {
507 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator()(const bool& a) const { return a; }
508 template <typename Packet>
509 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
510 return a;
511 }
512};
513template <>
514struct functor_traits<scalar_sqrt_op<bool>> {
515 enum { Cost = 1, PacketAccess = packet_traits<bool>::Vectorizable };
516};
517
522template <typename Scalar>
523struct scalar_cbrt_op {
524 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::cbrt(a); }
525};
526
527template <typename Scalar>
528struct functor_traits<scalar_cbrt_op<Scalar>> {
529 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
530};
531
536template <typename Scalar>
537struct scalar_rsqrt_op {
538 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::rsqrt(a); }
539 template <typename Packet>
540 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
541 return internal::prsqrt(a);
542 }
543};
544
545template <typename Scalar>
546struct functor_traits<scalar_rsqrt_op<Scalar>> {
547 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasRsqrt };
548};
549
554template <typename Scalar>
555struct scalar_cos_op {
556 EIGEN_DEVICE_FUNC inline Scalar operator()(const Scalar& a) const { return numext::cos(a); }
557 template <typename Packet>
558 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
559 return internal::pcos(a);
560 }
561};
562template <typename Scalar>
563struct functor_traits<scalar_cos_op<Scalar>> {
564 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasCos };
565};
566
571template <typename Scalar>
572struct scalar_sin_op {
573 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::sin(a); }
574 template <typename Packet>
575 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
576 return internal::psin(a);
577 }
578};
579template <typename Scalar>
580struct functor_traits<scalar_sin_op<Scalar>> {
581 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasSin };
582};
583
588template <typename Scalar>
589struct scalar_tan_op {
590 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::tan(a); }
591 template <typename Packet>
592 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
593 return internal::ptan(a);
594 }
595};
596template <typename Scalar>
597struct functor_traits<scalar_tan_op<Scalar>> {
598 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasTan };
599};
600
605template <typename Scalar>
606struct scalar_acos_op {
607 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::acos(a); }
608 template <typename Packet>
609 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
610 return internal::pacos(a);
611 }
612};
613template <typename Scalar>
614struct functor_traits<scalar_acos_op<Scalar>> {
615 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasACos };
616};
617
622template <typename Scalar>
623struct scalar_asin_op {
624 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::asin(a); }
625 template <typename Packet>
626 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
627 return internal::pasin(a);
628 }
629};
630template <typename Scalar>
631struct functor_traits<scalar_asin_op<Scalar>> {
632 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasASin };
633};
634
639template <typename Scalar>
640struct scalar_atan_op {
641 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::atan(a); }
642 template <typename Packet>
643 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
644 return internal::patan(a);
645 }
646};
647template <typename Scalar>
648struct functor_traits<scalar_atan_op<Scalar>> {
649 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasATan };
650};
651
656template <typename Scalar>
657struct scalar_tanh_op {
658 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::tanh(a); }
659 template <typename Packet>
660 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const {
661 return ptanh(x);
662 }
663};
664
665template <typename Scalar>
666struct functor_traits<scalar_tanh_op<Scalar>> {
667 enum {
668 PacketAccess = packet_traits<Scalar>::HasTanh,
669 Cost = ((EIGEN_FAST_MATH && is_same<Scalar, float>::value)
670// The following numbers are based on the AVX implementation,
671#ifdef EIGEN_VECTORIZE_FMA
672 // Haswell can issue 2 add/mul/madd per cycle.
673 // 9 pmadd, 2 pmul, 1 div, 2 other
674 ? (2 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost +
675 scalar_div_cost<Scalar, packet_traits<Scalar>::HasDiv>::value)
676#else
677 ? (11 * NumTraits<Scalar>::AddCost + 11 * NumTraits<Scalar>::MulCost +
678 scalar_div_cost<Scalar, packet_traits<Scalar>::HasDiv>::value)
679#endif
680 // This number assumes a naive implementation of tanh
681 : (6 * NumTraits<Scalar>::AddCost + 3 * NumTraits<Scalar>::MulCost +
682 2 * scalar_div_cost<Scalar, packet_traits<Scalar>::HasDiv>::value +
683 functor_traits<scalar_exp_op<Scalar>>::Cost))
684 };
685};
686
691template <typename Scalar>
692struct scalar_atanh_op {
693 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::atanh(a); }
694 template <typename Packet>
695 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const {
696 return patanh(x);
697 }
698};
699
700template <typename Scalar>
701struct functor_traits<scalar_atanh_op<Scalar>> {
702 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasATanh };
703};
704
709template <typename Scalar>
710struct scalar_sinh_op {
711 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::sinh(a); }
712 template <typename Packet>
713 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
714 return internal::psinh(a);
715 }
716};
717template <typename Scalar>
718struct functor_traits<scalar_sinh_op<Scalar>> {
719 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasSinh };
720};
721
726template <typename Scalar>
727struct scalar_asinh_op {
728 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::asinh(a); }
729};
730
731template <typename Scalar>
732struct functor_traits<scalar_asinh_op<Scalar>> {
733 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
734};
735
740template <typename Scalar>
741struct scalar_cosh_op {
742 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::cosh(a); }
743 template <typename Packet>
744 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
745 return internal::pcosh(a);
746 }
747};
748template <typename Scalar>
749struct functor_traits<scalar_cosh_op<Scalar>> {
750 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasCosh };
751};
752
757template <typename Scalar>
758struct scalar_acosh_op {
759 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::acosh(a); }
760};
761
762template <typename Scalar>
763struct functor_traits<scalar_acosh_op<Scalar>> {
764 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
765};
766
771template <typename Scalar>
772struct scalar_inverse_op {
773 EIGEN_DEVICE_FUNC inline Scalar operator()(const Scalar& a) const { return Scalar(1) / a; }
774 template <typename Packet>
775 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const {
776 return internal::preciprocal(a);
777 }
778};
779template <typename Scalar>
780struct functor_traits<scalar_inverse_op<Scalar>> {
781 enum {
782 PacketAccess = packet_traits<Scalar>::HasDiv,
783 // If packet_traits<Scalar>::HasReciprocal then the Estimated cost is that
784 // of computing an approximation plus a single Newton-Raphson step, which
785 // consists of 1 pmul + 1 pmadd.
786 Cost = (packet_traits<Scalar>::HasReciprocal ? 4 * NumTraits<Scalar>::MulCost
787 : scalar_div_cost<Scalar, PacketAccess>::value)
788 };
789};
790
795template <typename Scalar>
796struct scalar_square_op {
797 EIGEN_DEVICE_FUNC inline Scalar operator()(const Scalar& a) const { return a * a; }
798 template <typename Packet>
799 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const {
800 return internal::pmul(a, a);
801 }
802};
803template <typename Scalar>
804struct functor_traits<scalar_square_op<Scalar>> {
805 enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul };
806};
807
808// Boolean specialization to avoid -Wint-in-bool-context warnings on GCC.
809template <>
810struct scalar_square_op<bool> {
811 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator()(const bool& a) const { return a; }
812 template <typename Packet>
813 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const {
814 return a;
815 }
816};
817template <>
818struct functor_traits<scalar_square_op<bool>> {
819 enum { Cost = 0, PacketAccess = packet_traits<bool>::Vectorizable };
820};
821
826template <typename Scalar>
827struct scalar_cube_op {
828 EIGEN_DEVICE_FUNC inline Scalar operator()(const Scalar& a) const { return a * a * a; }
829 template <typename Packet>
830 EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const {
831 return internal::pmul(a, pmul(a, a));
832 }
833};
834template <typename Scalar>
835struct functor_traits<scalar_cube_op<Scalar>> {
836 enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul };
837};
838
839// Boolean specialization to avoid -Wint-in-bool-context warnings on GCC.
840template <>
841struct scalar_cube_op<bool> {
842 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator()(const bool& a) const { return a; }
843 template <typename Packet>
844 EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const {
845 return a;
846 }
847};
848template <>
849struct functor_traits<scalar_cube_op<bool>> {
850 enum { Cost = 0, PacketAccess = packet_traits<bool>::Vectorizable };
851};
852
857template <typename Scalar>
858struct scalar_round_op {
859 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const { return numext::round(a); }
860 template <typename Packet>
861 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
862 return internal::pround(a);
863 }
864};
865template <typename Scalar>
866struct functor_traits<scalar_round_op<Scalar>> {
867 enum {
868 Cost = NumTraits<Scalar>::MulCost,
869 PacketAccess = packet_traits<Scalar>::HasRound || NumTraits<Scalar>::IsInteger
870 };
871};
872
877template <typename Scalar>
878struct scalar_floor_op {
879 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const { return numext::floor(a); }
880 template <typename Packet>
881 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
882 return internal::pfloor(a);
883 }
884};
885template <typename Scalar>
886struct functor_traits<scalar_floor_op<Scalar>> {
887 enum {
888 Cost = NumTraits<Scalar>::MulCost,
889 PacketAccess = packet_traits<Scalar>::HasRound || NumTraits<Scalar>::IsInteger
890 };
891};
892
897template <typename Scalar>
898struct scalar_rint_op {
899 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const { return numext::rint(a); }
900 template <typename Packet>
901 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
902 return internal::print(a);
903 }
904};
905template <typename Scalar>
906struct functor_traits<scalar_rint_op<Scalar>> {
907 enum {
908 Cost = NumTraits<Scalar>::MulCost,
909 PacketAccess = packet_traits<Scalar>::HasRound || NumTraits<Scalar>::IsInteger
910 };
911};
912
917template <typename Scalar>
918struct scalar_ceil_op {
919 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const { return numext::ceil(a); }
920 template <typename Packet>
921 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
922 return internal::pceil(a);
923 }
924};
925template <typename Scalar>
926struct functor_traits<scalar_ceil_op<Scalar>> {
927 enum {
928 Cost = NumTraits<Scalar>::MulCost,
929 PacketAccess = packet_traits<Scalar>::HasRound || NumTraits<Scalar>::IsInteger
930 };
931};
932
937template <typename Scalar>
938struct scalar_trunc_op {
939 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& a) const { return numext::trunc(a); }
940 template <typename Packet>
941 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
942 return internal::ptrunc(a);
943 }
944};
945template <typename Scalar>
946struct functor_traits<scalar_trunc_op<Scalar>> {
947 enum {
948 Cost = NumTraits<Scalar>::MulCost,
949 PacketAccess = packet_traits<Scalar>::HasRound || NumTraits<Scalar>::IsInteger
950 };
951};
952
957template <typename Scalar, bool UseTypedPredicate = false>
958struct scalar_isnan_op {
959 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a) const {
960#if defined(SYCL_DEVICE_ONLY)
961 return numext::isnan(a);
962#else
963 return numext::isnan EIGEN_NOT_A_MACRO(a);
964#endif
965 }
966};
967
968template <typename Scalar>
969struct scalar_isnan_op<Scalar, true> {
970 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const {
971#if defined(SYCL_DEVICE_ONLY)
972 return (numext::isnan(a) ? ptrue(a) : pzero(a));
973#else
974 return (numext::isnan EIGEN_NOT_A_MACRO(a) ? ptrue(a) : pzero(a));
975#endif
976 }
977 template <typename Packet>
978 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
979 return pisnan(a);
980 }
981};
982
983template <typename Scalar, bool UseTypedPredicate>
984struct functor_traits<scalar_isnan_op<Scalar, UseTypedPredicate>> {
985 enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasCmp && UseTypedPredicate };
986};
987
992template <typename Scalar>
993struct scalar_isinf_op {
994 typedef bool result_type;
995 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const Scalar& a) const {
996#if defined(SYCL_DEVICE_ONLY)
997 return numext::isinf(a);
998#else
999 return (numext::isinf)(a);
1000#endif
1001 }
1002};
1003template <typename Scalar>
1004struct functor_traits<scalar_isinf_op<Scalar>> {
1005 enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = false };
1006};
1007
1012template <typename Scalar>
1013struct scalar_isfinite_op {
1014 typedef bool result_type;
1015 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const Scalar& a) const {
1016#if defined(SYCL_DEVICE_ONLY)
1017 return numext::isfinite(a);
1018#else
1019 return (numext::isfinite)(a);
1020#endif
1021 }
1022};
1023template <typename Scalar>
1024struct functor_traits<scalar_isfinite_op<Scalar>> {
1025 enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = false };
1026};
1027
1033template <typename Scalar>
1034struct scalar_boolean_not_op {
1035 using result_type = Scalar;
1036 // `false` any value `a` that satisfies `a == Scalar(0)`
1037 // `true` is the complement of `false`
1038 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const {
1039 return a == Scalar(0) ? Scalar(1) : Scalar(0);
1040 }
1041 template <typename Packet>
1042 EIGEN_STRONG_INLINE Packet packetOp(const Packet& a) const {
1043 const Packet cst_one = pset1<Packet>(Scalar(1));
1044 Packet not_a = pcmp_eq(a, pzero(a));
1045 return pand(not_a, cst_one);
1046 }
1047};
1048template <typename Scalar>
1049struct functor_traits<scalar_boolean_not_op<Scalar>> {
1050 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
1051};
1052
1053template <typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
1054struct bitwise_unary_impl {
1055 static constexpr size_t Size = sizeof(Scalar);
1056 using uint_t = typename numext::get_integer_by_size<Size>::unsigned_type;
1057 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_not(const Scalar& a) {
1058 uint_t a_as_uint = numext::bit_cast<uint_t, Scalar>(a);
1059 uint_t result = ~a_as_uint;
1060 return numext::bit_cast<Scalar, uint_t>(result);
1061 }
1062};
1063
1064template <typename Scalar>
1065struct bitwise_unary_impl<Scalar, true> {
1066 using Real = typename NumTraits<Scalar>::Real;
1067 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_not(const Scalar& a) {
1068 Real real_result = bitwise_unary_impl<Real>::run_not(numext::real(a));
1069 Real imag_result = bitwise_unary_impl<Real>::run_not(numext::imag(a));
1070 return Scalar(real_result, imag_result);
1071 }
1072};
1073
1079template <typename Scalar>
1080struct scalar_bitwise_not_op {
1081 EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization,
1082 BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES)
1083 EIGEN_STATIC_ASSERT((!internal::is_same<Scalar, bool>::value), DONT USE BITWISE OPS ON BOOLEAN TYPES)
1084 using result_type = Scalar;
1085 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const {
1086 return bitwise_unary_impl<Scalar>::run_not(a);
1087 }
1088 template <typename Packet>
1089 EIGEN_STRONG_INLINE Packet packetOp(const Packet& a) const {
1090 return pandnot(ptrue(a), a);
1091 }
1092};
1093template <typename Scalar>
1094struct functor_traits<scalar_bitwise_not_op<Scalar>> {
1095 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
1096};
1097
1102template <typename Scalar>
1103struct scalar_sign_op {
1104 EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::sign(a); }
1105
1106 template <typename Packet>
1107 EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const {
1108 return internal::psign(a);
1109 }
1110};
1111
1112template <typename Scalar>
1113struct functor_traits<scalar_sign_op<Scalar>> {
1114 enum {
1115 Cost = NumTraits<Scalar>::IsComplex ? (8 * NumTraits<Scalar>::MulCost) // roughly
1116 : (3 * NumTraits<Scalar>::AddCost),
1117 PacketAccess = packet_traits<Scalar>::HasSign && packet_traits<Scalar>::Vectorizable
1118 };
1119};
1120
1121// Real-valued implementation.
1122template <typename T, typename EnableIf = void>
1123struct scalar_logistic_op_impl {
1124 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const { return packetOp(x); }
1125
1126 template <typename Packet>
1127 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& x) const {
1128 const Packet one = pset1<Packet>(T(1));
1129 const Packet inf = pset1<Packet>(NumTraits<T>::infinity());
1130 const Packet e = pexp(x);
1131 const Packet inf_mask = pcmp_eq(e, inf);
1132 return pselect(inf_mask, one, pdiv(e, padd(one, e)));
1133 }
1134};
1135
1136// Complex-valud implementation.
1137template <typename T>
1138struct scalar_logistic_op_impl<T, std::enable_if_t<NumTraits<T>::IsComplex>> {
1139 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const {
1140 const T e = numext::exp(x);
1141 return (numext::isinf)(numext::real(e)) ? T(1) : e / (e + T(1));
1142 }
1143};
1144
1149template <typename T>
1150struct scalar_logistic_op : scalar_logistic_op_impl<T> {};
1151
1152// TODO(rmlarsen): Enable the following on host when integer_packet is defined
1153// for the relevant packet types.
1154#ifndef EIGEN_GPUCC
1155
1171template <>
1172struct scalar_logistic_op<float> {
1173 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float operator()(const float& x) const {
1174 // Truncate at the first point where the interpolant is exactly one.
1175 const float cst_exp_hi = 16.6355324f;
1176 const float e = numext::exp(numext::mini(x, cst_exp_hi));
1177 return e / (1.0f + e);
1178 }
1179
1180 template <typename Packet>
1181 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& _x) const {
1182 const Packet cst_zero = pset1<Packet>(0.0f);
1183 const Packet cst_one = pset1<Packet>(1.0f);
1184 const Packet cst_half = pset1<Packet>(0.5f);
1185 // Truncate at the first point where the interpolant is exactly one.
1186 const Packet cst_exp_hi = pset1<Packet>(16.6355324f);
1187 const Packet cst_exp_lo = pset1<Packet>(-104.f);
1188
1189 // Clamp x to the non-trivial range where S(x). Outside this
1190 // interval the correctly rounded value of S(x) is either zero
1191 // or one.
1192 Packet zero_mask = pcmp_lt(_x, cst_exp_lo);
1193 Packet x = pmin(_x, cst_exp_hi);
1194
1195 // 1. Multiplicative range reduction:
1196 // Reduce the range of x by a factor of 2. This avoids having
1197 // to compute exp(x) accurately where the result is a denormalized
1198 // value.
1199 x = pmul(x, cst_half);
1200
1201 // 2. Subtractive range reduction:
1202 // Express exp(x) as exp(m*ln(2) + r) = 2^m*exp(r), start by extracting
1203 // m = floor(x/ln(2) + 0.5), such that x = m*ln(2) + r.
1204 const Packet cst_cephes_LOG2EF = pset1<Packet>(1.44269504088896341f);
1205 Packet m = pfloor(pmadd(x, cst_cephes_LOG2EF, cst_half));
1206 // Get r = x - m*ln(2). We use a trick from Cephes where the term
1207 // m*ln(2) is subtracted out in two parts, m*C1+m*C2 = m*ln(2),
1208 // to avoid accumulating truncation errors.
1209 const Packet cst_cephes_exp_C1 = pset1<Packet>(-0.693359375f);
1210 const Packet cst_cephes_exp_C2 = pset1<Packet>(2.12194440e-4f);
1211 Packet r = pmadd(m, cst_cephes_exp_C1, x);
1212 r = pmadd(m, cst_cephes_exp_C2, r);
1213
1214 // 3. Compute an approximation to exp(r) using a degree 5 minimax polynomial.
1215 // We compute even and odd terms separately to increase instruction level
1216 // parallelism.
1217 Packet r2 = pmul(r, r);
1218 const Packet cst_p2 = pset1<Packet>(0.49999141693115234375f);
1219 const Packet cst_p3 = pset1<Packet>(0.16666877269744873046875f);
1220 const Packet cst_p4 = pset1<Packet>(4.1898667812347412109375e-2f);
1221 const Packet cst_p5 = pset1<Packet>(8.33471305668354034423828125e-3f);
1222
1223 const Packet p_even = pmadd(r2, cst_p4, cst_p2);
1224 const Packet p_odd = pmadd(r2, cst_p5, cst_p3);
1225 const Packet p_low = padd(r, cst_one);
1226 Packet p = pmadd(r, p_odd, p_even);
1227 p = pmadd(r2, p, p_low);
1228
1229 // 4. Undo subtractive range reduction exp(m*ln(2) + r) = 2^m * exp(r).
1230 Packet e = pldexp_fast_impl<Packet>::run(p, m);
1231
1232 // 5. Undo multiplicative range reduction by using exp(r) = exp(r/2)^2.
1233 e = pmul(e, e);
1234
1235 // Return exp(x) / (1 + exp(x))
1236 return pselect(zero_mask, cst_zero, pdiv(e, padd(cst_one, e)));
1237 }
1238};
1239#endif // #ifndef EIGEN_GPU_COMPILE_PHASE
1240
1241template <typename T>
1242struct functor_traits<scalar_logistic_op<T>> {
1243 enum {
1244 // The cost estimate for float here here is for the common(?) case where
1245 // all arguments are greater than -9.
1246 Cost = scalar_div_cost<T, packet_traits<T>::HasDiv>::value +
1247 (internal::is_same<T, float>::value ? NumTraits<T>::AddCost * 15 + NumTraits<T>::MulCost * 11
1248 : NumTraits<T>::AddCost * 2 + functor_traits<scalar_exp_op<T>>::Cost),
1249 PacketAccess = !NumTraits<T>::IsComplex && packet_traits<T>::HasAdd && packet_traits<T>::HasDiv &&
1250 (internal::is_same<T, float>::value
1251 ? packet_traits<T>::HasMul && packet_traits<T>::HasMax && packet_traits<T>::HasMin
1252 : packet_traits<T>::HasNegate && packet_traits<T>::HasExp)
1253 };
1254};
1255
1256template <typename Scalar, typename ExponentScalar, bool IsBaseInteger = NumTraits<Scalar>::IsInteger,
1257 bool IsExponentInteger = NumTraits<ExponentScalar>::IsInteger,
1258 bool IsBaseComplex = NumTraits<Scalar>::IsComplex,
1259 bool IsExponentComplex = NumTraits<ExponentScalar>::IsComplex>
1260struct scalar_unary_pow_op {
1261 typedef typename internal::promote_scalar_arg<
1262 Scalar, ExponentScalar,
1263 internal::has_ReturnType<ScalarBinaryOpTraits<Scalar, ExponentScalar, scalar_unary_pow_op>>::value>::type
1264 PromotedExponent;
1265 typedef typename ScalarBinaryOpTraits<Scalar, PromotedExponent, scalar_unary_pow_op>::ReturnType result_type;
1266 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_unary_pow_op(const ExponentScalar& exponent) : m_exponent(exponent) {}
1267 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const Scalar& a) const {
1268 EIGEN_USING_STD(pow);
1269 return static_cast<result_type>(pow(a, m_exponent));
1270 }
1271
1272 private:
1273 const ExponentScalar m_exponent;
1274 scalar_unary_pow_op() {}
1275};
1276
1277template <typename T>
1278constexpr int exponent_digits() {
1279 return CHAR_BIT * sizeof(T) - NumTraits<T>::digits() - NumTraits<T>::IsSigned;
1280}
1281
1282template <typename From, typename To>
1283struct is_floating_exactly_representable {
1284 // TODO(rmlarsen): Add radix to NumTraits and enable this check.
1285 // (NumTraits<To>::radix == NumTraits<From>::radix) &&
1286 static constexpr bool value =
1287 (exponent_digits<To>() >= exponent_digits<From>() && NumTraits<To>::digits() >= NumTraits<From>::digits());
1288};
1289
1290// Specialization for real, non-integer types, non-complex types.
1291template <typename Scalar, typename ExponentScalar>
1292struct scalar_unary_pow_op<Scalar, ExponentScalar, false, false, false, false> {
1293 template <bool IsExactlyRepresentable = is_floating_exactly_representable<ExponentScalar, Scalar>::value>
1294 std::enable_if_t<IsExactlyRepresentable, void> check_is_representable() const {}
1295
1296 // Issue a deprecation warning if we do a narrowing conversion on the exponent.
1297 template <bool IsExactlyRepresentable = is_floating_exactly_representable<ExponentScalar, Scalar>::value>
1298 EIGEN_DEPRECATED std::enable_if_t<!IsExactlyRepresentable, void> check_is_representable() const {}
1299
1300 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_unary_pow_op(const ExponentScalar& exponent)
1301 : m_exponent(static_cast<Scalar>(exponent)) {
1302 check_is_representable();
1303 }
1304
1305 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const {
1306 EIGEN_USING_STD(pow);
1307 return static_cast<Scalar>(pow(a, m_exponent));
1308 }
1309 template <typename Packet>
1310 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a) const {
1311 return unary_pow_impl<Packet, Scalar>::run(a, m_exponent);
1312 }
1313
1314 private:
1315 const Scalar m_exponent;
1316 scalar_unary_pow_op() {}
1317};
1318
1319template <typename Scalar, typename ExponentScalar, bool BaseIsInteger>
1320struct scalar_unary_pow_op<Scalar, ExponentScalar, BaseIsInteger, true, false, false> {
1321 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_unary_pow_op(const ExponentScalar& exponent) : m_exponent(exponent) {}
1322 // TODO: error handling logic for complex^real_integer
1323 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const {
1324 return unary_pow_impl<Scalar, ExponentScalar>::run(a, m_exponent);
1325 }
1326 template <typename Packet>
1327 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a) const {
1328 return unary_pow_impl<Packet, ExponentScalar>::run(a, m_exponent);
1329 }
1330
1331 private:
1332 const ExponentScalar m_exponent;
1333 scalar_unary_pow_op() {}
1334};
1335
1336template <typename Scalar, typename ExponentScalar>
1337struct functor_traits<scalar_unary_pow_op<Scalar, ExponentScalar>> {
1338 enum {
1339 GenPacketAccess = functor_traits<scalar_pow_op<Scalar, ExponentScalar>>::PacketAccess,
1340 IntPacketAccess = !NumTraits<Scalar>::IsComplex && packet_traits<Scalar>::HasMul &&
1341 (packet_traits<Scalar>::HasDiv || NumTraits<Scalar>::IsInteger) && packet_traits<Scalar>::HasCmp,
1342 PacketAccess = NumTraits<ExponentScalar>::IsInteger ? IntPacketAccess : (IntPacketAccess && GenPacketAccess),
1343 Cost = functor_traits<scalar_pow_op<Scalar, ExponentScalar>>::Cost
1344 };
1345};
1346
1347} // end namespace internal
1348
1349} // end namespace Eigen
1350
1351#endif // EIGEN_FUNCTORS_H
Namespace containing all symbols from the Eigen library.
Definition Core:137