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
13namespace Eigen {
14
15namespace internal {
16
17/** \internal
18 * \brief Template functor to compute the opposite of a scalar
19 *
20 * \sa class CwiseUnaryOp, MatrixBase::operator-
21 */
22template<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};
29template<typename Scalar>
30struct 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 */
41template<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};
49template<typename Scalar>
50struct 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 */
63template<typename Scalar> struct scalar_score_coeff_op : scalar_abs_op<Scalar>
64{
65 typedef void Score_is_abs;
66};
67template<typename Scalar>
68struct 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. */
71template<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};
78template<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 */
91template<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};
100template<typename Scalar>
101struct 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 */
109template<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};
116template<typename Scalar>
117struct 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 */
130template<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};
138template<typename Scalar>
139struct 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 */
151template<typename Scalar, typename NewType>
152struct 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};
157template<typename Scalar, typename NewType>
158struct 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 */
166template<typename Scalar>
167struct 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};
173template<typename Scalar>
174struct 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 */
182template<typename Scalar>
183struct 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};
189template<typename Scalar>
190struct 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 */
198template<typename Scalar>
199struct 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};
205template<typename Scalar>
206struct 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 */
214template<typename Scalar>
215struct 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};
221template<typename Scalar>
222struct 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 */
231template<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};
237template <typename Scalar>
238struct 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 */
271template<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};
277template <typename Scalar>
278struct 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 */
302template<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};
308template <typename Scalar>
309struct 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 */
322template<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};
328template<typename Scalar>
329struct 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 */
336template<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};
342template <typename Scalar>
343struct 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 */
363template<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
370template<typename Scalar>
371struct 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 */
382template<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};
388template<typename Scalar>
389struct 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 */
401template<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};
407template<typename Scalar>
408struct 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 */
421template<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};
427template<typename Scalar>
428struct 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 */
440template<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};
446template<typename Scalar>
447struct 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 */
459template<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};
465template<typename Scalar>
466struct 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 */
479template<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};
485template<typename Scalar>
486struct 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 */
498template <typename Scalar>
499struct 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
506template <typename Scalar>
507struct 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 */
535template<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};
541template<typename Scalar>
542struct 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 */
554template<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};
560template<typename Scalar>
561struct 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 */
573template<typename Scalar>
574struct 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};
581template<typename Scalar>
582struct 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 */
589template<typename Scalar>
590struct 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};
597template<typename Scalar>
598struct 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 */
605template<typename Scalar>
606struct 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};
613template<typename Scalar>
614struct 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 */
621template<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};
627template<typename Scalar>
628struct 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 */
640template<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};
646template<typename Scalar>
647struct 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 */
659template<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};
665template<typename Scalar>
666struct 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 */
678template<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};
683template<typename Scalar>
684struct 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 */
696template<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};
701template<typename Scalar>
702struct 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 */
714template<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};
719template<typename Scalar>
720struct 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 */
733template<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};
737template<typename Scalar>
738struct 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 */
749template<typename Scalar,bool iscpx=(NumTraits<Scalar>::IsComplex!=0) > struct scalar_sign_op;
750template<typename Scalar>
751struct 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};
761template<typename Scalar>
762struct 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};
777template<typename Scalar>
778struct 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