Eigen  3.2.92
BinaryFunctors.h
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 
24 template<typename Scalar> struct scalar_sum_op {
25 // typedef Scalar result_type;
26  EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
27  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
28  template<typename Packet>
29  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
30  { return internal::padd(a,b); }
31  template<typename Packet>
32  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
33  { return internal::predux(a); }
34 };
35 template<typename Scalar>
36 struct functor_traits<scalar_sum_op<Scalar> > {
37  enum {
38  Cost = NumTraits<Scalar>::AddCost,
39  PacketAccess = packet_traits<Scalar>::HasAdd
40  };
41 };
42 
48 template<> struct scalar_sum_op<bool> : scalar_sum_op<int> {
49  EIGEN_DEPRECATED
50  scalar_sum_op() {}
51 };
52 
53 
59 template<typename LhsScalar,typename RhsScalar> struct scalar_product_op {
60  enum {
61  // TODO vectorize mixed product
62  Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
63  };
64  typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
65  EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
66  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
67  template<typename Packet>
68  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
69  { return internal::pmul(a,b); }
70  template<typename Packet>
71  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
72  { return internal::predux_mul(a); }
73 };
74 template<typename LhsScalar,typename RhsScalar>
75 struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
76  enum {
77  Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
78  PacketAccess = scalar_product_op<LhsScalar,RhsScalar>::Vectorizable
79  };
80 };
81 
87 template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op {
88 
89  enum {
90  Conj = NumTraits<LhsScalar>::IsComplex
91  };
92 
93  typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
94 
95  EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
96  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
97  { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
98 
99  template<typename Packet>
100  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
101  { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
102 };
103 template<typename LhsScalar,typename RhsScalar>
104 struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
105  enum {
106  Cost = NumTraits<LhsScalar>::MulCost,
107  PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
108  };
109 };
110 
116 template<typename Scalar> struct scalar_min_op {
117  EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
118  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return numext::mini(a, b); }
119  template<typename Packet>
120  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
121  { return internal::pmin(a,b); }
122  template<typename Packet>
123  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
124  { return internal::predux_min(a); }
125 };
126 template<typename Scalar>
127 struct functor_traits<scalar_min_op<Scalar> > {
128  enum {
129  Cost = NumTraits<Scalar>::AddCost,
130  PacketAccess = packet_traits<Scalar>::HasMin
131  };
132 };
133 
139 template<typename Scalar> struct scalar_max_op {
140  EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
141  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return numext::maxi(a, b); }
142  template<typename Packet>
143  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
144  { return internal::pmax(a,b); }
145  template<typename Packet>
146  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
147  { return internal::predux_max(a); }
148 };
149 template<typename Scalar>
150 struct functor_traits<scalar_max_op<Scalar> > {
151  enum {
152  Cost = NumTraits<Scalar>::AddCost,
153  PacketAccess = packet_traits<Scalar>::HasMax
154  };
155 };
156 
161 template<typename Scalar, ComparisonName cmp> struct scalar_cmp_op;
162 
163 template<typename Scalar, ComparisonName cmp>
164 struct functor_traits<scalar_cmp_op<Scalar, cmp> > {
165  enum {
166  Cost = NumTraits<Scalar>::AddCost,
167  PacketAccess = false
168  };
169 };
170 
171 template<ComparisonName Cmp, typename Scalar>
172 struct result_of<scalar_cmp_op<Scalar, Cmp>(Scalar,Scalar)> {
173  typedef bool type;
174 };
175 
176 
177 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_EQ> {
178  typedef bool result_type;
179  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
180  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a==b;}
181 };
182 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LT> {
183  typedef bool result_type;
184  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
185  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<b;}
186 };
187 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LE> {
188  typedef bool result_type;
189  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
190  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<=b;}
191 };
192 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_GT> {
193  typedef bool result_type;
194  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
195  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a>b;}
196 };
197 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_GE> {
198  typedef bool result_type;
199  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
200  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a>=b;}
201 };
202 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_UNORD> {
203  typedef bool result_type;
204  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
205  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return !(a<=b || b<=a);}
206 };
207 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_NEQ> {
208  typedef bool result_type;
209  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
210  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a!=b;}
211 };
212 
213 
219 template<typename Scalar> struct scalar_hypot_op {
220  EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
221 // typedef typename NumTraits<Scalar>::Real result_type;
222  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
223  {
224  using std::sqrt;
225  Scalar p, qp;
226  if(_x>_y)
227  {
228  p = _x;
229  qp = _y / p;
230  }
231  else
232  {
233  p = _y;
234  qp = _x / p;
235  }
236  return p * sqrt(Scalar(1) + qp*qp);
237  }
238 };
239 template<typename Scalar>
240 struct functor_traits<scalar_hypot_op<Scalar> > {
241  enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
242 };
243 
247 template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
248  EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
249  EIGEN_DEVICE_FUNC
250  inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return numext::pow(a, b); }
251 };
252 template<typename Scalar, typename OtherScalar>
253 struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
254  enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
255 };
256 
257 
258 
259 //---------- non associative binary functors ----------
260 
266 template<typename Scalar> struct scalar_difference_op {
267  EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
268  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
269  template<typename Packet>
270  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
271  { return internal::psub(a,b); }
272 };
273 template<typename Scalar>
274 struct functor_traits<scalar_difference_op<Scalar> > {
275  enum {
276  Cost = NumTraits<Scalar>::AddCost,
277  PacketAccess = packet_traits<Scalar>::HasSub
278  };
279 };
280 
286 template<typename LhsScalar,typename RhsScalar> struct scalar_quotient_op {
287  enum {
288  // TODO vectorize mixed product
289  Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv
290  };
291  typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
292  EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
293  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
294  template<typename Packet>
295  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
296  { return internal::pdiv(a,b); }
297 };
298 template<typename LhsScalar,typename RhsScalar>
299 struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
300  enum {
301  Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost), // rough estimate!
302  PacketAccess = scalar_quotient_op<LhsScalar,RhsScalar>::Vectorizable
303  };
304 };
305 
306 
307 
313 struct scalar_boolean_and_op {
314  EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
315  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
316 };
317 template<> struct functor_traits<scalar_boolean_and_op> {
318  enum {
319  Cost = NumTraits<bool>::AddCost,
320  PacketAccess = false
321  };
322 };
323 
329 struct scalar_boolean_or_op {
330  EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
331  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
332 };
333 template<> struct functor_traits<scalar_boolean_or_op> {
334  enum {
335  Cost = NumTraits<bool>::AddCost,
336  PacketAccess = false
337  };
338 };
339 
340 
341 
342 //---------- binary functors bound to a constant, thus appearing as a unary functor ----------
343 
349 /* NOTE why doing the pset1() in packetOp *is* an optimization ?
350  * indeed it seems better to declare m_other as a Packet and do the pset1() once
351  * in the constructor. However, in practice:
352  * - GCC does not like m_other as a Packet and generate a load every time it needs it
353  * - on the other hand GCC is able to moves the pset1() outside the loop :)
354  * - simpler code ;)
355  * (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
356  */
357 template<typename Scalar>
358 struct scalar_multiple_op {
359  // FIXME default copy constructors seems bugged with std::complex<>
360  EIGEN_DEVICE_FUNC
361  EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
362  EIGEN_DEVICE_FUNC
363  EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
364  EIGEN_DEVICE_FUNC
365  EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
366  template <typename Packet>
367  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
368  { return internal::pmul(a, pset1<Packet>(m_other)); }
369  typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
370 };
371 template<typename Scalar>
372 struct functor_traits<scalar_multiple_op<Scalar> >
373 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
374 
375 template<typename Scalar1, typename Scalar2>
376 struct scalar_multiple2_op {
377  typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
378  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { }
379  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { }
380  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; }
381  typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
382 };
383 template<typename Scalar1,typename Scalar2>
384 struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
385 { enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
386 
395 template<typename Scalar>
396 struct scalar_quotient1_op {
397  // FIXME default copy constructors seems bugged with std::complex<>
398  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient1_op(const scalar_quotient1_op& other) : m_other(other.m_other) { }
399  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other) : m_other(other) {}
400  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
401  template <typename Packet>
402  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
403  { return internal::pdiv(a, pset1<Packet>(m_other)); }
404  typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
405 };
406 template<typename Scalar>
407 struct functor_traits<scalar_quotient1_op<Scalar> >
408 { enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
409 
410 template<typename Scalar1, typename Scalar2>
411 struct scalar_quotient2_op {
412  typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
413  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient2_op(const scalar_quotient2_op& other) : m_other(other.m_other) { }
414  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient2_op(const Scalar2& other) : m_other(other) { }
415  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a / m_other; }
416  typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
417 };
418 template<typename Scalar1,typename Scalar2>
419 struct functor_traits<scalar_quotient2_op<Scalar1,Scalar2> >
420 { enum { Cost = 2 * NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
421 
422 // In Eigen, any binary op (Product, CwiseBinaryOp) require the Lhs and Rhs to have the same scalar type, except for multiplication
423 // where the mixing of different types is handled by scalar_product_traits
424 // In particular, real * complex<real> is allowed.
425 // FIXME move this to functor_traits adding a functor_default
426 template<typename Functor> struct functor_is_product_like { enum { ret = 0 }; };
427 template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
428 template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
429 template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_quotient_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
430 
431 
436 /* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */
437 template<typename Scalar>
438 struct scalar_add_op {
439  // FIXME default copy constructors seems bugged with std::complex<>
440  EIGEN_DEVICE_FUNC inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { }
441  EIGEN_DEVICE_FUNC inline scalar_add_op(const Scalar& other) : m_other(other) { }
442  EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a + m_other; }
443  template <typename Packet>
444  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
445  { return internal::padd(a, pset1<Packet>(m_other)); }
446  const Scalar m_other;
447 };
448 template<typename Scalar>
449 struct functor_traits<scalar_add_op<Scalar> >
450 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
451 
456 template<typename Scalar>
457 struct scalar_sub_op {
458  EIGEN_DEVICE_FUNC inline scalar_sub_op(const scalar_sub_op& other) : m_other(other.m_other) { }
459  EIGEN_DEVICE_FUNC inline scalar_sub_op(const Scalar& other) : m_other(other) { }
460  EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a - m_other; }
461  template <typename Packet>
462  EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
463  { return internal::psub(a, pset1<Packet>(m_other)); }
464  const Scalar m_other;
465 };
466 template<typename Scalar>
467 struct functor_traits<scalar_sub_op<Scalar> >
468 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
469 
474 template<typename Scalar>
475 struct scalar_rsub_op {
476  EIGEN_DEVICE_FUNC inline scalar_rsub_op(const scalar_rsub_op& other) : m_other(other.m_other) { }
477  EIGEN_DEVICE_FUNC inline scalar_rsub_op(const Scalar& other) : m_other(other) { }
478  EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return m_other - a; }
479  template <typename Packet>
480  EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
481  { return internal::psub(pset1<Packet>(m_other), a); }
482  const Scalar m_other;
483 };
484 template<typename Scalar>
485 struct functor_traits<scalar_rsub_op<Scalar> >
486 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
487 
492 template<typename Scalar>
493 struct scalar_pow_op {
494  // FIXME default copy constructors seems bugged with std::complex<>
495  EIGEN_DEVICE_FUNC inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
496  EIGEN_DEVICE_FUNC inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
497  EIGEN_DEVICE_FUNC
498  inline Scalar operator() (const Scalar& a) const { return numext::pow(a, m_exponent); }
499  const Scalar m_exponent;
500 };
501 template<typename Scalar>
502 struct functor_traits<scalar_pow_op<Scalar> >
503 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
504 
509 template<typename Scalar>
510 struct scalar_inverse_mult_op {
511  EIGEN_DEVICE_FUNC scalar_inverse_mult_op(const Scalar& other) : m_other(other) {}
512  EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return m_other / a; }
513  template<typename Packet>
514  EIGEN_DEVICE_FUNC inline const Packet packetOp(const Packet& a) const
515  { return internal::pdiv(pset1<Packet>(m_other),a); }
516  Scalar m_other;
517 };
518 
519 } // end namespace internal
520 
521 } // end namespace Eigen
522 
523 #endif // EIGEN_BINARY_FUNCTORS_H
Definition: LDLT.h:16
Definition: Eigen_Colamd.h:54