Home | History | Annotate | Download | only in functors
      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 (at) 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 {
     24   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
     31   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