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 \b positive \b and \b real 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 267 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar &x, const Scalar &y) const 268 { 269 // This functor is used by hypotNorm only for which it is faster to first apply abs 270 // on all coefficients prior to reduction through hypot. 271 // This way we avoid calling abs on positive and real entries, and this also permits 272 // to seamlessly handle complexes. Otherwise we would have to handle both real and complexes 273 // through the same functor... 274 return internal::positive_real_hypot(x,y); 275 } 276 }; 277 template<typename Scalar> 278 struct functor_traits<scalar_hypot_op<Scalar,Scalar> > { 279 enum 280 { 281 Cost = 3 * NumTraits<Scalar>::AddCost + 282 2 * NumTraits<Scalar>::MulCost + 283 2 * scalar_div_cost<Scalar,false>::value, 284 PacketAccess = false 285 }; 286 }; 287 288 /** \internal 289 * \brief Template functor to compute the pow of two scalars 290 */ 291 template<typename Scalar, typename Exponent> 292 struct scalar_pow_op : binary_op_base<Scalar,Exponent> 293 { 294 typedef typename ScalarBinaryOpTraits<Scalar,Exponent,scalar_pow_op>::ReturnType result_type; 295 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN 296 EIGEN_EMPTY_STRUCT_CTOR(scalar_pow_op) 297 #else 298 scalar_pow_op() { 299 typedef Scalar LhsScalar; 300 typedef Exponent RhsScalar; 301 EIGEN_SCALAR_BINARY_OP_PLUGIN 302 } 303 #endif 304 EIGEN_DEVICE_FUNC 305 inline result_type operator() (const Scalar& a, const Exponent& b) const { return numext::pow(a, b); } 306 }; 307 template<typename Scalar, typename Exponent> 308 struct functor_traits<scalar_pow_op<Scalar,Exponent> > { 309 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; 310 }; 311 312 313 314 //---------- non associative binary functors ---------- 315 316 /** \internal 317 * \brief Template functor to compute the difference of two scalars 318 * 319 * \sa class CwiseBinaryOp, MatrixBase::operator- 320 */ 321 template<typename LhsScalar,typename RhsScalar> 322 struct scalar_difference_op : binary_op_base<LhsScalar,RhsScalar> 323 { 324 typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_difference_op>::ReturnType result_type; 325 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN 326 EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op) 327 #else 328 scalar_difference_op() { 329 EIGEN_SCALAR_BINARY_OP_PLUGIN 330 } 331 #endif 332 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a - b; } 333 template<typename Packet> 334 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const 335 { return internal::psub(a,b); } 336 }; 337 template<typename LhsScalar,typename RhsScalar> 338 struct functor_traits<scalar_difference_op<LhsScalar,RhsScalar> > { 339 enum { 340 Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2, 341 PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasSub && packet_traits<RhsScalar>::HasSub 342 }; 343 }; 344 345 /** \internal 346 * \brief Template functor to compute the quotient of two scalars 347 * 348 * \sa class CwiseBinaryOp, Cwise::operator/() 349 */ 350 template<typename LhsScalar,typename RhsScalar> 351 struct scalar_quotient_op : binary_op_base<LhsScalar,RhsScalar> 352 { 353 typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_quotient_op>::ReturnType result_type; 354 #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN 355 EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op) 356 #else 357 scalar_quotient_op() { 358 EIGEN_SCALAR_BINARY_OP_PLUGIN 359 } 360 #endif 361 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; } 362 template<typename Packet> 363 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const 364 { return internal::pdiv(a,b); } 365 }; 366 template<typename LhsScalar,typename RhsScalar> 367 struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > { 368 typedef typename scalar_quotient_op<LhsScalar,RhsScalar>::result_type result_type; 369 enum { 370 PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv, 371 Cost = scalar_div_cost<result_type,PacketAccess>::value 372 }; 373 }; 374 375 376 377 /** \internal 378 * \brief Template functor to compute the and of two booleans 379 * 380 * \sa class CwiseBinaryOp, ArrayBase::operator&& 381 */ 382 struct scalar_boolean_and_op { 383 EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op) 384 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; } 385 }; 386 template<> struct functor_traits<scalar_boolean_and_op> { 387 enum { 388 Cost = NumTraits<bool>::AddCost, 389 PacketAccess = false 390 }; 391 }; 392 393 /** \internal 394 * \brief Template functor to compute the or of two booleans 395 * 396 * \sa class CwiseBinaryOp, ArrayBase::operator|| 397 */ 398 struct scalar_boolean_or_op { 399 EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op) 400 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; } 401 }; 402 template<> struct functor_traits<scalar_boolean_or_op> { 403 enum { 404 Cost = NumTraits<bool>::AddCost, 405 PacketAccess = false 406 }; 407 }; 408 409 /** \internal 410 * \brief Template functor to compute the xor of two booleans 411 * 412 * \sa class CwiseBinaryOp, ArrayBase::operator^ 413 */ 414 struct scalar_boolean_xor_op { 415 EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_xor_op) 416 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a ^ b; } 417 }; 418 template<> struct functor_traits<scalar_boolean_xor_op> { 419 enum { 420 Cost = NumTraits<bool>::AddCost, 421 PacketAccess = false 422 }; 423 }; 424 425 426 427 //---------- binary functors bound to a constant, thus appearing as a unary functor ---------- 428 429 // The following two classes permits to turn any binary functor into a unary one with one argument bound to a constant value. 430 // They are analogues to std::binder1st/binder2nd but with the following differences: 431 // - they are compatible with packetOp 432 // - they are portable across C++ versions (the std::binder* are deprecated in C++11) 433 template<typename BinaryOp> struct bind1st_op : BinaryOp { 434 435 typedef typename BinaryOp::first_argument_type first_argument_type; 436 typedef typename BinaryOp::second_argument_type second_argument_type; 437 typedef typename BinaryOp::result_type result_type; 438 439 bind1st_op(const first_argument_type &val) : m_value(val) {} 440 441 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const second_argument_type& b) const { return BinaryOp::operator()(m_value,b); } 442 443 template<typename Packet> 444 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& b) const 445 { return BinaryOp::packetOp(internal::pset1<Packet>(m_value), b); } 446 447 first_argument_type m_value; 448 }; 449 template<typename BinaryOp> struct functor_traits<bind1st_op<BinaryOp> > : functor_traits<BinaryOp> {}; 450 451 452 template<typename BinaryOp> struct bind2nd_op : BinaryOp { 453 454 typedef typename BinaryOp::first_argument_type first_argument_type; 455 typedef typename BinaryOp::second_argument_type second_argument_type; 456 typedef typename BinaryOp::result_type result_type; 457 458 bind2nd_op(const second_argument_type &val) : m_value(val) {} 459 460 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const first_argument_type& a) const { return BinaryOp::operator()(a,m_value); } 461 462 template<typename Packet> 463 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const 464 { return BinaryOp::packetOp(a,internal::pset1<Packet>(m_value)); } 465 466 second_argument_type m_value; 467 }; 468 template<typename BinaryOp> struct functor_traits<bind2nd_op<BinaryOp> > : functor_traits<BinaryOp> {}; 469 470 471 } // end namespace internal 472 473 } // end namespace Eigen 474 475 #endif // EIGEN_BINARY_FUNCTORS_H 476