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