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