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@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 scalar_sum_opscalar_sum_op38 scalar_sum_op() { 39 EIGEN_SCALAR_BINARY_OP_PLUGIN 40 } 41 #endif operatorscalar_sum_op42 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a + b; } 43 template<typename Packet> packetOpscalar_sum_op44 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> preduxscalar_sum_op47 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