Branch data Line data Source code
1 : : // This file is part of Eigen, a lightweight C++ template library
2 : : // for linear algebra.
3 : : //
4 : : // Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
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 : : namespace Eigen {
14 : :
15 : : namespace internal {
16 : :
17 : : /** \internal
18 : : * \brief Template functor to compute the opposite of a scalar
19 : : *
20 : : * \sa class CwiseUnaryOp, MatrixBase::operator-
21 : : */
22 : : template<typename Scalar> struct scalar_opposite_op {
23 : 12300 : EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op)
24 : 2050 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; }
25 : : template<typename Packet>
26 : 4100 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
27 : 4100 : { return internal::pnegate(a); }
28 : : };
29 : : template<typename Scalar>
30 : : struct functor_traits<scalar_opposite_op<Scalar> >
31 : : { enum {
32 : : Cost = NumTraits<Scalar>::AddCost,
33 : : PacketAccess = packet_traits<Scalar>::HasNegate };
34 : : };
35 : :
36 : : /** \internal
37 : : * \brief Template functor to compute the absolute value of a scalar
38 : : *
39 : : * \sa class CwiseUnaryOp, Cwise::abs
40 : : */
41 : : template<typename Scalar> struct scalar_abs_op {
42 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op)
43 : : typedef typename NumTraits<Scalar>::Real result_type;
44 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs(a); }
45 : : template<typename Packet>
46 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
47 : : { return internal::pabs(a); }
48 : : };
49 : : template<typename Scalar>
50 : : struct functor_traits<scalar_abs_op<Scalar> >
51 : : {
52 : : enum {
53 : : Cost = NumTraits<Scalar>::AddCost,
54 : : PacketAccess = packet_traits<Scalar>::HasAbs
55 : : };
56 : : };
57 : :
58 : : /** \internal
59 : : * \brief Template functor to compute the score of a scalar, to chose a pivot
60 : : *
61 : : * \sa class CwiseUnaryOp
62 : : */
63 : : template<typename Scalar> struct scalar_score_coeff_op : scalar_abs_op<Scalar>
64 : : {
65 : : typedef void Score_is_abs;
66 : : };
67 : : template<typename Scalar>
68 : : struct functor_traits<scalar_score_coeff_op<Scalar> > : functor_traits<scalar_abs_op<Scalar> > {};
69 : :
70 : : /* Avoid recomputing abs when we know the score and they are the same. Not a true Eigen functor. */
71 : : template<typename Scalar, typename=void> struct abs_knowing_score
72 : : {
73 : : EIGEN_EMPTY_STRUCT_CTOR(abs_knowing_score)
74 : : typedef typename NumTraits<Scalar>::Real result_type;
75 : : template<typename Score>
76 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a, const Score&) const { return numext::abs(a); }
77 : : };
78 : : template<typename Scalar> struct abs_knowing_score<Scalar, typename scalar_score_coeff_op<Scalar>::Score_is_abs>
79 : : {
80 : : EIGEN_EMPTY_STRUCT_CTOR(abs_knowing_score)
81 : : typedef typename NumTraits<Scalar>::Real result_type;
82 : : template<typename Scal>
83 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scal&, const result_type& a) const { return a; }
84 : : };
85 : :
86 : : /** \internal
87 : : * \brief Template functor to compute the squared absolute value of a scalar
88 : : *
89 : : * \sa class CwiseUnaryOp, Cwise::abs2
90 : : */
91 : : template<typename Scalar> struct scalar_abs2_op {
92 : 64008 : EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
93 : : typedef typename NumTraits<Scalar>::Real result_type;
94 : : EIGEN_DEVICE_FUNC
95 : 4526 : EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::abs2(a); }
96 : : template<typename Packet>
97 : 31636 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
98 : 31636 : { return internal::pmul(a,a); }
99 : : };
100 : : template<typename Scalar>
101 : : struct functor_traits<scalar_abs2_op<Scalar> >
102 : : { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; };
103 : :
104 : : /** \internal
105 : : * \brief Template functor to compute the conjugate of a complex value
106 : : *
107 : : * \sa class CwiseUnaryOp, MatrixBase::conjugate()
108 : : */
109 : : template<typename Scalar> struct scalar_conjugate_op {
110 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
111 : : EIGEN_DEVICE_FUNC
112 : : EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::conj(a); }
113 : : template<typename Packet>
114 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
115 : : };
116 : : template<typename Scalar>
117 : : struct functor_traits<scalar_conjugate_op<Scalar> >
118 : : {
119 : : enum {
120 : : Cost = 0,
121 : : // Yes the cost is zero even for complexes because in most cases for which
122 : : // the cost is used, conjugation turns to be a no-op. Some examples:
123 : : // cost(a*conj(b)) == cost(a*b)
124 : : // cost(a+conj(b)) == cost(a+b)
125 : : // <etc.
126 : : // If we don't set it to zero, then:
127 : : // A.conjugate().lazyProduct(B.conjugate())
128 : : // will bake its operands. We definitely don't want that!
129 : : PacketAccess = packet_traits<Scalar>::HasConj
130 : : };
131 : : };
132 : :
133 : : /** \internal
134 : : * \brief Template functor to compute the phase angle of a complex
135 : : *
136 : : * \sa class CwiseUnaryOp, Cwise::arg
137 : : */
138 : : template<typename Scalar> struct scalar_arg_op {
139 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_arg_op)
140 : : typedef typename NumTraits<Scalar>::Real result_type;
141 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return numext::arg(a); }
142 : : template<typename Packet>
143 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
144 : : { return internal::parg(a); }
145 : : };
146 : : template<typename Scalar>
147 : : struct functor_traits<scalar_arg_op<Scalar> >
148 : : {
149 : : enum {
150 : : Cost = NumTraits<Scalar>::IsComplex ? 5 * NumTraits<Scalar>::MulCost : NumTraits<Scalar>::AddCost,
151 : : PacketAccess = packet_traits<Scalar>::HasArg
152 : : };
153 : : };
154 : : /** \internal
155 : : * \brief Template functor to cast a scalar to another type
156 : : *
157 : : * \sa class CwiseUnaryOp, MatrixBase::cast()
158 : : */
159 : : template<typename Scalar, typename NewType>
160 : : struct scalar_cast_op {
161 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op)
162 : : typedef NewType result_type;
163 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); }
164 : : };
165 : : template<typename Scalar, typename NewType>
166 : : struct functor_traits<scalar_cast_op<Scalar,NewType> >
167 : : { enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; };
168 : :
169 : : /** \internal
170 : : * \brief Template functor to arithmetically shift a scalar right by a number of bits
171 : : *
172 : : * \sa class CwiseUnaryOp, MatrixBase::shift_right()
173 : : */
174 : : template<typename Scalar, int N>
175 : : struct scalar_shift_right_op {
176 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_shift_right_op)
177 : :
178 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const
179 : : { return a >> N; }
180 : : template<typename Packet>
181 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
182 : : { return internal::parithmetic_shift_right<N>(a); }
183 : : };
184 : : template<typename Scalar, int N>
185 : : struct functor_traits<scalar_shift_right_op<Scalar,N> >
186 : : { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasShift }; };
187 : :
188 : : /** \internal
189 : : * \brief Template functor to logically shift a scalar left by a number of bits
190 : : *
191 : : * \sa class CwiseUnaryOp, MatrixBase::shift_left()
192 : : */
193 : : template<typename Scalar, int N>
194 : : struct scalar_shift_left_op {
195 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_shift_left_op)
196 : :
197 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const
198 : : { return a << N; }
199 : : template<typename Packet>
200 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
201 : : { return internal::plogical_shift_left<N>(a); }
202 : : };
203 : : template<typename Scalar, int N>
204 : : struct functor_traits<scalar_shift_left_op<Scalar,N> >
205 : : { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasShift }; };
206 : :
207 : : /** \internal
208 : : * \brief Template functor to extract the real part of a complex
209 : : *
210 : : * \sa class CwiseUnaryOp, MatrixBase::real()
211 : : */
212 : : template<typename Scalar>
213 : : struct scalar_real_op {
214 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
215 : : typedef typename NumTraits<Scalar>::Real result_type;
216 : : EIGEN_DEVICE_FUNC
217 : : EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::real(a); }
218 : : };
219 : : template<typename Scalar>
220 : : struct functor_traits<scalar_real_op<Scalar> >
221 : : { enum { Cost = 0, PacketAccess = false }; };
222 : :
223 : : /** \internal
224 : : * \brief Template functor to extract the imaginary part of a complex
225 : : *
226 : : * \sa class CwiseUnaryOp, MatrixBase::imag()
227 : : */
228 : : template<typename Scalar>
229 : : struct scalar_imag_op {
230 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
231 : : typedef typename NumTraits<Scalar>::Real result_type;
232 : : EIGEN_DEVICE_FUNC
233 : : EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::imag(a); }
234 : : };
235 : : template<typename Scalar>
236 : : struct functor_traits<scalar_imag_op<Scalar> >
237 : : { enum { Cost = 0, PacketAccess = false }; };
238 : :
239 : : /** \internal
240 : : * \brief Template functor to extract the real part of a complex as a reference
241 : : *
242 : : * \sa class CwiseUnaryOp, MatrixBase::real()
243 : : */
244 : : template<typename Scalar>
245 : : struct scalar_real_ref_op {
246 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
247 : : typedef typename NumTraits<Scalar>::Real result_type;
248 : : EIGEN_DEVICE_FUNC
249 : : EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::real_ref(*const_cast<Scalar*>(&a)); }
250 : : };
251 : : template<typename Scalar>
252 : : struct functor_traits<scalar_real_ref_op<Scalar> >
253 : : { enum { Cost = 0, PacketAccess = false }; };
254 : :
255 : : /** \internal
256 : : * \brief Template functor to extract the imaginary part of a complex as a reference
257 : : *
258 : : * \sa class CwiseUnaryOp, MatrixBase::imag()
259 : : */
260 : : template<typename Scalar>
261 : : struct scalar_imag_ref_op {
262 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
263 : : typedef typename NumTraits<Scalar>::Real result_type;
264 : : EIGEN_DEVICE_FUNC
265 : : EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::imag_ref(*const_cast<Scalar*>(&a)); }
266 : : };
267 : : template<typename Scalar>
268 : : struct functor_traits<scalar_imag_ref_op<Scalar> >
269 : : { enum { Cost = 0, PacketAccess = false }; };
270 : :
271 : : /** \internal
272 : : *
273 : : * \brief Template functor to compute the exponential of a scalar
274 : : *
275 : : * \sa class CwiseUnaryOp, Cwise::exp()
276 : : */
277 : : template<typename Scalar> struct scalar_exp_op {
278 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op)
279 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::exp(a); }
280 : : template <typename Packet>
281 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pexp(a); }
282 : : };
283 : : template <typename Scalar>
284 : : struct functor_traits<scalar_exp_op<Scalar> > {
285 : : enum {
286 : : PacketAccess = packet_traits<Scalar>::HasExp,
287 : : // The following numbers are based on the AVX implementation.
288 : : #ifdef EIGEN_VECTORIZE_FMA
289 : : // Haswell can issue 2 add/mul/madd per cycle.
290 : : Cost =
291 : : (sizeof(Scalar) == 4
292 : : // float: 8 pmadd, 4 pmul, 2 padd/psub, 6 other
293 : : ? (8 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost)
294 : : // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
295 : : : (14 * NumTraits<Scalar>::AddCost +
296 : : 6 * NumTraits<Scalar>::MulCost +
297 : : scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value))
298 : : #else
299 : : Cost =
300 : : (sizeof(Scalar) == 4
301 : : // float: 7 pmadd, 6 pmul, 4 padd/psub, 10 other
302 : : ? (21 * NumTraits<Scalar>::AddCost + 13 * NumTraits<Scalar>::MulCost)
303 : : // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other
304 : : : (23 * NumTraits<Scalar>::AddCost +
305 : : 12 * NumTraits<Scalar>::MulCost +
306 : : scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value))
307 : : #endif
308 : : };
309 : : };
310 : :
311 : : /** \internal
312 : : *
313 : : * \brief Template functor to compute the exponential of a scalar - 1.
314 : : *
315 : : * \sa class CwiseUnaryOp, ArrayBase::expm1()
316 : : */
317 : : template<typename Scalar> struct scalar_expm1_op {
318 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_expm1_op)
319 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::expm1(a); }
320 : : template <typename Packet>
321 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pexpm1(a); }
322 : : };
323 : : template <typename Scalar>
324 : : struct functor_traits<scalar_expm1_op<Scalar> > {
325 : : enum {
326 : : PacketAccess = packet_traits<Scalar>::HasExpm1,
327 : : Cost = functor_traits<scalar_exp_op<Scalar> >::Cost // TODO measure cost of expm1
328 : : };
329 : : };
330 : :
331 : : /** \internal
332 : : *
333 : : * \brief Template functor to compute the logarithm of a scalar
334 : : *
335 : : * \sa class CwiseUnaryOp, ArrayBase::log()
336 : : */
337 : : template<typename Scalar> struct scalar_log_op {
338 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op)
339 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log(a); }
340 : : template <typename Packet>
341 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog(a); }
342 : : };
343 : : template <typename Scalar>
344 : : struct functor_traits<scalar_log_op<Scalar> > {
345 : : enum {
346 : : PacketAccess = packet_traits<Scalar>::HasLog,
347 : : Cost =
348 : : (PacketAccess
349 : : // The following numbers are based on the AVX implementation.
350 : : #ifdef EIGEN_VECTORIZE_FMA
351 : : // 8 pmadd, 6 pmul, 8 padd/psub, 16 other, can issue 2 add/mul/madd per cycle.
352 : : ? (20 * NumTraits<Scalar>::AddCost + 7 * NumTraits<Scalar>::MulCost)
353 : : #else
354 : : // 8 pmadd, 6 pmul, 8 padd/psub, 20 other
355 : : ? (36 * NumTraits<Scalar>::AddCost + 14 * NumTraits<Scalar>::MulCost)
356 : : #endif
357 : : // Measured cost of std::log.
358 : : : sizeof(Scalar)==4 ? 40 : 85)
359 : : };
360 : : };
361 : :
362 : : /** \internal
363 : : *
364 : : * \brief Template functor to compute the logarithm of 1 plus a scalar value
365 : : *
366 : : * \sa class CwiseUnaryOp, ArrayBase::log1p()
367 : : */
368 : : template<typename Scalar> struct scalar_log1p_op {
369 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_log1p_op)
370 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log1p(a); }
371 : : template <typename Packet>
372 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog1p(a); }
373 : : };
374 : : template <typename Scalar>
375 : : struct functor_traits<scalar_log1p_op<Scalar> > {
376 : : enum {
377 : : PacketAccess = packet_traits<Scalar>::HasLog1p,
378 : : Cost = functor_traits<scalar_log_op<Scalar> >::Cost // TODO measure cost of log1p
379 : : };
380 : : };
381 : :
382 : : /** \internal
383 : : *
384 : : * \brief Template functor to compute the base-10 logarithm of a scalar
385 : : *
386 : : * \sa class CwiseUnaryOp, Cwise::log10()
387 : : */
388 : : template<typename Scalar> struct scalar_log10_op {
389 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_log10_op)
390 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { EIGEN_USING_STD(log10) return log10(a); }
391 : : template <typename Packet>
392 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog10(a); }
393 : : };
394 : : template<typename Scalar>
395 : : struct functor_traits<scalar_log10_op<Scalar> >
396 : : { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog10 }; };
397 : :
398 : : /** \internal
399 : : *
400 : : * \brief Template functor to compute the base-2 logarithm of a scalar
401 : : *
402 : : * \sa class CwiseUnaryOp, Cwise::log2()
403 : : */
404 : : template<typename Scalar> struct scalar_log2_op {
405 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_log2_op)
406 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return Scalar(EIGEN_LOG2E) * numext::log(a); }
407 : : template <typename Packet>
408 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog2(a); }
409 : : };
410 : : template<typename Scalar>
411 : : struct functor_traits<scalar_log2_op<Scalar> >
412 : : { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; };
413 : :
414 : : /** \internal
415 : : * \brief Template functor to compute the square root of a scalar
416 : : * \sa class CwiseUnaryOp, Cwise::sqrt()
417 : : */
418 : : template<typename Scalar> struct scalar_sqrt_op {
419 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op)
420 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sqrt(a); }
421 : : template <typename Packet>
422 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); }
423 : : };
424 : : template <typename Scalar>
425 : : struct functor_traits<scalar_sqrt_op<Scalar> > {
426 : : enum {
427 : : #if EIGEN_FAST_MATH
428 : : // The following numbers are based on the AVX implementation.
429 : : Cost = (sizeof(Scalar) == 8 ? 28
430 : : // 4 pmul, 1 pmadd, 3 other
431 : : : (3 * NumTraits<Scalar>::AddCost +
432 : : 5 * NumTraits<Scalar>::MulCost)),
433 : : #else
434 : : // The following numbers are based on min VSQRT throughput on Haswell.
435 : : Cost = (sizeof(Scalar) == 8 ? 28 : 14),
436 : : #endif
437 : : PacketAccess = packet_traits<Scalar>::HasSqrt
438 : : };
439 : : };
440 : :
441 : : // Boolean specialization to eliminate -Wimplicit-conversion-floating-point-to-bool warnings.
442 : : template<> struct scalar_sqrt_op<bool> {
443 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op)
444 : : EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator() (const bool& a) const { return a; }
445 : : template <typename Packet>
446 : : EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return a; }
447 : : };
448 : : template <>
449 : : struct functor_traits<scalar_sqrt_op<bool> > {
450 : : enum { Cost = 1, PacketAccess = packet_traits<bool>::Vectorizable };
451 : : };
452 : :
453 : : /** \internal
454 : : * \brief Template functor to compute the reciprocal square root of a scalar
455 : : * \sa class CwiseUnaryOp, Cwise::rsqrt()
456 : : */
457 : : template<typename Scalar> struct scalar_rsqrt_op {
458 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_rsqrt_op)
459 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::rsqrt(a); }
460 : : template <typename Packet>
461 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::prsqrt(a); }
462 : : };
463 : :
464 : : template<typename Scalar>
465 : : struct functor_traits<scalar_rsqrt_op<Scalar> >
466 : : { enum {
467 : : Cost = 5 * NumTraits<Scalar>::MulCost,
468 : : PacketAccess = packet_traits<Scalar>::HasRsqrt
469 : : };
470 : : };
471 : :
472 : : /** \internal
473 : : * \brief Template functor to compute the cosine of a scalar
474 : : * \sa class CwiseUnaryOp, ArrayBase::cos()
475 : : */
476 : : template<typename Scalar> struct scalar_cos_op {
477 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op)
478 : : EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return numext::cos(a); }
479 : : template <typename Packet>
480 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcos(a); }
481 : : };
482 : : template<typename Scalar>
483 : : struct functor_traits<scalar_cos_op<Scalar> >
484 : : {
485 : : enum {
486 : : Cost = 5 * NumTraits<Scalar>::MulCost,
487 : : PacketAccess = packet_traits<Scalar>::HasCos
488 : : };
489 : : };
490 : :
491 : : /** \internal
492 : : * \brief Template functor to compute the sine of a scalar
493 : : * \sa class CwiseUnaryOp, ArrayBase::sin()
494 : : */
495 : : template<typename Scalar> struct scalar_sin_op {
496 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op)
497 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sin(a); }
498 : : template <typename Packet>
499 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psin(a); }
500 : : };
501 : : template<typename Scalar>
502 : : struct functor_traits<scalar_sin_op<Scalar> >
503 : : {
504 : : enum {
505 : : Cost = 5 * NumTraits<Scalar>::MulCost,
506 : : PacketAccess = packet_traits<Scalar>::HasSin
507 : : };
508 : : };
509 : :
510 : :
511 : : /** \internal
512 : : * \brief Template functor to compute the tan of a scalar
513 : : * \sa class CwiseUnaryOp, ArrayBase::tan()
514 : : */
515 : : template<typename Scalar> struct scalar_tan_op {
516 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op)
517 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::tan(a); }
518 : : template <typename Packet>
519 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::ptan(a); }
520 : : };
521 : : template<typename Scalar>
522 : : struct functor_traits<scalar_tan_op<Scalar> >
523 : : {
524 : : enum {
525 : : Cost = 5 * NumTraits<Scalar>::MulCost,
526 : : PacketAccess = packet_traits<Scalar>::HasTan
527 : : };
528 : : };
529 : :
530 : : /** \internal
531 : : * \brief Template functor to compute the arc cosine of a scalar
532 : : * \sa class CwiseUnaryOp, ArrayBase::acos()
533 : : */
534 : : template<typename Scalar> struct scalar_acos_op {
535 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op)
536 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::acos(a); }
537 : : template <typename Packet>
538 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
539 : : };
540 : : template<typename Scalar>
541 : : struct functor_traits<scalar_acos_op<Scalar> >
542 : : {
543 : : enum {
544 : : Cost = 5 * NumTraits<Scalar>::MulCost,
545 : : PacketAccess = packet_traits<Scalar>::HasACos
546 : : };
547 : : };
548 : :
549 : : /** \internal
550 : : * \brief Template functor to compute the arc sine of a scalar
551 : : * \sa class CwiseUnaryOp, ArrayBase::asin()
552 : : */
553 : : template<typename Scalar> struct scalar_asin_op {
554 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op)
555 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::asin(a); }
556 : : template <typename Packet>
557 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pasin(a); }
558 : : };
559 : : template<typename Scalar>
560 : : struct functor_traits<scalar_asin_op<Scalar> >
561 : : {
562 : : enum {
563 : : Cost = 5 * NumTraits<Scalar>::MulCost,
564 : : PacketAccess = packet_traits<Scalar>::HasASin
565 : : };
566 : : };
567 : :
568 : :
569 : : /** \internal
570 : : * \brief Template functor to compute the atan of a scalar
571 : : * \sa class CwiseUnaryOp, ArrayBase::atan()
572 : : */
573 : : template<typename Scalar> struct scalar_atan_op {
574 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_atan_op)
575 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::atan(a); }
576 : : template <typename Packet>
577 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::patan(a); }
578 : : };
579 : : template<typename Scalar>
580 : : struct functor_traits<scalar_atan_op<Scalar> >
581 : : {
582 : : enum {
583 : : Cost = 5 * NumTraits<Scalar>::MulCost,
584 : : PacketAccess = packet_traits<Scalar>::HasATan
585 : : };
586 : : };
587 : :
588 : : /** \internal
589 : : * \brief Template functor to compute the tanh of a scalar
590 : : * \sa class CwiseUnaryOp, ArrayBase::tanh()
591 : : */
592 : : template <typename Scalar>
593 : : struct scalar_tanh_op {
594 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_tanh_op)
595 : : EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::tanh(a); }
596 : : template <typename Packet>
597 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const { return ptanh(x); }
598 : : };
599 : :
600 : : template <typename Scalar>
601 : : struct functor_traits<scalar_tanh_op<Scalar> > {
602 : : enum {
603 : : PacketAccess = packet_traits<Scalar>::HasTanh,
604 : : Cost = ( (EIGEN_FAST_MATH && is_same<Scalar,float>::value)
605 : : // The following numbers are based on the AVX implementation,
606 : : #ifdef EIGEN_VECTORIZE_FMA
607 : : // Haswell can issue 2 add/mul/madd per cycle.
608 : : // 9 pmadd, 2 pmul, 1 div, 2 other
609 : : ? (2 * NumTraits<Scalar>::AddCost +
610 : : 6 * NumTraits<Scalar>::MulCost +
611 : : scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)
612 : : #else
613 : : ? (11 * NumTraits<Scalar>::AddCost +
614 : : 11 * NumTraits<Scalar>::MulCost +
615 : : scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)
616 : : #endif
617 : : // This number assumes a naive implementation of tanh
618 : : : (6 * NumTraits<Scalar>::AddCost +
619 : : 3 * NumTraits<Scalar>::MulCost +
620 : : 2 * scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value +
621 : : functor_traits<scalar_exp_op<Scalar> >::Cost))
622 : : };
623 : : };
624 : :
625 : : #if EIGEN_HAS_CXX11_MATH
626 : : /** \internal
627 : : * \brief Template functor to compute the atanh of a scalar
628 : : * \sa class CwiseUnaryOp, ArrayBase::atanh()
629 : : */
630 : : template <typename Scalar>
631 : : struct scalar_atanh_op {
632 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_atanh_op)
633 : : EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::atanh(a); }
634 : : };
635 : :
636 : : template <typename Scalar>
637 : : struct functor_traits<scalar_atanh_op<Scalar> > {
638 : : enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
639 : : };
640 : : #endif
641 : :
642 : : /** \internal
643 : : * \brief Template functor to compute the sinh of a scalar
644 : : * \sa class CwiseUnaryOp, ArrayBase::sinh()
645 : : */
646 : : template<typename Scalar> struct scalar_sinh_op {
647 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_sinh_op)
648 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sinh(a); }
649 : : template <typename Packet>
650 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psinh(a); }
651 : : };
652 : : template<typename Scalar>
653 : : struct functor_traits<scalar_sinh_op<Scalar> >
654 : : {
655 : : enum {
656 : : Cost = 5 * NumTraits<Scalar>::MulCost,
657 : : PacketAccess = packet_traits<Scalar>::HasSinh
658 : : };
659 : : };
660 : :
661 : : #if EIGEN_HAS_CXX11_MATH
662 : : /** \internal
663 : : * \brief Template functor to compute the asinh of a scalar
664 : : * \sa class CwiseUnaryOp, ArrayBase::asinh()
665 : : */
666 : : template <typename Scalar>
667 : : struct scalar_asinh_op {
668 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_asinh_op)
669 : : EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::asinh(a); }
670 : : };
671 : :
672 : : template <typename Scalar>
673 : : struct functor_traits<scalar_asinh_op<Scalar> > {
674 : : enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
675 : : };
676 : : #endif
677 : :
678 : : /** \internal
679 : : * \brief Template functor to compute the cosh of a scalar
680 : : * \sa class CwiseUnaryOp, ArrayBase::cosh()
681 : : */
682 : : template<typename Scalar> struct scalar_cosh_op {
683 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cosh_op)
684 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::cosh(a); }
685 : : template <typename Packet>
686 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcosh(a); }
687 : : };
688 : : template<typename Scalar>
689 : : struct functor_traits<scalar_cosh_op<Scalar> >
690 : : {
691 : : enum {
692 : : Cost = 5 * NumTraits<Scalar>::MulCost,
693 : : PacketAccess = packet_traits<Scalar>::HasCosh
694 : : };
695 : : };
696 : :
697 : : #if EIGEN_HAS_CXX11_MATH
698 : : /** \internal
699 : : * \brief Template functor to compute the acosh of a scalar
700 : : * \sa class CwiseUnaryOp, ArrayBase::acosh()
701 : : */
702 : : template <typename Scalar>
703 : : struct scalar_acosh_op {
704 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_acosh_op)
705 : : EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::acosh(a); }
706 : : };
707 : :
708 : : template <typename Scalar>
709 : : struct functor_traits<scalar_acosh_op<Scalar> > {
710 : : enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
711 : : };
712 : : #endif
713 : :
714 : : /** \internal
715 : : * \brief Template functor to compute the inverse of a scalar
716 : : * \sa class CwiseUnaryOp, Cwise::inverse()
717 : : */
718 : : template<typename Scalar>
719 : : struct scalar_inverse_op {
720 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op)
721 : : EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; }
722 : : template<typename Packet>
723 : : EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
724 : : { return internal::pdiv(pset1<Packet>(Scalar(1)),a); }
725 : : };
726 : : template <typename Scalar>
727 : : struct functor_traits<scalar_inverse_op<Scalar> > {
728 : : enum {
729 : : PacketAccess = packet_traits<Scalar>::HasDiv,
730 : : Cost = scalar_div_cost<Scalar, PacketAccess>::value
731 : : };
732 : : };
733 : :
734 : : /** \internal
735 : : * \brief Template functor to compute the square of a scalar
736 : : * \sa class CwiseUnaryOp, Cwise::square()
737 : : */
738 : : template<typename Scalar>
739 : : struct scalar_square_op {
740 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op)
741 : : EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a; }
742 : : template<typename Packet>
743 : : EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
744 : : { return internal::pmul(a,a); }
745 : : };
746 : : template<typename Scalar>
747 : : struct functor_traits<scalar_square_op<Scalar> >
748 : : { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
749 : :
750 : : // Boolean specialization to avoid -Wint-in-bool-context warnings on GCC.
751 : : template<>
752 : : struct scalar_square_op<bool> {
753 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op)
754 : : EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator() (const bool& a) const { return a; }
755 : : template<typename Packet>
756 : : EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
757 : : { return a; }
758 : : };
759 : : template<>
760 : : struct functor_traits<scalar_square_op<bool> >
761 : : { enum { Cost = 0, PacketAccess = packet_traits<bool>::Vectorizable }; };
762 : :
763 : : /** \internal
764 : : * \brief Template functor to compute the cube of a scalar
765 : : * \sa class CwiseUnaryOp, Cwise::cube()
766 : : */
767 : : template<typename Scalar>
768 : : struct scalar_cube_op {
769 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op)
770 : : EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a*a; }
771 : : template<typename Packet>
772 : : EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
773 : : { return internal::pmul(a,pmul(a,a)); }
774 : : };
775 : : template<typename Scalar>
776 : : struct functor_traits<scalar_cube_op<Scalar> >
777 : : { enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
778 : :
779 : : // Boolean specialization to avoid -Wint-in-bool-context warnings on GCC.
780 : : template<>
781 : : struct scalar_cube_op<bool> {
782 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op)
783 : : EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline bool operator() (const bool& a) const { return a; }
784 : : template<typename Packet>
785 : : EIGEN_DEPRECATED EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
786 : : { return a; }
787 : : };
788 : : template<>
789 : : struct functor_traits<scalar_cube_op<bool> >
790 : : { enum { Cost = 0, PacketAccess = packet_traits<bool>::Vectorizable }; };
791 : :
792 : : /** \internal
793 : : * \brief Template functor to compute the rounded value of a scalar
794 : : * \sa class CwiseUnaryOp, ArrayBase::round()
795 : : */
796 : : template<typename Scalar> struct scalar_round_op {
797 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_round_op)
798 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::round(a); }
799 : : template <typename Packet>
800 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pround(a); }
801 : : };
802 : : template<typename Scalar>
803 : : struct functor_traits<scalar_round_op<Scalar> >
804 : : {
805 : : enum {
806 : : Cost = NumTraits<Scalar>::MulCost,
807 : : PacketAccess = packet_traits<Scalar>::HasRound
808 : : };
809 : : };
810 : :
811 : : /** \internal
812 : : * \brief Template functor to compute the floor of a scalar
813 : : * \sa class CwiseUnaryOp, ArrayBase::floor()
814 : : */
815 : : template<typename Scalar> struct scalar_floor_op {
816 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_floor_op)
817 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::floor(a); }
818 : : template <typename Packet>
819 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pfloor(a); }
820 : : };
821 : : template<typename Scalar>
822 : : struct functor_traits<scalar_floor_op<Scalar> >
823 : : {
824 : : enum {
825 : : Cost = NumTraits<Scalar>::MulCost,
826 : : PacketAccess = packet_traits<Scalar>::HasFloor
827 : : };
828 : : };
829 : :
830 : : /** \internal
831 : : * \brief Template functor to compute the rounded (with current rounding mode) value of a scalar
832 : : * \sa class CwiseUnaryOp, ArrayBase::rint()
833 : : */
834 : : template<typename Scalar> struct scalar_rint_op {
835 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_rint_op)
836 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::rint(a); }
837 : : template <typename Packet>
838 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::print(a); }
839 : : };
840 : : template<typename Scalar>
841 : : struct functor_traits<scalar_rint_op<Scalar> >
842 : : {
843 : : enum {
844 : : Cost = NumTraits<Scalar>::MulCost,
845 : : PacketAccess = packet_traits<Scalar>::HasRint
846 : : };
847 : : };
848 : :
849 : : /** \internal
850 : : * \brief Template functor to compute the ceil of a scalar
851 : : * \sa class CwiseUnaryOp, ArrayBase::ceil()
852 : : */
853 : : template<typename Scalar> struct scalar_ceil_op {
854 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_ceil_op)
855 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::ceil(a); }
856 : : template <typename Packet>
857 : : EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pceil(a); }
858 : : };
859 : : template<typename Scalar>
860 : : struct functor_traits<scalar_ceil_op<Scalar> >
861 : : {
862 : : enum {
863 : : Cost = NumTraits<Scalar>::MulCost,
864 : : PacketAccess = packet_traits<Scalar>::HasCeil
865 : : };
866 : : };
867 : :
868 : : /** \internal
869 : : * \brief Template functor to compute whether a scalar is NaN
870 : : * \sa class CwiseUnaryOp, ArrayBase::isnan()
871 : : */
872 : : template<typename Scalar> struct scalar_isnan_op {
873 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_isnan_op)
874 : : typedef bool result_type;
875 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const {
876 : : #if defined(SYCL_DEVICE_ONLY)
877 : : return numext::isnan(a);
878 : : #else
879 : : return (numext::isnan)(a);
880 : : #endif
881 : : }
882 : : };
883 : : template<typename Scalar>
884 : : struct functor_traits<scalar_isnan_op<Scalar> >
885 : : {
886 : : enum {
887 : : Cost = NumTraits<Scalar>::MulCost,
888 : : PacketAccess = false
889 : : };
890 : : };
891 : :
892 : : /** \internal
893 : : * \brief Template functor to check whether a scalar is +/-inf
894 : : * \sa class CwiseUnaryOp, ArrayBase::isinf()
895 : : */
896 : : template<typename Scalar> struct scalar_isinf_op {
897 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_isinf_op)
898 : : typedef bool result_type;
899 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const {
900 : : #if defined(SYCL_DEVICE_ONLY)
901 : : return numext::isinf(a);
902 : : #else
903 : : return (numext::isinf)(a);
904 : : #endif
905 : : }
906 : : };
907 : : template<typename Scalar>
908 : : struct functor_traits<scalar_isinf_op<Scalar> >
909 : : {
910 : : enum {
911 : : Cost = NumTraits<Scalar>::MulCost,
912 : : PacketAccess = false
913 : : };
914 : : };
915 : :
916 : : /** \internal
917 : : * \brief Template functor to check whether a scalar has a finite value
918 : : * \sa class CwiseUnaryOp, ArrayBase::isfinite()
919 : : */
920 : : template<typename Scalar> struct scalar_isfinite_op {
921 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_isfinite_op)
922 : : typedef bool result_type;
923 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const {
924 : : #if defined(SYCL_DEVICE_ONLY)
925 : : return numext::isfinite(a);
926 : : #else
927 : : return (numext::isfinite)(a);
928 : : #endif
929 : : }
930 : : };
931 : : template<typename Scalar>
932 : : struct functor_traits<scalar_isfinite_op<Scalar> >
933 : : {
934 : : enum {
935 : : Cost = NumTraits<Scalar>::MulCost,
936 : : PacketAccess = false
937 : : };
938 : : };
939 : :
940 : : /** \internal
941 : : * \brief Template functor to compute the logical not of a boolean
942 : : *
943 : : * \sa class CwiseUnaryOp, ArrayBase::operator!
944 : : */
945 : : template<typename Scalar> struct scalar_boolean_not_op {
946 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_not_op)
947 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a) const { return !a; }
948 : : };
949 : : template<typename Scalar>
950 : : struct functor_traits<scalar_boolean_not_op<Scalar> > {
951 : : enum {
952 : : Cost = NumTraits<bool>::AddCost,
953 : : PacketAccess = false
954 : : };
955 : : };
956 : :
957 : : /** \internal
958 : : * \brief Template functor to compute the signum of a scalar
959 : : * \sa class CwiseUnaryOp, Cwise::sign()
960 : : */
961 : : template<typename Scalar,bool is_complex=(NumTraits<Scalar>::IsComplex!=0), bool is_integer=(NumTraits<Scalar>::IsInteger!=0) > struct scalar_sign_op;
962 : : template<typename Scalar>
963 : : struct scalar_sign_op<Scalar, false, true> {
964 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op)
965 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const
966 : : {
967 : : return Scalar( (a>Scalar(0)) - (a<Scalar(0)) );
968 : : }
969 : : //TODO
970 : : //template <typename Packet>
971 : : //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); }
972 : : };
973 : :
974 : : template<typename Scalar>
975 : : struct scalar_sign_op<Scalar, false, false> {
976 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op)
977 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const
978 : : {
979 : : return (numext::isnan)(a) ? a : Scalar( (a>Scalar(0)) - (a<Scalar(0)) );
980 : : }
981 : : //TODO
982 : : //template <typename Packet>
983 : : //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); }
984 : : };
985 : :
986 : : template<typename Scalar, bool is_integer>
987 : : struct scalar_sign_op<Scalar,true, is_integer> {
988 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op)
989 : : EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const
990 : : {
991 : : typedef typename NumTraits<Scalar>::Real real_type;
992 : : real_type aa = numext::abs(a);
993 : : if (aa==real_type(0))
994 : : return Scalar(0);
995 : : aa = real_type(1)/aa;
996 : : return Scalar(a.real()*aa, a.imag()*aa );
997 : : }
998 : : //TODO
999 : : //template <typename Packet>
1000 : : //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); }
1001 : : };
1002 : : template<typename Scalar>
1003 : : struct functor_traits<scalar_sign_op<Scalar> >
1004 : : { enum {
1005 : : Cost =
1006 : : NumTraits<Scalar>::IsComplex
1007 : : ? ( 8*NumTraits<Scalar>::MulCost ) // roughly
1008 : : : ( 3*NumTraits<Scalar>::AddCost),
1009 : : PacketAccess = packet_traits<Scalar>::HasSign
1010 : : };
1011 : : };
1012 : :
1013 : : /** \internal
1014 : : * \brief Template functor to compute the logistic function of a scalar
1015 : : * \sa class CwiseUnaryOp, ArrayBase::logistic()
1016 : : */
1017 : : template <typename T>
1018 : : struct scalar_logistic_op {
1019 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_logistic_op)
1020 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const {
1021 : : return packetOp(x);
1022 : : }
1023 : :
1024 : : template <typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1025 : : Packet packetOp(const Packet& x) const {
1026 : : const Packet one = pset1<Packet>(T(1));
1027 : : return pdiv(one, padd(one, pexp(pnegate(x))));
1028 : : }
1029 : : };
1030 : :
1031 : : #ifndef EIGEN_GPU_COMPILE_PHASE
1032 : : /** \internal
1033 : : * \brief Template specialization of the logistic function for float.
1034 : : *
1035 : : * Uses just a 9/10-degree rational interpolant which
1036 : : * interpolates 1/(1+exp(-x)) - 0.5 up to a couple of ulps in the range
1037 : : * [-9, 18]. Below -9 we use the more accurate approximation
1038 : : * 1/(1+exp(-x)) ~= exp(x), and above 18 the logistic function is 1 withing
1039 : : * one ulp. The shifted logistic is interpolated because it was easier to
1040 : : * make the fit converge.
1041 : : *
1042 : : */
1043 : : template <>
1044 : : struct scalar_logistic_op<float> {
1045 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_logistic_op)
1046 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE float operator()(const float& x) const {
1047 : : return packetOp(x);
1048 : : }
1049 : :
1050 : : template <typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1051 : : Packet packetOp(const Packet& _x) const {
1052 : : const Packet cutoff_lower = pset1<Packet>(-9.f);
1053 : : const Packet lt_mask = pcmp_lt<Packet>(_x, cutoff_lower);
1054 : : const bool any_small = predux_any(lt_mask);
1055 : :
1056 : : // The upper cut-off is the smallest x for which the rational approximation evaluates to 1.
1057 : : // Choosing this value saves us a few instructions clamping the results at the end.
1058 : : #ifdef EIGEN_VECTORIZE_FMA
1059 : : const Packet cutoff_upper = pset1<Packet>(15.7243833541870117f);
1060 : : #else
1061 : : const Packet cutoff_upper = pset1<Packet>(15.6437711715698242f);
1062 : : #endif
1063 : : const Packet x = pmin(_x, cutoff_upper);
1064 : :
1065 : : // The monomial coefficients of the numerator polynomial (odd).
1066 : : const Packet alpha_1 = pset1<Packet>(2.48287947061529e-01f);
1067 : : const Packet alpha_3 = pset1<Packet>(8.51377133304701e-03f);
1068 : : const Packet alpha_5 = pset1<Packet>(6.08574864600143e-05f);
1069 : : const Packet alpha_7 = pset1<Packet>(1.15627324459942e-07f);
1070 : : const Packet alpha_9 = pset1<Packet>(4.37031012579801e-11f);
1071 : :
1072 : : // The monomial coefficients of the denominator polynomial (even).
1073 : : const Packet beta_0 = pset1<Packet>(9.93151921023180e-01f);
1074 : : const Packet beta_2 = pset1<Packet>(1.16817656904453e-01f);
1075 : : const Packet beta_4 = pset1<Packet>(1.70198817374094e-03f);
1076 : : const Packet beta_6 = pset1<Packet>(6.29106785017040e-06f);
1077 : : const Packet beta_8 = pset1<Packet>(5.76102136993427e-09f);
1078 : : const Packet beta_10 = pset1<Packet>(6.10247389755681e-13f);
1079 : :
1080 : : // Since the polynomials are odd/even, we need x^2.
1081 : : const Packet x2 = pmul(x, x);
1082 : :
1083 : : // Evaluate the numerator polynomial p.
1084 : : Packet p = pmadd(x2, alpha_9, alpha_7);
1085 : : p = pmadd(x2, p, alpha_5);
1086 : : p = pmadd(x2, p, alpha_3);
1087 : : p = pmadd(x2, p, alpha_1);
1088 : : p = pmul(x, p);
1089 : :
1090 : : // Evaluate the denominator polynomial q.
1091 : : Packet q = pmadd(x2, beta_10, beta_8);
1092 : : q = pmadd(x2, q, beta_6);
1093 : : q = pmadd(x2, q, beta_4);
1094 : : q = pmadd(x2, q, beta_2);
1095 : : q = pmadd(x2, q, beta_0);
1096 : : // Divide the numerator by the denominator and shift it up.
1097 : : const Packet logistic = padd(pdiv(p, q), pset1<Packet>(0.5f));
1098 : : if (EIGEN_PREDICT_FALSE(any_small)) {
1099 : : const Packet exponential = pexp(_x);
1100 : : return pselect(lt_mask, exponential, logistic);
1101 : : } else {
1102 : : return logistic;
1103 : : }
1104 : : }
1105 : : };
1106 : : #endif // #ifndef EIGEN_GPU_COMPILE_PHASE
1107 : :
1108 : : template <typename T>
1109 : : struct functor_traits<scalar_logistic_op<T> > {
1110 : : enum {
1111 : : // The cost estimate for float here here is for the common(?) case where
1112 : : // all arguments are greater than -9.
1113 : : Cost = scalar_div_cost<T, packet_traits<T>::HasDiv>::value +
1114 : : (internal::is_same<T, float>::value
1115 : : ? NumTraits<T>::AddCost * 15 + NumTraits<T>::MulCost * 11
1116 : : : NumTraits<T>::AddCost * 2 +
1117 : : functor_traits<scalar_exp_op<T> >::Cost),
1118 : : PacketAccess =
1119 : : packet_traits<T>::HasAdd && packet_traits<T>::HasDiv &&
1120 : : (internal::is_same<T, float>::value
1121 : : ? packet_traits<T>::HasMul && packet_traits<T>::HasMax &&
1122 : : packet_traits<T>::HasMin
1123 : : : packet_traits<T>::HasNegate && packet_traits<T>::HasExp)
1124 : : };
1125 : : };
1126 : :
1127 : : } // end namespace internal
1128 : :
1129 : : } // end namespace Eigen
1130 : :
1131 : : #endif // EIGEN_FUNCTORS_H
|