Eigen  3.3.3
BinaryFunctors.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_BINARY_FUNCTORS_H
00011 #define EIGEN_BINARY_FUNCTORS_H
00012 
00013 namespace Eigen {
00014 
00015 namespace internal {
00016 
00017 //---------- associative binary functors ----------
00018 
00019 template<typename Arg1, typename Arg2>
00020 struct binary_op_base
00021 {
00022   typedef Arg1 first_argument_type;
00023   typedef Arg2 second_argument_type;
00024 };
00025 
00031 template<typename LhsScalar,typename RhsScalar>
00032 struct scalar_sum_op : binary_op_base<LhsScalar,RhsScalar>
00033 {
00034   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_sum_op>::ReturnType result_type;
00035 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
00036   EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
00037 #else
00038   scalar_sum_op() {
00039     EIGEN_SCALAR_BINARY_OP_PLUGIN
00040   }
00041 #endif
00042   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a + b; }
00043   template<typename Packet>
00044   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00045   { return internal::padd(a,b); }
00046   template<typename Packet>
00047   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
00048   { return internal::predux(a); }
00049 };
00050 template<typename LhsScalar,typename RhsScalar>
00051 struct functor_traits<scalar_sum_op<LhsScalar,RhsScalar> > {
00052   enum {
00053     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2, // rough estimate!
00054     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasAdd && packet_traits<RhsScalar>::HasAdd
00055     // TODO vectorize mixed sum
00056   };
00057 };
00058 
00064 template<> struct scalar_sum_op<bool,bool> : scalar_sum_op<int,int> {
00065   EIGEN_DEPRECATED
00066   scalar_sum_op() {}
00067 };
00068 
00069 
00075 template<typename LhsScalar,typename RhsScalar>
00076 struct scalar_product_op  : binary_op_base<LhsScalar,RhsScalar>
00077 {
00078   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_product_op>::ReturnType result_type;
00079 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
00080   EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
00081 #else
00082   scalar_product_op() {
00083     EIGEN_SCALAR_BINARY_OP_PLUGIN
00084   }
00085 #endif
00086   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
00087   template<typename Packet>
00088   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00089   { return internal::pmul(a,b); }
00090   template<typename Packet>
00091   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
00092   { return internal::predux_mul(a); }
00093 };
00094 template<typename LhsScalar,typename RhsScalar>
00095 struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
00096   enum {
00097     Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
00098     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
00099     // TODO vectorize mixed product
00100   };
00101 };
00102 
00108 template<typename LhsScalar,typename RhsScalar>
00109 struct scalar_conj_product_op  : binary_op_base<LhsScalar,RhsScalar>
00110 {
00111 
00112   enum {
00113     Conj = NumTraits<LhsScalar>::IsComplex
00114   };
00115   
00116   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_conj_product_op>::ReturnType result_type;
00117   
00118   EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
00119   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
00120   { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
00121   
00122   template<typename Packet>
00123   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00124   { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
00125 };
00126 template<typename LhsScalar,typename RhsScalar>
00127 struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
00128   enum {
00129     Cost = NumTraits<LhsScalar>::MulCost,
00130     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
00131   };
00132 };
00133 
00139 template<typename LhsScalar,typename RhsScalar>
00140 struct scalar_min_op : binary_op_base<LhsScalar,RhsScalar>
00141 {
00142   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_min_op>::ReturnType result_type;
00143   EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
00144   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return numext::mini(a, b); }
00145   template<typename Packet>
00146   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00147   { return internal::pmin(a,b); }
00148   template<typename Packet>
00149   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
00150   { return internal::predux_min(a); }
00151 };
00152 template<typename LhsScalar,typename RhsScalar>
00153 struct functor_traits<scalar_min_op<LhsScalar,RhsScalar> > {
00154   enum {
00155     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
00156     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMin
00157   };
00158 };
00159 
00165 template<typename LhsScalar,typename RhsScalar>
00166 struct scalar_max_op  : binary_op_base<LhsScalar,RhsScalar>
00167 {
00168   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_max_op>::ReturnType result_type;
00169   EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
00170   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return numext::maxi(a, b); }
00171   template<typename Packet>
00172   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00173   { return internal::pmax(a,b); }
00174   template<typename Packet>
00175   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
00176   { return internal::predux_max(a); }
00177 };
00178 template<typename LhsScalar,typename RhsScalar>
00179 struct functor_traits<scalar_max_op<LhsScalar,RhsScalar> > {
00180   enum {
00181     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
00182     PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMax
00183   };
00184 };
00185 
00190 template<typename LhsScalar, typename RhsScalar, ComparisonName cmp> struct scalar_cmp_op;
00191 
00192 template<typename LhsScalar, typename RhsScalar, ComparisonName cmp>
00193 struct functor_traits<scalar_cmp_op<LhsScalar,RhsScalar, cmp> > {
00194   enum {
00195     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
00196     PacketAccess = false
00197   };
00198 };
00199 
00200 template<ComparisonName Cmp, typename LhsScalar, typename RhsScalar>
00201 struct result_of<scalar_cmp_op<LhsScalar, RhsScalar, Cmp>(LhsScalar,RhsScalar)> {
00202   typedef bool type;
00203 };
00204 
00205 
00206 template<typename LhsScalar, typename RhsScalar>
00207 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_EQ> : binary_op_base<LhsScalar,RhsScalar>
00208 {
00209   typedef bool result_type;
00210   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
00211   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a==b;}
00212 };
00213 template<typename LhsScalar, typename RhsScalar>
00214 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LT> : binary_op_base<LhsScalar,RhsScalar>
00215 {
00216   typedef bool result_type;
00217   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
00218   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<b;}
00219 };
00220 template<typename LhsScalar, typename RhsScalar>
00221 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LE> : binary_op_base<LhsScalar,RhsScalar>
00222 {
00223   typedef bool result_type;
00224   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
00225   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<=b;}
00226 };
00227 template<typename LhsScalar, typename RhsScalar>
00228 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GT> : binary_op_base<LhsScalar,RhsScalar>
00229 {
00230   typedef bool result_type;
00231   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
00232   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>b;}
00233 };
00234 template<typename LhsScalar, typename RhsScalar>
00235 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GE> : binary_op_base<LhsScalar,RhsScalar>
00236 {
00237   typedef bool result_type;
00238   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
00239   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>=b;}
00240 };
00241 template<typename LhsScalar, typename RhsScalar>
00242 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_UNORD> : binary_op_base<LhsScalar,RhsScalar>
00243 {
00244   typedef bool result_type;
00245   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
00246   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return !(a<=b || b<=a);}
00247 };
00248 template<typename LhsScalar, typename RhsScalar>
00249 struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_NEQ> : binary_op_base<LhsScalar,RhsScalar>
00250 {
00251   typedef bool result_type;
00252   EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
00253   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a!=b;}
00254 };
00255 
00256 
00262 template<typename Scalar>
00263 struct scalar_hypot_op<Scalar,Scalar> : binary_op_base<Scalar,Scalar>
00264 {
00265   EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
00266 //   typedef typename NumTraits<Scalar>::Real result_type;
00267   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
00268   {
00269     EIGEN_USING_STD_MATH(sqrt)
00270     Scalar p, qp;
00271     if(_x>_y)
00272     {
00273       p = _x;
00274       qp = _y / p;
00275     }
00276     else
00277     {
00278       p = _y;
00279       qp = _x / p;
00280     }
00281     return p * sqrt(Scalar(1) + qp*qp);
00282   }
00283 };
00284 template<typename Scalar>
00285 struct functor_traits<scalar_hypot_op<Scalar,Scalar> > {
00286   enum
00287   {
00288     Cost = 3 * NumTraits<Scalar>::AddCost +
00289            2 * NumTraits<Scalar>::MulCost +
00290            2 * scalar_div_cost<Scalar,false>::value,
00291     PacketAccess = false
00292   };
00293 };
00294 
00298 template<typename Scalar, typename Exponent>
00299 struct scalar_pow_op  : binary_op_base<Scalar,Exponent>
00300 {
00301   typedef typename ScalarBinaryOpTraits<Scalar,Exponent,scalar_pow_op>::ReturnType result_type;
00302 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
00303   EIGEN_EMPTY_STRUCT_CTOR(scalar_pow_op)
00304 #else
00305   scalar_pow_op() {
00306     typedef Scalar LhsScalar;
00307     typedef Exponent RhsScalar;
00308     EIGEN_SCALAR_BINARY_OP_PLUGIN
00309   }
00310 #endif
00311   EIGEN_DEVICE_FUNC
00312   inline result_type operator() (const Scalar& a, const Exponent& b) const { return numext::pow(a, b); }
00313 };
00314 template<typename Scalar, typename Exponent>
00315 struct functor_traits<scalar_pow_op<Scalar,Exponent> > {
00316   enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
00317 };
00318 
00319 
00320 
00321 //---------- non associative binary functors ----------
00322 
00328 template<typename LhsScalar,typename RhsScalar>
00329 struct scalar_difference_op : binary_op_base<LhsScalar,RhsScalar>
00330 {
00331   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_difference_op>::ReturnType result_type;
00332 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
00333   EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
00334 #else
00335   scalar_difference_op() {
00336     EIGEN_SCALAR_BINARY_OP_PLUGIN
00337   }
00338 #endif
00339   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a - b; }
00340   template<typename Packet>
00341   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00342   { return internal::psub(a,b); }
00343 };
00344 template<typename LhsScalar,typename RhsScalar>
00345 struct functor_traits<scalar_difference_op<LhsScalar,RhsScalar> > {
00346   enum {
00347     Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
00348     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasSub && packet_traits<RhsScalar>::HasSub
00349   };
00350 };
00351 
00357 template<typename LhsScalar,typename RhsScalar>
00358 struct scalar_quotient_op  : binary_op_base<LhsScalar,RhsScalar>
00359 {
00360   typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_quotient_op>::ReturnType result_type;
00361 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
00362   EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
00363 #else
00364   scalar_quotient_op() {
00365     EIGEN_SCALAR_BINARY_OP_PLUGIN
00366   }
00367 #endif
00368   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
00369   template<typename Packet>
00370   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00371   { return internal::pdiv(a,b); }
00372 };
00373 template<typename LhsScalar,typename RhsScalar>
00374 struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
00375   typedef typename scalar_quotient_op<LhsScalar,RhsScalar>::result_type result_type;
00376   enum {
00377     PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv,
00378     Cost = scalar_div_cost<result_type,PacketAccess>::value
00379   };
00380 };
00381 
00382 
00383 
00389 struct scalar_boolean_and_op {
00390   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
00391   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
00392 };
00393 template<> struct functor_traits<scalar_boolean_and_op> {
00394   enum {
00395     Cost = NumTraits<bool>::AddCost,
00396     PacketAccess = false
00397   };
00398 };
00399 
00405 struct scalar_boolean_or_op {
00406   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
00407   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
00408 };
00409 template<> struct functor_traits<scalar_boolean_or_op> {
00410   enum {
00411     Cost = NumTraits<bool>::AddCost,
00412     PacketAccess = false
00413   };
00414 };
00415 
00421 struct scalar_boolean_xor_op {
00422   EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_xor_op)
00423   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a ^ b; }
00424 };
00425 template<> struct functor_traits<scalar_boolean_xor_op> {
00426   enum {
00427     Cost = NumTraits<bool>::AddCost,
00428     PacketAccess = false
00429   };
00430 };
00431 
00432 
00433 
00434 //---------- binary functors bound to a constant, thus appearing as a unary functor ----------
00435 
00436 // The following two classes permits to turn any binary functor into a unary one with one argument bound to a constant value.
00437 // They are analogues to std::binder1st/binder2nd but with the following differences:
00438 //  - they are compatible with packetOp
00439 //  - they are portable across C++ versions (the std::binder* are deprecated in C++11)
00440 template<typename BinaryOp> struct bind1st_op : BinaryOp {
00441 
00442   typedef typename BinaryOp::first_argument_type  first_argument_type;
00443   typedef typename BinaryOp::second_argument_type second_argument_type;
00444   typedef typename BinaryOp::result_type          result_type;
00445 
00446   bind1st_op(const first_argument_type &val) : m_value(val) {}
00447 
00448   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const second_argument_type& b) const { return BinaryOp::operator()(m_value,b); }
00449 
00450   template<typename Packet>
00451   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& b) const
00452   { return BinaryOp::packetOp(internal::pset1<Packet>(m_value), b); }
00453 
00454   first_argument_type m_value;
00455 };
00456 template<typename BinaryOp> struct functor_traits<bind1st_op<BinaryOp> > : functor_traits<BinaryOp> {};
00457 
00458 
00459 template<typename BinaryOp> struct bind2nd_op : BinaryOp {
00460 
00461   typedef typename BinaryOp::first_argument_type  first_argument_type;
00462   typedef typename BinaryOp::second_argument_type second_argument_type;
00463   typedef typename BinaryOp::result_type          result_type;
00464 
00465   bind2nd_op(const second_argument_type &val) : m_value(val) {}
00466 
00467   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const first_argument_type& a) const { return BinaryOp::operator()(a,m_value); }
00468 
00469   template<typename Packet>
00470   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
00471   { return BinaryOp::packetOp(a,internal::pset1<Packet>(m_value)); }
00472 
00473   second_argument_type m_value;
00474 };
00475 template<typename BinaryOp> struct functor_traits<bind2nd_op<BinaryOp> > : functor_traits<BinaryOp> {};
00476 
00477 
00478 } // end namespace internal
00479 
00480 } // end namespace Eigen
00481 
00482 #endif // EIGEN_BINARY_FUNCTORS_H
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends