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