Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:13:27

0001 // This file is part of Eigen, a lightweight C++ template library
0002 // for linear algebra.
0003 //
0004 // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
0005 //
0006 // This Source Code Form is subject to the terms of the Mozilla
0007 // Public License v. 2.0. If a copy of the MPL was not distributed
0008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
0009 
0010 #ifndef EIGEN_BINARY_FUNCTORS_H
0011 #define EIGEN_BINARY_FUNCTORS_H
0012 
0013 namespace Eigen {
0014 
0015 namespace internal {
0016 
0017 //---------- associative binary functors ----------
0018 
0019 template<typename Arg1, typename Arg2>
0020 struct binary_op_base
0021 {
0022   typedef Arg1 first_argument_type;
0023   typedef Arg2 second_argument_type;
0024 };
0025 
0026 /** \internal
0027   * \brief Template functor to compute the sum of two scalars
0028   *
0029   * \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, DenseBase::sum()
0030   */
0031 template<typename LhsScalar,typename RhsScalar>
0032 struct scalar_sum_op : binary_op_base<LhsScalar,RhsScalar>
0033 {
0034   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_sum_op>::ReturnType result_type;
0035 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
0036   EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
0037 #else
0038   scalar_sum_op() {
0039     EIGEN_SCALAR_BINARY_OP_PLUGIN
0040   }
0041 #endif
0042   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a + b; }
0043   template<typename Packet>
0044   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
0045   { return internal::padd(a,b); }
0046   template<typename Packet>
0047   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
0048   { return internal::predux(a); }
0049 };
0050 template<typename LhsScalar,typename RhsScalar>
0051 struct functor_traits<scalar_sum_op<LhsScalar,RhsScalar> > {
0052   enum {
0053     Cost = (int(NumTraits<LhsScalar>::AddCost) + int(NumTraits<RhsScalar>::AddCost)) / 2, // rough estimate!
0054     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasAdd && packet_traits<RhsScalar>::HasAdd
0055     // TODO vectorize mixed sum
0056   };
0057 };
0058 
0059 
0060 template<>
0061 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool scalar_sum_op<bool,bool>::operator() (const bool& a, const bool& b) const { return a || b; }
0062 
0063 
0064 /** \internal
0065   * \brief Template functor to compute the product of two scalars
0066   *
0067   * \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
0068   */
0069 template<typename LhsScalar,typename RhsScalar>
0070 struct scalar_product_op  : binary_op_base<LhsScalar,RhsScalar>
0071 {
0072   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_product_op>::ReturnType result_type;
0073 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
0074   EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
0075 #else
0076   scalar_product_op() {
0077     EIGEN_SCALAR_BINARY_OP_PLUGIN
0078   }
0079 #endif
0080   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
0081   template<typename Packet>
0082   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
0083   { return internal::pmul(a,b); }
0084   template<typename Packet>
0085   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
0086   { return internal::predux_mul(a); }
0087 };
0088 template<typename LhsScalar,typename RhsScalar>
0089 struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
0090   enum {
0091     Cost = (int(NumTraits<LhsScalar>::MulCost) + int(NumTraits<RhsScalar>::MulCost))/2, // rough estimate!
0092     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
0093     // TODO vectorize mixed product
0094   };
0095 };
0096 
0097 template<>
0098 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool scalar_product_op<bool,bool>::operator() (const bool& a, const bool& b) const { return a && b; }
0099 
0100 
0101 /** \internal
0102   * \brief Template functor to compute the conjugate product of two scalars
0103   *
0104   * This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y)
0105   */
0106 template<typename LhsScalar,typename RhsScalar>
0107 struct scalar_conj_product_op  : binary_op_base<LhsScalar,RhsScalar>
0108 {
0109 
0110   enum {
0111     Conj = NumTraits<LhsScalar>::IsComplex
0112   };
0113   
0114   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_conj_product_op>::ReturnType result_type;
0115   
0116   EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
0117   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const
0118   { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
0119   
0120   template<typename Packet>
0121   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
0122   { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
0123 };
0124 template<typename LhsScalar,typename RhsScalar>
0125 struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
0126   enum {
0127     Cost = NumTraits<LhsScalar>::MulCost,
0128     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
0129   };
0130 };
0131 
0132 /** \internal
0133   * \brief Template functor to compute the min of two scalars
0134   *
0135   * \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
0136   */
0137 template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
0138 struct scalar_min_op : binary_op_base<LhsScalar,RhsScalar>
0139 {
0140   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_min_op>::ReturnType result_type;
0141   EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
0142   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const {
0143     return internal::pmin<NaNPropagation>(a, b);
0144   }
0145   template<typename Packet>
0146   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
0147   {
0148     return internal::pmin<NaNPropagation>(a,b);
0149   }
0150   template<typename Packet>
0151   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
0152   {
0153     return internal::predux_min<NaNPropagation>(a);
0154   }
0155 };
0156 
0157 template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
0158 struct functor_traits<scalar_min_op<LhsScalar,RhsScalar, NaNPropagation> > {
0159   enum {
0160     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
0161     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMin
0162   };
0163 };
0164 
0165 /** \internal
0166   * \brief Template functor to compute the max of two scalars
0167   *
0168   * \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
0169   */
0170 template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
0171 struct scalar_max_op : binary_op_base<LhsScalar,RhsScalar>
0172 {
0173   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_max_op>::ReturnType result_type;
0174   EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
0175   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const {
0176     return internal::pmax<NaNPropagation>(a,b);
0177   }
0178   template<typename Packet>
0179   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
0180   {
0181     return internal::pmax<NaNPropagation>(a,b);
0182   }
0183   template<typename Packet>
0184   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
0185   {
0186     return internal::predux_max<NaNPropagation>(a);
0187   }
0188 };
0189 
0190 template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
0191 struct functor_traits<scalar_max_op<LhsScalar,RhsScalar, NaNPropagation> > {
0192   enum {
0193     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
0194     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMax
0195   };
0196 };
0197 
0198 /** \internal
0199   * \brief Template functors for comparison of two scalars
0200   * \todo Implement packet-comparisons
0201   */
0202 template<typename LhsScalar, typename RhsScalar, ComparisonName cmp> struct scalar_cmp_op;
0203 
0204 template<typename LhsScalar, typename RhsScalar, ComparisonName cmp>
0205 struct functor_traits<scalar_cmp_op<LhsScalar,RhsScalar, cmp> > {
0206   enum {
0207     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
0208     PacketAccess = false
0209   };
0210 };
0211 
0212 template<ComparisonName Cmp, typename LhsScalar, typename RhsScalar>
0213 struct result_of<scalar_cmp_op<LhsScalar, RhsScalar, Cmp>(LhsScalar,RhsScalar)> {
0214   typedef bool type;
0215 };
0216 
0217 
0218 template<typename LhsScalar, typename RhsScalar>
0219 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_EQ> : binary_op_base<LhsScalar,RhsScalar>
0220 {
0221   typedef bool result_type;
0222   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
0223   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a==b;}
0224 };
0225 template<typename LhsScalar, typename RhsScalar>
0226 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LT> : binary_op_base<LhsScalar,RhsScalar>
0227 {
0228   typedef bool result_type;
0229   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
0230   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<b;}
0231 };
0232 template<typename LhsScalar, typename RhsScalar>
0233 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LE> : binary_op_base<LhsScalar,RhsScalar>
0234 {
0235   typedef bool result_type;
0236   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
0237   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<=b;}
0238 };
0239 template<typename LhsScalar, typename RhsScalar>
0240 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GT> : binary_op_base<LhsScalar,RhsScalar>
0241 {
0242   typedef bool result_type;
0243   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
0244   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>b;}
0245 };
0246 template<typename LhsScalar, typename RhsScalar>
0247 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GE> : binary_op_base<LhsScalar,RhsScalar>
0248 {
0249   typedef bool result_type;
0250   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
0251   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>=b;}
0252 };
0253 template<typename LhsScalar, typename RhsScalar>
0254 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_UNORD> : binary_op_base<LhsScalar,RhsScalar>
0255 {
0256   typedef bool result_type;
0257   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
0258   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return !(a<=b || b<=a);}
0259 };
0260 template<typename LhsScalar, typename RhsScalar>
0261 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_NEQ> : binary_op_base<LhsScalar,RhsScalar>
0262 {
0263   typedef bool result_type;
0264   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
0265   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a!=b;}
0266 };
0267 
0268 /** \internal
0269   * \brief Template functor to compute the hypot of two \b positive \b and \b real scalars
0270   *
0271   * \sa MatrixBase::stableNorm(), class Redux
0272   */
0273 template<typename Scalar>
0274 struct scalar_hypot_op<Scalar,Scalar> : binary_op_base<Scalar,Scalar>
0275 {
0276   EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
0277 
0278   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar &x, const Scalar &y) const
0279   {
0280     // This functor is used by hypotNorm only for which it is faster to first apply abs
0281     // on all coefficients prior to reduction through hypot.
0282     // This way we avoid calling abs on positive and real entries, and this also permits
0283     // to seamlessly handle complexes. Otherwise we would have to handle both real and complexes
0284     // through the same functor...
0285     return internal::positive_real_hypot(x,y);
0286   }
0287 };
0288 template<typename Scalar>
0289 struct functor_traits<scalar_hypot_op<Scalar,Scalar> > {
0290   enum
0291   {
0292     Cost = 3 * NumTraits<Scalar>::AddCost +
0293            2 * NumTraits<Scalar>::MulCost +
0294            2 * scalar_div_cost<Scalar,false>::value,
0295     PacketAccess = false
0296   };
0297 };
0298 
0299 /** \internal
0300   * \brief Template functor to compute the pow of two scalars
0301   * See the specification of pow in https://en.cppreference.com/w/cpp/numeric/math/pow
0302   */
0303 template<typename Scalar, typename Exponent>
0304 struct scalar_pow_op  : binary_op_base<Scalar,Exponent>
0305 {
0306   typedef typename ScalarBinaryOpTraits<Scalar,Exponent,scalar_pow_op>::ReturnType result_type;
0307 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
0308   EIGEN_EMPTY_STRUCT_CTOR(scalar_pow_op)
0309 #else
0310   scalar_pow_op() {
0311     typedef Scalar LhsScalar;
0312     typedef Exponent RhsScalar;
0313     EIGEN_SCALAR_BINARY_OP_PLUGIN
0314   }
0315 #endif
0316 
0317   EIGEN_DEVICE_FUNC
0318   inline result_type operator() (const Scalar& a, const Exponent& b) const { return numext::pow(a, b); }
0319 
0320   template<typename Packet>
0321   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
0322   {
0323     return generic_pow(a,b);
0324   }
0325 };
0326 
0327 template<typename Scalar, typename Exponent>
0328 struct functor_traits<scalar_pow_op<Scalar,Exponent> > {
0329   enum {
0330     Cost = 5 * NumTraits<Scalar>::MulCost,
0331     PacketAccess = (!NumTraits<Scalar>::IsComplex && !NumTraits<Scalar>::IsInteger &&
0332                     packet_traits<Scalar>::HasExp && packet_traits<Scalar>::HasLog &&
0333                     packet_traits<Scalar>::HasRound && packet_traits<Scalar>::HasCmp &&
0334                     // Temporarly disable packet access for half/bfloat16 until
0335                     // accuracy is improved.
0336                     !is_same<Scalar, half>::value && !is_same<Scalar, bfloat16>::value
0337                     )
0338   };
0339 };
0340 
0341 //---------- non associative binary functors ----------
0342 
0343 /** \internal
0344   * \brief Template functor to compute the difference of two scalars
0345   *
0346   * \sa class CwiseBinaryOp, MatrixBase::operator-
0347   */
0348 template<typename LhsScalar,typename RhsScalar>
0349 struct scalar_difference_op : binary_op_base<LhsScalar,RhsScalar>
0350 {
0351   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_difference_op>::ReturnType result_type;
0352 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
0353   EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
0354 #else
0355   scalar_difference_op() {
0356     EIGEN_SCALAR_BINARY_OP_PLUGIN
0357   }
0358 #endif
0359   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a - b; }
0360   template<typename Packet>
0361   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
0362   { return internal::psub(a,b); }
0363 };
0364 template<typename LhsScalar,typename RhsScalar>
0365 struct functor_traits<scalar_difference_op<LhsScalar,RhsScalar> > {
0366   enum {
0367     Cost = (int(NumTraits<LhsScalar>::AddCost) + int(NumTraits<RhsScalar>::AddCost)) / 2,
0368     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasSub && packet_traits<RhsScalar>::HasSub
0369   };
0370 };
0371 
0372 /** \internal
0373   * \brief Template functor to compute the quotient of two scalars
0374   *
0375   * \sa class CwiseBinaryOp, Cwise::operator/()
0376   */
0377 template<typename LhsScalar,typename RhsScalar>
0378 struct scalar_quotient_op  : binary_op_base<LhsScalar,RhsScalar>
0379 {
0380   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_quotient_op>::ReturnType result_type;
0381 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
0382   EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
0383 #else
0384   scalar_quotient_op() {
0385     EIGEN_SCALAR_BINARY_OP_PLUGIN
0386   }
0387 #endif
0388   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
0389   template<typename Packet>
0390   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
0391   { return internal::pdiv(a,b); }
0392 };
0393 template<typename LhsScalar,typename RhsScalar>
0394 struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
0395   typedef typename scalar_quotient_op<LhsScalar,RhsScalar>::result_type result_type;
0396   enum {
0397     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv,
0398     Cost = scalar_div_cost<result_type,PacketAccess>::value
0399   };
0400 };
0401 
0402 
0403 
0404 /** \internal
0405   * \brief Template functor to compute the and of two booleans
0406   *
0407   * \sa class CwiseBinaryOp, ArrayBase::operator&&
0408   */
0409 struct scalar_boolean_and_op {
0410   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
0411   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
0412   template<typename Packet>
0413   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
0414   { return internal::pand(a,b); }
0415 };
0416 template<> struct functor_traits<scalar_boolean_and_op> {
0417   enum {
0418     Cost = NumTraits<bool>::AddCost,
0419     PacketAccess = true
0420   };
0421 };
0422 
0423 /** \internal
0424   * \brief Template functor to compute the or of two booleans
0425   *
0426   * \sa class CwiseBinaryOp, ArrayBase::operator||
0427   */
0428 struct scalar_boolean_or_op {
0429   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
0430   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
0431   template<typename Packet>
0432   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
0433   { return internal::por(a,b); }
0434 };
0435 template<> struct functor_traits<scalar_boolean_or_op> {
0436   enum {
0437     Cost = NumTraits<bool>::AddCost,
0438     PacketAccess = true
0439   };
0440 };
0441 
0442 /** \internal
0443  * \brief Template functor to compute the xor of two booleans
0444  *
0445  * \sa class CwiseBinaryOp, ArrayBase::operator^
0446  */
0447 struct scalar_boolean_xor_op {
0448   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_xor_op)
0449   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a ^ b; }
0450   template<typename Packet>
0451   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
0452   { return internal::pxor(a,b); }
0453 };
0454 template<> struct functor_traits<scalar_boolean_xor_op> {
0455   enum {
0456     Cost = NumTraits<bool>::AddCost,
0457     PacketAccess = true
0458   };
0459 };
0460 
0461 /** \internal
0462   * \brief Template functor to compute the absolute difference of two scalars
0463   *
0464   * \sa class CwiseBinaryOp, MatrixBase::absolute_difference
0465   */
0466 template<typename LhsScalar,typename RhsScalar>
0467 struct scalar_absolute_difference_op : binary_op_base<LhsScalar,RhsScalar>
0468 {
0469   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_absolute_difference_op>::ReturnType result_type;
0470 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
0471   EIGEN_EMPTY_STRUCT_CTOR(scalar_absolute_difference_op)
0472 #else
0473   scalar_absolute_difference_op() {
0474     EIGEN_SCALAR_BINARY_OP_PLUGIN
0475   }
0476 #endif
0477   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
0478   { return numext::absdiff(a,b); }
0479   template<typename Packet>
0480   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
0481   { return internal::pabsdiff(a,b); }
0482 };
0483 template<typename LhsScalar,typename RhsScalar>
0484 struct functor_traits<scalar_absolute_difference_op<LhsScalar,RhsScalar> > {
0485   enum {
0486     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
0487     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasAbsDiff
0488   };
0489 };
0490 
0491 
0492 
0493 //---------- binary functors bound to a constant, thus appearing as a unary functor ----------
0494 
0495 // The following two classes permits to turn any binary functor into a unary one with one argument bound to a constant value.
0496 // They are analogues to std::binder1st/binder2nd but with the following differences:
0497 //  - they are compatible with packetOp
0498 //  - they are portable across C++ versions (the std::binder* are deprecated in C++11)
0499 template<typename BinaryOp> struct bind1st_op : BinaryOp {
0500 
0501   typedef typename BinaryOp::first_argument_type  first_argument_type;
0502   typedef typename BinaryOp::second_argument_type second_argument_type;
0503   typedef typename BinaryOp::result_type          result_type;
0504 
0505   EIGEN_DEVICE_FUNC explicit bind1st_op(const first_argument_type &val) : m_value(val) {}
0506 
0507   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const second_argument_type& b) const { return BinaryOp::operator()(m_value,b); }
0508 
0509   template<typename Packet>
0510   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& b) const
0511   { return BinaryOp::packetOp(internal::pset1<Packet>(m_value), b); }
0512 
0513   first_argument_type m_value;
0514 };
0515 template<typename BinaryOp> struct functor_traits<bind1st_op<BinaryOp> > : functor_traits<BinaryOp> {};
0516 
0517 
0518 template<typename BinaryOp> struct bind2nd_op : BinaryOp {
0519 
0520   typedef typename BinaryOp::first_argument_type  first_argument_type;
0521   typedef typename BinaryOp::second_argument_type second_argument_type;
0522   typedef typename BinaryOp::result_type          result_type;
0523 
0524   EIGEN_DEVICE_FUNC explicit bind2nd_op(const second_argument_type &val) : m_value(val) {}
0525 
0526   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const first_argument_type& a) const { return BinaryOp::operator()(a,m_value); }
0527 
0528   template<typename Packet>
0529   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
0530   { return BinaryOp::packetOp(a,internal::pset1<Packet>(m_value)); }
0531 
0532   second_argument_type m_value;
0533 };
0534 template<typename BinaryOp> struct functor_traits<bind2nd_op<BinaryOp> > : functor_traits<BinaryOp> {};
0535 
0536 
0537 } // end namespace internal
0538 
0539 } // end namespace Eigen
0540 
0541 #endif // EIGEN_BINARY_FUNCTORS_H