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 | EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op) |
24 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; } |
25 | template<typename Packet> |
26 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const |
27 | { 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 | EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op) |
93 | typedef typename NumTraits<Scalar>::Real result_type; |
94 | EIGEN_DEVICE_FUNC |
95 | 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 | 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 { using numext::conj; return 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 = NumTraits<Scalar>::IsComplex ? NumTraits<Scalar>::AddCost : 0, |
121 | PacketAccess = packet_traits<Scalar>::HasConj |
122 | }; |
123 | }; |
124 | |
125 | /** \internal |
126 | * \brief Template functor to compute the phase angle of a complex |
127 | * |
128 | * \sa class CwiseUnaryOp, Cwise::arg |
129 | */ |
130 | template<typename Scalar> struct scalar_arg_op { |
131 | EIGEN_EMPTY_STRUCT_CTOR(scalar_arg_op) |
132 | typedef typename NumTraits<Scalar>::Real result_type; |
133 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { using numext::arg; return arg(a); } |
134 | template<typename Packet> |
135 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const |
136 | { return internal::parg(a); } |
137 | }; |
138 | template<typename Scalar> |
139 | struct functor_traits<scalar_arg_op<Scalar> > |
140 | { |
141 | enum { |
142 | Cost = NumTraits<Scalar>::IsComplex ? 5 * NumTraits<Scalar>::MulCost : NumTraits<Scalar>::AddCost, |
143 | PacketAccess = packet_traits<Scalar>::HasArg |
144 | }; |
145 | }; |
146 | /** \internal |
147 | * \brief Template functor to cast a scalar to another type |
148 | * |
149 | * \sa class CwiseUnaryOp, MatrixBase::cast() |
150 | */ |
151 | template<typename Scalar, typename NewType> |
152 | struct scalar_cast_op { |
153 | EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op) |
154 | typedef NewType result_type; |
155 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); } |
156 | }; |
157 | template<typename Scalar, typename NewType> |
158 | struct functor_traits<scalar_cast_op<Scalar,NewType> > |
159 | { enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; }; |
160 | |
161 | /** \internal |
162 | * \brief Template functor to extract the real part of a complex |
163 | * |
164 | * \sa class CwiseUnaryOp, MatrixBase::real() |
165 | */ |
166 | template<typename Scalar> |
167 | struct scalar_real_op { |
168 | EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op) |
169 | typedef typename NumTraits<Scalar>::Real result_type; |
170 | EIGEN_DEVICE_FUNC |
171 | EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::real(a); } |
172 | }; |
173 | template<typename Scalar> |
174 | struct functor_traits<scalar_real_op<Scalar> > |
175 | { enum { Cost = 0, PacketAccess = false }; }; |
176 | |
177 | /** \internal |
178 | * \brief Template functor to extract the imaginary part of a complex |
179 | * |
180 | * \sa class CwiseUnaryOp, MatrixBase::imag() |
181 | */ |
182 | template<typename Scalar> |
183 | struct scalar_imag_op { |
184 | EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op) |
185 | typedef typename NumTraits<Scalar>::Real result_type; |
186 | EIGEN_DEVICE_FUNC |
187 | EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return numext::imag(a); } |
188 | }; |
189 | template<typename Scalar> |
190 | struct functor_traits<scalar_imag_op<Scalar> > |
191 | { enum { Cost = 0, PacketAccess = false }; }; |
192 | |
193 | /** \internal |
194 | * \brief Template functor to extract the real part of a complex as a reference |
195 | * |
196 | * \sa class CwiseUnaryOp, MatrixBase::real() |
197 | */ |
198 | template<typename Scalar> |
199 | struct scalar_real_ref_op { |
200 | EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op) |
201 | typedef typename NumTraits<Scalar>::Real result_type; |
202 | EIGEN_DEVICE_FUNC |
203 | EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::real_ref(*const_cast<Scalar*>(&a)); } |
204 | }; |
205 | template<typename Scalar> |
206 | struct functor_traits<scalar_real_ref_op<Scalar> > |
207 | { enum { Cost = 0, PacketAccess = false }; }; |
208 | |
209 | /** \internal |
210 | * \brief Template functor to extract the imaginary part of a complex as a reference |
211 | * |
212 | * \sa class CwiseUnaryOp, MatrixBase::imag() |
213 | */ |
214 | template<typename Scalar> |
215 | struct scalar_imag_ref_op { |
216 | EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op) |
217 | typedef typename NumTraits<Scalar>::Real result_type; |
218 | EIGEN_DEVICE_FUNC |
219 | EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return numext::imag_ref(*const_cast<Scalar*>(&a)); } |
220 | }; |
221 | template<typename Scalar> |
222 | struct functor_traits<scalar_imag_ref_op<Scalar> > |
223 | { enum { Cost = 0, PacketAccess = false }; }; |
224 | |
225 | /** \internal |
226 | * |
227 | * \brief Template functor to compute the exponential of a scalar |
228 | * |
229 | * \sa class CwiseUnaryOp, Cwise::exp() |
230 | */ |
231 | template<typename Scalar> struct scalar_exp_op { |
232 | EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op) |
233 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::exp(a); } |
234 | template <typename Packet> |
235 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pexp(a); } |
236 | }; |
237 | template <typename Scalar> |
238 | struct functor_traits<scalar_exp_op<Scalar> > { |
239 | enum { |
240 | PacketAccess = packet_traits<Scalar>::HasExp, |
241 | // The following numbers are based on the AVX implementation. |
242 | #ifdef EIGEN_VECTORIZE_FMA |
243 | // Haswell can issue 2 add/mul/madd per cycle. |
244 | Cost = |
245 | (sizeof(Scalar) == 4 |
246 | // float: 8 pmadd, 4 pmul, 2 padd/psub, 6 other |
247 | ? (8 * NumTraits<Scalar>::AddCost + 6 * NumTraits<Scalar>::MulCost) |
248 | // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other |
249 | : (14 * NumTraits<Scalar>::AddCost + |
250 | 6 * NumTraits<Scalar>::MulCost + |
251 | scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)) |
252 | #else |
253 | Cost = |
254 | (sizeof(Scalar) == 4 |
255 | // float: 7 pmadd, 6 pmul, 4 padd/psub, 10 other |
256 | ? (21 * NumTraits<Scalar>::AddCost + 13 * NumTraits<Scalar>::MulCost) |
257 | // double: 7 pmadd, 5 pmul, 3 padd/psub, 1 div, 13 other |
258 | : (23 * NumTraits<Scalar>::AddCost + |
259 | 12 * NumTraits<Scalar>::MulCost + |
260 | scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value)) |
261 | #endif |
262 | }; |
263 | }; |
264 | |
265 | /** \internal |
266 | * |
267 | * \brief Template functor to compute the logarithm of a scalar |
268 | * |
269 | * \sa class CwiseUnaryOp, ArrayBase::log() |
270 | */ |
271 | template<typename Scalar> struct scalar_log_op { |
272 | EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op) |
273 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log(a); } |
274 | template <typename Packet> |
275 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog(a); } |
276 | }; |
277 | template <typename Scalar> |
278 | struct functor_traits<scalar_log_op<Scalar> > { |
279 | enum { |
280 | PacketAccess = packet_traits<Scalar>::HasLog, |
281 | Cost = |
282 | (PacketAccess |
283 | // The following numbers are based on the AVX implementation. |
284 | #ifdef EIGEN_VECTORIZE_FMA |
285 | // 8 pmadd, 6 pmul, 8 padd/psub, 16 other, can issue 2 add/mul/madd per cycle. |
286 | ? (20 * NumTraits<Scalar>::AddCost + 7 * NumTraits<Scalar>::MulCost) |
287 | #else |
288 | // 8 pmadd, 6 pmul, 8 padd/psub, 20 other |
289 | ? (36 * NumTraits<Scalar>::AddCost + 14 * NumTraits<Scalar>::MulCost) |
290 | #endif |
291 | // Measured cost of std::log. |
292 | : sizeof(Scalar)==4 ? 40 : 85) |
293 | }; |
294 | }; |
295 | |
296 | /** \internal |
297 | * |
298 | * \brief Template functor to compute the logarithm of 1 plus a scalar value |
299 | * |
300 | * \sa class CwiseUnaryOp, ArrayBase::log1p() |
301 | */ |
302 | template<typename Scalar> struct scalar_log1p_op { |
303 | EIGEN_EMPTY_STRUCT_CTOR(scalar_log1p_op) |
304 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::log1p(a); } |
305 | template <typename Packet> |
306 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog1p(a); } |
307 | }; |
308 | template <typename Scalar> |
309 | struct functor_traits<scalar_log1p_op<Scalar> > { |
310 | enum { |
311 | PacketAccess = packet_traits<Scalar>::HasLog1p, |
312 | Cost = functor_traits<scalar_log_op<Scalar> >::Cost // TODO measure cost of log1p |
313 | }; |
314 | }; |
315 | |
316 | /** \internal |
317 | * |
318 | * \brief Template functor to compute the base-10 logarithm of a scalar |
319 | * |
320 | * \sa class CwiseUnaryOp, Cwise::log10() |
321 | */ |
322 | template<typename Scalar> struct scalar_log10_op { |
323 | EIGEN_EMPTY_STRUCT_CTOR(scalar_log10_op) |
324 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { EIGEN_USING_STD_MATH(log10) return log10(a); } |
325 | template <typename Packet> |
326 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plog10(a); } |
327 | }; |
328 | template<typename Scalar> |
329 | struct functor_traits<scalar_log10_op<Scalar> > |
330 | { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog10 }; }; |
331 | |
332 | /** \internal |
333 | * \brief Template functor to compute the square root of a scalar |
334 | * \sa class CwiseUnaryOp, Cwise::sqrt() |
335 | */ |
336 | template<typename Scalar> struct scalar_sqrt_op { |
337 | EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op) |
338 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sqrt(a); } |
339 | template <typename Packet> |
340 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); } |
341 | }; |
342 | template <typename Scalar> |
343 | struct functor_traits<scalar_sqrt_op<Scalar> > { |
344 | enum { |
345 | #if EIGEN_FAST_MATH |
346 | // The following numbers are based on the AVX implementation. |
347 | Cost = (sizeof(Scalar) == 8 ? 28 |
348 | // 4 pmul, 1 pmadd, 3 other |
349 | : (3 * NumTraits<Scalar>::AddCost + |
350 | 5 * NumTraits<Scalar>::MulCost)), |
351 | #else |
352 | // The following numbers are based on min VSQRT throughput on Haswell. |
353 | Cost = (sizeof(Scalar) == 8 ? 28 : 14), |
354 | #endif |
355 | PacketAccess = packet_traits<Scalar>::HasSqrt |
356 | }; |
357 | }; |
358 | |
359 | /** \internal |
360 | * \brief Template functor to compute the reciprocal square root of a scalar |
361 | * \sa class CwiseUnaryOp, Cwise::rsqrt() |
362 | */ |
363 | template<typename Scalar> struct scalar_rsqrt_op { |
364 | EIGEN_EMPTY_STRUCT_CTOR(scalar_rsqrt_op) |
365 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return Scalar(1)/numext::sqrt(a); } |
366 | template <typename Packet> |
367 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::prsqrt(a); } |
368 | }; |
369 | |
370 | template<typename Scalar> |
371 | struct functor_traits<scalar_rsqrt_op<Scalar> > |
372 | { enum { |
373 | Cost = 5 * NumTraits<Scalar>::MulCost, |
374 | PacketAccess = packet_traits<Scalar>::HasRsqrt |
375 | }; |
376 | }; |
377 | |
378 | /** \internal |
379 | * \brief Template functor to compute the cosine of a scalar |
380 | * \sa class CwiseUnaryOp, ArrayBase::cos() |
381 | */ |
382 | template<typename Scalar> struct scalar_cos_op { |
383 | EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op) |
384 | EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return numext::cos(a); } |
385 | template <typename Packet> |
386 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcos(a); } |
387 | }; |
388 | template<typename Scalar> |
389 | struct functor_traits<scalar_cos_op<Scalar> > |
390 | { |
391 | enum { |
392 | Cost = 5 * NumTraits<Scalar>::MulCost, |
393 | PacketAccess = packet_traits<Scalar>::HasCos |
394 | }; |
395 | }; |
396 | |
397 | /** \internal |
398 | * \brief Template functor to compute the sine of a scalar |
399 | * \sa class CwiseUnaryOp, ArrayBase::sin() |
400 | */ |
401 | template<typename Scalar> struct scalar_sin_op { |
402 | EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op) |
403 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sin(a); } |
404 | template <typename Packet> |
405 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psin(a); } |
406 | }; |
407 | template<typename Scalar> |
408 | struct functor_traits<scalar_sin_op<Scalar> > |
409 | { |
410 | enum { |
411 | Cost = 5 * NumTraits<Scalar>::MulCost, |
412 | PacketAccess = packet_traits<Scalar>::HasSin |
413 | }; |
414 | }; |
415 | |
416 | |
417 | /** \internal |
418 | * \brief Template functor to compute the tan of a scalar |
419 | * \sa class CwiseUnaryOp, ArrayBase::tan() |
420 | */ |
421 | template<typename Scalar> struct scalar_tan_op { |
422 | EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op) |
423 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::tan(a); } |
424 | template <typename Packet> |
425 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::ptan(a); } |
426 | }; |
427 | template<typename Scalar> |
428 | struct functor_traits<scalar_tan_op<Scalar> > |
429 | { |
430 | enum { |
431 | Cost = 5 * NumTraits<Scalar>::MulCost, |
432 | PacketAccess = packet_traits<Scalar>::HasTan |
433 | }; |
434 | }; |
435 | |
436 | /** \internal |
437 | * \brief Template functor to compute the arc cosine of a scalar |
438 | * \sa class CwiseUnaryOp, ArrayBase::acos() |
439 | */ |
440 | template<typename Scalar> struct scalar_acos_op { |
441 | EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op) |
442 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::acos(a); } |
443 | template <typename Packet> |
444 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } |
445 | }; |
446 | template<typename Scalar> |
447 | struct functor_traits<scalar_acos_op<Scalar> > |
448 | { |
449 | enum { |
450 | Cost = 5 * NumTraits<Scalar>::MulCost, |
451 | PacketAccess = packet_traits<Scalar>::HasACos |
452 | }; |
453 | }; |
454 | |
455 | /** \internal |
456 | * \brief Template functor to compute the arc sine of a scalar |
457 | * \sa class CwiseUnaryOp, ArrayBase::asin() |
458 | */ |
459 | template<typename Scalar> struct scalar_asin_op { |
460 | EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op) |
461 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::asin(a); } |
462 | template <typename Packet> |
463 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pasin(a); } |
464 | }; |
465 | template<typename Scalar> |
466 | struct functor_traits<scalar_asin_op<Scalar> > |
467 | { |
468 | enum { |
469 | Cost = 5 * NumTraits<Scalar>::MulCost, |
470 | PacketAccess = packet_traits<Scalar>::HasASin |
471 | }; |
472 | }; |
473 | |
474 | |
475 | /** \internal |
476 | * \brief Template functor to compute the atan of a scalar |
477 | * \sa class CwiseUnaryOp, ArrayBase::atan() |
478 | */ |
479 | template<typename Scalar> struct scalar_atan_op { |
480 | EIGEN_EMPTY_STRUCT_CTOR(scalar_atan_op) |
481 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::atan(a); } |
482 | template <typename Packet> |
483 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::patan(a); } |
484 | }; |
485 | template<typename Scalar> |
486 | struct functor_traits<scalar_atan_op<Scalar> > |
487 | { |
488 | enum { |
489 | Cost = 5 * NumTraits<Scalar>::MulCost, |
490 | PacketAccess = packet_traits<Scalar>::HasATan |
491 | }; |
492 | }; |
493 | |
494 | /** \internal |
495 | * \brief Template functor to compute the tanh of a scalar |
496 | * \sa class CwiseUnaryOp, ArrayBase::tanh() |
497 | */ |
498 | template <typename Scalar> |
499 | struct scalar_tanh_op { |
500 | EIGEN_EMPTY_STRUCT_CTOR(scalar_tanh_op) |
501 | EIGEN_DEVICE_FUNC inline const Scalar operator()(const Scalar& a) const { return numext::tanh(a); } |
502 | template <typename Packet> |
503 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x) const { return ptanh(x); } |
504 | }; |
505 | |
506 | template <typename Scalar> |
507 | struct functor_traits<scalar_tanh_op<Scalar> > { |
508 | enum { |
509 | PacketAccess = packet_traits<Scalar>::HasTanh, |
510 | Cost = ( (EIGEN_FAST_MATH && is_same<Scalar,float>::value) |
511 | // The following numbers are based on the AVX implementation, |
512 | #ifdef EIGEN_VECTORIZE_FMA |
513 | // Haswell can issue 2 add/mul/madd per cycle. |
514 | // 9 pmadd, 2 pmul, 1 div, 2 other |
515 | ? (2 * NumTraits<Scalar>::AddCost + |
516 | 6 * NumTraits<Scalar>::MulCost + |
517 | scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value) |
518 | #else |
519 | ? (11 * NumTraits<Scalar>::AddCost + |
520 | 11 * NumTraits<Scalar>::MulCost + |
521 | scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value) |
522 | #endif |
523 | // This number assumes a naive implementation of tanh |
524 | : (6 * NumTraits<Scalar>::AddCost + |
525 | 3 * NumTraits<Scalar>::MulCost + |
526 | 2 * scalar_div_cost<Scalar,packet_traits<Scalar>::HasDiv>::value + |
527 | functor_traits<scalar_exp_op<Scalar> >::Cost)) |
528 | }; |
529 | }; |
530 | |
531 | /** \internal |
532 | * \brief Template functor to compute the sinh of a scalar |
533 | * \sa class CwiseUnaryOp, ArrayBase::sinh() |
534 | */ |
535 | template<typename Scalar> struct scalar_sinh_op { |
536 | EIGEN_EMPTY_STRUCT_CTOR(scalar_sinh_op) |
537 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::sinh(a); } |
538 | template <typename Packet> |
539 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psinh(a); } |
540 | }; |
541 | template<typename Scalar> |
542 | struct functor_traits<scalar_sinh_op<Scalar> > |
543 | { |
544 | enum { |
545 | Cost = 5 * NumTraits<Scalar>::MulCost, |
546 | PacketAccess = packet_traits<Scalar>::HasSinh |
547 | }; |
548 | }; |
549 | |
550 | /** \internal |
551 | * \brief Template functor to compute the cosh of a scalar |
552 | * \sa class CwiseUnaryOp, ArrayBase::cosh() |
553 | */ |
554 | template<typename Scalar> struct scalar_cosh_op { |
555 | EIGEN_EMPTY_STRUCT_CTOR(scalar_cosh_op) |
556 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { return numext::cosh(a); } |
557 | template <typename Packet> |
558 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pcosh(a); } |
559 | }; |
560 | template<typename Scalar> |
561 | struct functor_traits<scalar_cosh_op<Scalar> > |
562 | { |
563 | enum { |
564 | Cost = 5 * NumTraits<Scalar>::MulCost, |
565 | PacketAccess = packet_traits<Scalar>::HasCosh |
566 | }; |
567 | }; |
568 | |
569 | /** \internal |
570 | * \brief Template functor to compute the inverse of a scalar |
571 | * \sa class CwiseUnaryOp, Cwise::inverse() |
572 | */ |
573 | template<typename Scalar> |
574 | struct scalar_inverse_op { |
575 | EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op) |
576 | EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; } |
577 | template<typename Packet> |
578 | EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const |
579 | { return internal::pdiv(pset1<Packet>(Scalar(1)),a); } |
580 | }; |
581 | template<typename Scalar> |
582 | struct functor_traits<scalar_inverse_op<Scalar> > |
583 | { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; }; |
584 | |
585 | /** \internal |
586 | * \brief Template functor to compute the square of a scalar |
587 | * \sa class CwiseUnaryOp, Cwise::square() |
588 | */ |
589 | template<typename Scalar> |
590 | struct scalar_square_op { |
591 | EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op) |
592 | EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a; } |
593 | template<typename Packet> |
594 | EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const |
595 | { return internal::pmul(a,a); } |
596 | }; |
597 | template<typename Scalar> |
598 | struct functor_traits<scalar_square_op<Scalar> > |
599 | { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; |
600 | |
601 | /** \internal |
602 | * \brief Template functor to compute the cube of a scalar |
603 | * \sa class CwiseUnaryOp, Cwise::cube() |
604 | */ |
605 | template<typename Scalar> |
606 | struct scalar_cube_op { |
607 | EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op) |
608 | EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a*a*a; } |
609 | template<typename Packet> |
610 | EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const |
611 | { return internal::pmul(a,pmul(a,a)); } |
612 | }; |
613 | template<typename Scalar> |
614 | struct functor_traits<scalar_cube_op<Scalar> > |
615 | { enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; }; |
616 | |
617 | /** \internal |
618 | * \brief Template functor to compute the rounded value of a scalar |
619 | * \sa class CwiseUnaryOp, ArrayBase::round() |
620 | */ |
621 | template<typename Scalar> struct scalar_round_op { |
622 | EIGEN_EMPTY_STRUCT_CTOR(scalar_round_op) |
623 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::round(a); } |
624 | template <typename Packet> |
625 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pround(a); } |
626 | }; |
627 | template<typename Scalar> |
628 | struct functor_traits<scalar_round_op<Scalar> > |
629 | { |
630 | enum { |
631 | Cost = NumTraits<Scalar>::MulCost, |
632 | PacketAccess = packet_traits<Scalar>::HasRound |
633 | }; |
634 | }; |
635 | |
636 | /** \internal |
637 | * \brief Template functor to compute the floor of a scalar |
638 | * \sa class CwiseUnaryOp, ArrayBase::floor() |
639 | */ |
640 | template<typename Scalar> struct scalar_floor_op { |
641 | EIGEN_EMPTY_STRUCT_CTOR(scalar_floor_op) |
642 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::floor(a); } |
643 | template <typename Packet> |
644 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pfloor(a); } |
645 | }; |
646 | template<typename Scalar> |
647 | struct functor_traits<scalar_floor_op<Scalar> > |
648 | { |
649 | enum { |
650 | Cost = NumTraits<Scalar>::MulCost, |
651 | PacketAccess = packet_traits<Scalar>::HasFloor |
652 | }; |
653 | }; |
654 | |
655 | /** \internal |
656 | * \brief Template functor to compute the ceil of a scalar |
657 | * \sa class CwiseUnaryOp, ArrayBase::ceil() |
658 | */ |
659 | template<typename Scalar> struct scalar_ceil_op { |
660 | EIGEN_EMPTY_STRUCT_CTOR(scalar_ceil_op) |
661 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return numext::ceil(a); } |
662 | template <typename Packet> |
663 | EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pceil(a); } |
664 | }; |
665 | template<typename Scalar> |
666 | struct functor_traits<scalar_ceil_op<Scalar> > |
667 | { |
668 | enum { |
669 | Cost = NumTraits<Scalar>::MulCost, |
670 | PacketAccess = packet_traits<Scalar>::HasCeil |
671 | }; |
672 | }; |
673 | |
674 | /** \internal |
675 | * \brief Template functor to compute whether a scalar is NaN |
676 | * \sa class CwiseUnaryOp, ArrayBase::isnan() |
677 | */ |
678 | template<typename Scalar> struct scalar_isnan_op { |
679 | EIGEN_EMPTY_STRUCT_CTOR(scalar_isnan_op) |
680 | typedef bool result_type; |
681 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isnan)(a); } |
682 | }; |
683 | template<typename Scalar> |
684 | struct functor_traits<scalar_isnan_op<Scalar> > |
685 | { |
686 | enum { |
687 | Cost = NumTraits<Scalar>::MulCost, |
688 | PacketAccess = false |
689 | }; |
690 | }; |
691 | |
692 | /** \internal |
693 | * \brief Template functor to check whether a scalar is +/-inf |
694 | * \sa class CwiseUnaryOp, ArrayBase::isinf() |
695 | */ |
696 | template<typename Scalar> struct scalar_isinf_op { |
697 | EIGEN_EMPTY_STRUCT_CTOR(scalar_isinf_op) |
698 | typedef bool result_type; |
699 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isinf)(a); } |
700 | }; |
701 | template<typename Scalar> |
702 | struct functor_traits<scalar_isinf_op<Scalar> > |
703 | { |
704 | enum { |
705 | Cost = NumTraits<Scalar>::MulCost, |
706 | PacketAccess = false |
707 | }; |
708 | }; |
709 | |
710 | /** \internal |
711 | * \brief Template functor to check whether a scalar has a finite value |
712 | * \sa class CwiseUnaryOp, ArrayBase::isfinite() |
713 | */ |
714 | template<typename Scalar> struct scalar_isfinite_op { |
715 | EIGEN_EMPTY_STRUCT_CTOR(scalar_isfinite_op) |
716 | typedef bool result_type; |
717 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return (numext::isfinite)(a); } |
718 | }; |
719 | template<typename Scalar> |
720 | struct functor_traits<scalar_isfinite_op<Scalar> > |
721 | { |
722 | enum { |
723 | Cost = NumTraits<Scalar>::MulCost, |
724 | PacketAccess = false |
725 | }; |
726 | }; |
727 | |
728 | /** \internal |
729 | * \brief Template functor to compute the logical not of a boolean |
730 | * |
731 | * \sa class CwiseUnaryOp, ArrayBase::operator! |
732 | */ |
733 | template<typename Scalar> struct scalar_boolean_not_op { |
734 | EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_not_op) |
735 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a) const { return !a; } |
736 | }; |
737 | template<typename Scalar> |
738 | struct functor_traits<scalar_boolean_not_op<Scalar> > { |
739 | enum { |
740 | Cost = NumTraits<bool>::AddCost, |
741 | PacketAccess = false |
742 | }; |
743 | }; |
744 | |
745 | /** \internal |
746 | * \brief Template functor to compute the signum of a scalar |
747 | * \sa class CwiseUnaryOp, Cwise::sign() |
748 | */ |
749 | template<typename Scalar,bool iscpx=(NumTraits<Scalar>::IsComplex!=0) > struct scalar_sign_op; |
750 | template<typename Scalar> |
751 | struct scalar_sign_op<Scalar,false> { |
752 | EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op) |
753 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const |
754 | { |
755 | return Scalar( (a>Scalar(0)) - (a<Scalar(0)) ); |
756 | } |
757 | //TODO |
758 | //template <typename Packet> |
759 | //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); } |
760 | }; |
761 | template<typename Scalar> |
762 | struct scalar_sign_op<Scalar,true> { |
763 | EIGEN_EMPTY_STRUCT_CTOR(scalar_sign_op) |
764 | EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const |
765 | { |
766 | typedef typename NumTraits<Scalar>::Real real_type; |
767 | real_type aa = numext::abs(a); |
768 | if (aa==real_type(0)) |
769 | return Scalar(0); |
770 | aa = real_type(1)/aa; |
771 | return Scalar(real(a)*aa, imag(a)*aa ); |
772 | } |
773 | //TODO |
774 | //template <typename Packet> |
775 | //EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::psign(a); } |
776 | }; |
777 | template<typename Scalar> |
778 | struct functor_traits<scalar_sign_op<Scalar> > |
779 | { enum { |
780 | Cost = |
781 | NumTraits<Scalar>::IsComplex |
782 | ? ( 8*NumTraits<Scalar>::MulCost ) // roughly |
783 | : ( 3*NumTraits<Scalar>::AddCost), |
784 | PacketAccess = packet_traits<Scalar>::HasSign |
785 | }; |
786 | }; |
787 | |
788 | } // end namespace internal |
789 | |
790 | } // end namespace Eigen |
791 | |
792 | #endif // EIGEN_FUNCTORS_H |
793 | |