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