![]() |
Eigen
3.3.3
|
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