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-2010 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_BINARY_FUNCTORS_H
     11 #define EIGEN_BINARY_FUNCTORS_H
     12 
     13 namespace Eigen {
     14 
     15 namespace internal {
     16 
     17 //---------- associative binary functors ----------
     18 
     19 template<typename Arg1, typename Arg2>
     20 struct binary_op_base
     21 {
     22   typedef Arg1 first_argument_type;
     23   typedef Arg2 second_argument_type;
     24 };
     25 
     26 /** \internal
     27   * \brief Template functor to compute the sum of two scalars
     28   *
     29   * \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, DenseBase::sum()
     30   */
     31 template<typename LhsScalar,typename RhsScalar>
     32 struct scalar_sum_op : binary_op_base<LhsScalar,RhsScalar>
     33 {
     34   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_sum_op>::ReturnType result_type;
     35 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
     36   EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
     37 #else
     38   scalar_sum_op() {
     39     EIGEN_SCALAR_BINARY_OP_PLUGIN
     40   }
     41 #endif
     42   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a + b; }
     43   template<typename Packet>
     44   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
     45   { return internal::padd(a,b); }
     46   template<typename Packet>
     47   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
     48   { return internal::predux(a); }
     49 };
     50 template<typename LhsScalar,typename RhsScalar>
     51 struct functor_traits<scalar_sum_op<LhsScalar,RhsScalar> > {
     52   enum {
     53     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2, // rough estimate!
     54     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasAdd && packet_traits<RhsScalar>::HasAdd
     55     // TODO vectorize mixed sum
     56   };
     57 };
     58 
     59 /** \internal
     60   * \brief Template specialization to deprecate the summation of boolean expressions.
     61   * This is required to solve Bug 426.
     62   * \sa DenseBase::count(), DenseBase::any(), ArrayBase::cast(), MatrixBase::cast()
     63   */
     64 template<> struct scalar_sum_op<bool,bool> : scalar_sum_op<int,int> {
     65   EIGEN_DEPRECATED
     66   scalar_sum_op() {}
     67 };
     68 
     69 
     70 /** \internal
     71   * \brief Template functor to compute the product of two scalars
     72   *
     73   * \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
     74   */
     75 template<typename LhsScalar,typename RhsScalar>
     76 struct scalar_product_op  : binary_op_base<LhsScalar,RhsScalar>
     77 {
     78   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_product_op>::ReturnType result_type;
     79 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
     80   EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
     81 #else
     82   scalar_product_op() {
     83     EIGEN_SCALAR_BINARY_OP_PLUGIN
     84   }
     85 #endif
     86   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
     87   template<typename Packet>
     88   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
     89   { return internal::pmul(a,b); }
     90   template<typename Packet>
     91   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
     92   { return internal::predux_mul(a); }
     93 };
     94 template<typename LhsScalar,typename RhsScalar>
     95 struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
     96   enum {
     97     Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
     98     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
     99     // TODO vectorize mixed product
    100   };
    101 };
    102 
    103 /** \internal
    104   * \brief Template functor to compute the conjugate product of two scalars
    105   *
    106   * This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y)
    107   */
    108 template<typename LhsScalar,typename RhsScalar>
    109 struct scalar_conj_product_op  : binary_op_base<LhsScalar,RhsScalar>
    110 {
    111 
    112   enum {
    113     Conj = NumTraits<LhsScalar>::IsComplex
    114   };
    115 
    116   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_conj_product_op>::ReturnType result_type;
    117 
    118   EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
    119   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
    120   { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
    121 
    122   template<typename Packet>
    123   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
    124   { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
    125 };
    126 template<typename LhsScalar,typename RhsScalar>
    127 struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
    128   enum {
    129     Cost = NumTraits<LhsScalar>::MulCost,
    130     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
    131   };
    132 };
    133 
    134 /** \internal
    135   * \brief Template functor to compute the min of two scalars
    136   *
    137   * \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
    138   */
    139 template<typename LhsScalar,typename RhsScalar>
    140 struct scalar_min_op : binary_op_base<LhsScalar,RhsScalar>
    141 {
    142   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_min_op>::ReturnType result_type;
    143   EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
    144   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return numext::mini(a, b); }
    145   template<typename Packet>
    146   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
    147   { return internal::pmin(a,b); }
    148   template<typename Packet>
    149   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
    150   { return internal::predux_min(a); }
    151 };
    152 template<typename LhsScalar,typename RhsScalar>
    153 struct functor_traits<scalar_min_op<LhsScalar,RhsScalar> > {
    154   enum {
    155     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
    156     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMin
    157   };
    158 };
    159 
    160 /** \internal
    161   * \brief Template functor to compute the max of two scalars
    162   *
    163   * \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
    164   */
    165 template<typename LhsScalar,typename RhsScalar>
    166 struct scalar_max_op  : binary_op_base<LhsScalar,RhsScalar>
    167 {
    168   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_max_op>::ReturnType result_type;
    169   EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
    170   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return numext::maxi(a, b); }
    171   template<typename Packet>
    172   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
    173   { return internal::pmax(a,b); }
    174   template<typename Packet>
    175   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
    176   { return internal::predux_max(a); }
    177 };
    178 template<typename LhsScalar,typename RhsScalar>
    179 struct functor_traits<scalar_max_op<LhsScalar,RhsScalar> > {
    180   enum {
    181     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
    182     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMax
    183   };
    184 };
    185 
    186 /** \internal
    187   * \brief Template functors for comparison of two scalars
    188   * \todo Implement packet-comparisons
    189   */
    190 template<typename LhsScalar, typename RhsScalar, ComparisonName cmp> struct scalar_cmp_op;
    191 
    192 template<typename LhsScalar, typename RhsScalar, ComparisonName cmp>
    193 struct functor_traits<scalar_cmp_op<LhsScalar,RhsScalar, cmp> > {
    194   enum {
    195     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
    196     PacketAccess = false
    197   };
    198 };
    199 
    200 template<ComparisonName Cmp, typename LhsScalar, typename RhsScalar>
    201 struct result_of<scalar_cmp_op<LhsScalar, RhsScalar, Cmp>(LhsScalar,RhsScalar)> {
    202   typedef bool type;
    203 };
    204 
    205 
    206 template<typename LhsScalar, typename RhsScalar>
    207 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_EQ> : binary_op_base<LhsScalar,RhsScalar>
    208 {
    209   typedef bool result_type;
    210   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
    211   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a==b;}
    212 };
    213 template<typename LhsScalar, typename RhsScalar>
    214 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LT> : binary_op_base<LhsScalar,RhsScalar>
    215 {
    216   typedef bool result_type;
    217   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
    218   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<b;}
    219 };
    220 template<typename LhsScalar, typename RhsScalar>
    221 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LE> : binary_op_base<LhsScalar,RhsScalar>
    222 {
    223   typedef bool result_type;
    224   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
    225   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<=b;}
    226 };
    227 template<typename LhsScalar, typename RhsScalar>
    228 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GT> : binary_op_base<LhsScalar,RhsScalar>
    229 {
    230   typedef bool result_type;
    231   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
    232   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>b;}
    233 };
    234 template<typename LhsScalar, typename RhsScalar>
    235 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GE> : binary_op_base<LhsScalar,RhsScalar>
    236 {
    237   typedef bool result_type;
    238   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
    239   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>=b;}
    240 };
    241 template<typename LhsScalar, typename RhsScalar>
    242 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_UNORD> : binary_op_base<LhsScalar,RhsScalar>
    243 {
    244   typedef bool result_type;
    245   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
    246   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return !(a<=b || b<=a);}
    247 };
    248 template<typename LhsScalar, typename RhsScalar>
    249 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_NEQ> : binary_op_base<LhsScalar,RhsScalar>
    250 {
    251   typedef bool result_type;
    252   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
    253   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a!=b;}
    254 };
    255 
    256 
    257 /** \internal
    258   * \brief Template functor to compute the hypot of two scalars
    259   *
    260   * \sa MatrixBase::stableNorm(), class Redux
    261   */
    262 template<typename Scalar>
    263 struct scalar_hypot_op<Scalar,Scalar> : binary_op_base<Scalar,Scalar>
    264 {
    265   EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
    266 //   typedef typename NumTraits<Scalar>::Real result_type;
    267   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
    268   {
    269     EIGEN_USING_STD_MATH(sqrt)
    270     Scalar p, qp;
    271     if(_x>_y)
    272     {
    273       p = _x;
    274       qp = _y / p;
    275     }
    276     else
    277     {
    278       p = _y;
    279       qp = _x / p;
    280     }
    281     return p * sqrt(Scalar(1) + qp*qp);
    282   }
    283 };
    284 template<typename Scalar>
    285 struct functor_traits<scalar_hypot_op<Scalar,Scalar> > {
    286   enum
    287   {
    288     Cost = 3 * NumTraits<Scalar>::AddCost +
    289            2 * NumTraits<Scalar>::MulCost +
    290            2 * scalar_div_cost<Scalar,false>::value,
    291     PacketAccess = false
    292   };
    293 };
    294 
    295 /** \internal
    296   * \brief Template functor to compute the pow of two scalars
    297   */
    298 template<typename Scalar, typename Exponent>
    299 struct scalar_pow_op  : binary_op_base<Scalar,Exponent>
    300 {
    301   typedef typename ScalarBinaryOpTraits<Scalar,Exponent,scalar_pow_op>::ReturnType result_type;
    302 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
    303   EIGEN_EMPTY_STRUCT_CTOR(scalar_pow_op)
    304 #else
    305   scalar_pow_op() {
    306     typedef Scalar LhsScalar;
    307     typedef Exponent RhsScalar;
    308     EIGEN_SCALAR_BINARY_OP_PLUGIN
    309   }
    310 #endif
    311   EIGEN_DEVICE_FUNC
    312   inline result_type operator() (const Scalar& a, const Exponent& b) const { return numext::pow(a, b); }
    313 };
    314 template<typename Scalar, typename Exponent>
    315 struct functor_traits<scalar_pow_op<Scalar,Exponent> > {
    316   enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
    317 };
    318 
    319 
    320 
    321 //---------- non associative binary functors ----------
    322 
    323 /** \internal
    324   * \brief Template functor to compute the difference of two scalars
    325   *
    326   * \sa class CwiseBinaryOp, MatrixBase::operator-
    327   */
    328 template<typename LhsScalar,typename RhsScalar>
    329 struct scalar_difference_op : binary_op_base<LhsScalar,RhsScalar>
    330 {
    331   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_difference_op>::ReturnType result_type;
    332 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
    333   EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
    334 #else
    335   scalar_difference_op() {
    336     EIGEN_SCALAR_BINARY_OP_PLUGIN
    337   }
    338 #endif
    339   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a - b; }
    340   template<typename Packet>
    341   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
    342   { return internal::psub(a,b); }
    343 };
    344 template<typename LhsScalar,typename RhsScalar>
    345 struct functor_traits<scalar_difference_op<LhsScalar,RhsScalar> > {
    346   enum {
    347     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
    348     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasSub && packet_traits<RhsScalar>::HasSub
    349   };
    350 };
    351 
    352 /** \internal
    353   * \brief Template functor to compute the quotient of two scalars
    354   *
    355   * \sa class CwiseBinaryOp, Cwise::operator/()
    356   */
    357 template<typename LhsScalar,typename RhsScalar>
    358 struct scalar_quotient_op  : binary_op_base<LhsScalar,RhsScalar>
    359 {
    360   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_quotient_op>::ReturnType result_type;
    361 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
    362   EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
    363 #else
    364   scalar_quotient_op() {
    365     EIGEN_SCALAR_BINARY_OP_PLUGIN
    366   }
    367 #endif
    368   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
    369   template<typename Packet>
    370   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
    371   { return internal::pdiv(a,b); }
    372 };
    373 template<typename LhsScalar,typename RhsScalar>
    374 struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
    375   typedef typename scalar_quotient_op<LhsScalar,RhsScalar>::result_type result_type;
    376   enum {
    377     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv,
    378     Cost = scalar_div_cost<result_type,PacketAccess>::value
    379   };
    380 };
    381 
    382 
    383 
    384 /** \internal
    385   * \brief Template functor to compute the and of two booleans
    386   *
    387   * \sa class CwiseBinaryOp, ArrayBase::operator&&
    388   */
    389 struct scalar_boolean_and_op {
    390   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
    391   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
    392 };
    393 template<> struct functor_traits<scalar_boolean_and_op> {
    394   enum {
    395     Cost = NumTraits<bool>::AddCost,
    396     PacketAccess = false
    397   };
    398 };
    399 
    400 /** \internal
    401   * \brief Template functor to compute the or of two booleans
    402   *
    403   * \sa class CwiseBinaryOp, ArrayBase::operator||
    404   */
    405 struct scalar_boolean_or_op {
    406   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
    407   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
    408 };
    409 template<> struct functor_traits<scalar_boolean_or_op> {
    410   enum {
    411     Cost = NumTraits<bool>::AddCost,
    412     PacketAccess = false
    413   };
    414 };
    415 
    416 /** \internal
    417  * \brief Template functor to compute the xor of two booleans
    418  *
    419  * \sa class CwiseBinaryOp, ArrayBase::operator^
    420  */
    421 struct scalar_boolean_xor_op {
    422   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_xor_op)
    423   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a ^ b; }
    424 };
    425 template<> struct functor_traits<scalar_boolean_xor_op> {
    426   enum {
    427     Cost = NumTraits<bool>::AddCost,
    428     PacketAccess = false
    429   };
    430 };
    431 
    432 
    433 
    434 //---------- binary functors bound to a constant, thus appearing as a unary functor ----------
    435 
    436 // The following two classes permits to turn any binary functor into a unary one with one argument bound to a constant value.
    437 // They are analogues to std::binder1st/binder2nd but with the following differences:
    438 //  - they are compatible with packetOp
    439 //  - they are portable across C++ versions (the std::binder* are deprecated in C++11)
    440 template<typename BinaryOp> struct bind1st_op : BinaryOp {
    441 
    442   typedef typename BinaryOp::first_argument_type  first_argument_type;
    443   typedef typename BinaryOp::second_argument_type second_argument_type;
    444   typedef typename BinaryOp::result_type          result_type;
    445 
    446   bind1st_op(const first_argument_type &val) : m_value(val) {}
    447 
    448   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const second_argument_type& b) const { return BinaryOp::operator()(m_value,b); }
    449 
    450   template<typename Packet>
    451   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& b) const
    452   { return BinaryOp::packetOp(internal::pset1<Packet>(m_value), b); }
    453 
    454   first_argument_type m_value;
    455 };
    456 template<typename BinaryOp> struct functor_traits<bind1st_op<BinaryOp> > : functor_traits<BinaryOp> {};
    457 
    458 
    459 template<typename BinaryOp> struct bind2nd_op : BinaryOp {
    460 
    461   typedef typename BinaryOp::first_argument_type  first_argument_type;
    462   typedef typename BinaryOp::second_argument_type second_argument_type;
    463   typedef typename BinaryOp::result_type          result_type;
    464 
    465   bind2nd_op(const second_argument_type &val) : m_value(val) {}
    466 
    467   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const first_argument_type& a) const { return BinaryOp::operator()(a,m_value); }
    468 
    469   template<typename Packet>
    470   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
    471   { return BinaryOp::packetOp(a,internal::pset1<Packet>(m_value)); }
    472 
    473   second_argument_type m_value;
    474 };
    475 template<typename BinaryOp> struct functor_traits<bind2nd_op<BinaryOp> > : functor_traits<BinaryOp> {};
    476 
    477 
    478 } // end namespace internal
    479 
    480 } // end namespace Eigen
    481 
    482 #endif // EIGEN_BINARY_FUNCTORS_H
    483