Eigen  3.2.91
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_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
30  { return internal::padd(a,b); }
31  template<typename Packet>
32  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_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
69  { return internal::pmul(a,b); }
70  template<typename Packet>
71  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_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_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
121  { return internal::pmin(a,b); }
122  template<typename Packet>
123  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_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
144  { return internal::pmax(a,b); }
145  template<typename Packet>
146  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  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
179  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a==b;}
180 };
181 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LT> {
182  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
183  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<b;}
184 };
185 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_LE> {
186  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
187  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return a<=b;}
188 };
189 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_UNORD> {
190  EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
191  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const Scalar& a, const Scalar& b) const {return !(a<=b || b<=a);}
192 };
193 template<typename Scalar> struct scalar_cmp_op<Scalar, cmp_NEQ> {
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 
198 
204 template<typename Scalar> struct scalar_hypot_op {
205  EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
206 // typedef typename NumTraits<Scalar>::Real result_type;
207  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
208  {
209  using std::sqrt;
210  Scalar p, qp;
211  if(_x>_y)
212  {
213  p = _x;
214  qp = _y / p;
215  }
216  else
217  {
218  p = _y;
219  qp = _x / p;
220  }
221  return p * sqrt(Scalar(1) + qp*qp);
222  }
223 };
224 template<typename Scalar>
225 struct functor_traits<scalar_hypot_op<Scalar> > {
226  enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
227 };
228 
232 template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
233  EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
234  EIGEN_DEVICE_FUNC
235  inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return numext::pow(a, b); }
236 };
237 template<typename Scalar, typename OtherScalar>
238 struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
239  enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
240 };
241 
242 
243 
244 //---------- non associative binary functors ----------
245 
251 template<typename Scalar> struct scalar_difference_op {
252  EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
253  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
254  template<typename Packet>
255  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
256  { return internal::psub(a,b); }
257 };
258 template<typename Scalar>
259 struct functor_traits<scalar_difference_op<Scalar> > {
260  enum {
261  Cost = NumTraits<Scalar>::AddCost,
262  PacketAccess = packet_traits<Scalar>::HasSub
263  };
264 };
265 
271 template<typename LhsScalar,typename RhsScalar> struct scalar_quotient_op {
272  enum {
273  // TODO vectorize mixed product
274  Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv
275  };
276  typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
277  EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
278  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
279  template<typename Packet>
280  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
281  { return internal::pdiv(a,b); }
282 };
283 template<typename LhsScalar,typename RhsScalar>
284 struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
285  enum {
286  Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost), // rough estimate!
287  PacketAccess = scalar_quotient_op<LhsScalar,RhsScalar>::Vectorizable
288  };
289 };
290 
291 
292 
298 struct scalar_boolean_and_op {
299  EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
300  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
301 };
302 template<> struct functor_traits<scalar_boolean_and_op> {
303  enum {
304  Cost = NumTraits<bool>::AddCost,
305  PacketAccess = false
306  };
307 };
308 
314 struct scalar_boolean_or_op {
315  EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
316  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
317 };
318 template<> struct functor_traits<scalar_boolean_or_op> {
319  enum {
320  Cost = NumTraits<bool>::AddCost,
321  PacketAccess = false
322  };
323 };
324 
325 
326 
327 //---------- binary functors bound to a constant, thus appearing as a unary functor ----------
328 
334 /* NOTE why doing the pset1() in packetOp *is* an optimization ?
335  * indeed it seems better to declare m_other as a Packet and do the pset1() once
336  * in the constructor. However, in practice:
337  * - GCC does not like m_other as a Packet and generate a load every time it needs it
338  * - on the other hand GCC is able to moves the pset1() outside the loop :)
339  * - simpler code ;)
340  * (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
341  */
342 template<typename Scalar>
343 struct scalar_multiple_op {
344  // FIXME default copy constructors seems bugged with std::complex<>
345  EIGEN_DEVICE_FUNC
346  EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
347  EIGEN_DEVICE_FUNC
348  EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
349  EIGEN_DEVICE_FUNC
350  EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
351  template <typename Packet>
352  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
353  { return internal::pmul(a, pset1<Packet>(m_other)); }
354  typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
355 };
356 template<typename Scalar>
357 struct functor_traits<scalar_multiple_op<Scalar> >
358 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
359 
360 template<typename Scalar1, typename Scalar2>
361 struct scalar_multiple2_op {
362  typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
363  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { }
364  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { }
365  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; }
366  typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
367 };
368 template<typename Scalar1,typename Scalar2>
369 struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
370 { enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
371 
380 template<typename Scalar>
381 struct scalar_quotient1_op {
382  // FIXME default copy constructors seems bugged with std::complex<>
383  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient1_op(const scalar_quotient1_op& other) : m_other(other.m_other) { }
384  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other) : m_other(other) {}
385  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
386  template <typename Packet>
387  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
388  { return internal::pdiv(a, pset1<Packet>(m_other)); }
389  typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
390 };
391 template<typename Scalar>
392 struct functor_traits<scalar_quotient1_op<Scalar> >
393 { enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
394 
395 template<typename Scalar1, typename Scalar2>
396 struct scalar_quotient2_op {
397  typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
398  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient2_op(const scalar_quotient2_op& other) : m_other(other.m_other) { }
399  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_quotient2_op(const Scalar2& other) : m_other(other) { }
400  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a / m_other; }
401  typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
402 };
403 template<typename Scalar1,typename Scalar2>
404 struct functor_traits<scalar_quotient2_op<Scalar1,Scalar2> >
405 { enum { Cost = 2 * NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
406 
407 // In Eigen, any binary op (Product, CwiseBinaryOp) require the Lhs and Rhs to have the same scalar type, except for multiplication
408 // where the mixing of different types is handled by scalar_product_traits
409 // In particular, real * complex<real> is allowed.
410 // FIXME move this to functor_traits adding a functor_default
411 template<typename Functor> struct functor_is_product_like { enum { ret = 0 }; };
412 template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
413 template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
414 template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_quotient_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
415 
416 
421 /* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */
422 template<typename Scalar>
423 struct scalar_add_op {
424  // FIXME default copy constructors seems bugged with std::complex<>
425  EIGEN_DEVICE_FUNC inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { }
426  EIGEN_DEVICE_FUNC inline scalar_add_op(const Scalar& other) : m_other(other) { }
427  EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return a + m_other; }
428  template <typename Packet>
429  inline const Packet packetOp(const Packet& a) const
430  { return internal::padd(a, pset1<Packet>(m_other)); }
431  const Scalar m_other;
432 };
433 template<typename Scalar>
434 struct functor_traits<scalar_add_op<Scalar> >
435 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
436 
441 template<typename Scalar>
442 struct scalar_sub_op {
443  inline scalar_sub_op(const scalar_sub_op& other) : m_other(other.m_other) { }
444  inline scalar_sub_op(const Scalar& other) : m_other(other) { }
445  inline Scalar operator() (const Scalar& a) const { return a - m_other; }
446  template <typename Packet>
447  inline const Packet packetOp(const Packet& a) const
448  { return internal::psub(a, pset1<Packet>(m_other)); }
449  const Scalar m_other;
450 };
451 template<typename Scalar>
452 struct functor_traits<scalar_sub_op<Scalar> >
453 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
454 
459 template<typename Scalar>
460 struct scalar_rsub_op {
461  inline scalar_rsub_op(const scalar_rsub_op& other) : m_other(other.m_other) { }
462  inline scalar_rsub_op(const Scalar& other) : m_other(other) { }
463  inline Scalar operator() (const Scalar& a) const { return m_other - a; }
464  template <typename Packet>
465  inline const Packet packetOp(const Packet& a) const
466  { return internal::psub(pset1<Packet>(m_other), a); }
467  const Scalar m_other;
468 };
469 template<typename Scalar>
470 struct functor_traits<scalar_rsub_op<Scalar> >
471 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
472 
477 template<typename Scalar>
478 struct scalar_pow_op {
479  // FIXME default copy constructors seems bugged with std::complex<>
480  inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
481  inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
482  EIGEN_DEVICE_FUNC
483  inline Scalar operator() (const Scalar& a) const { return numext::pow(a, m_exponent); }
484  const Scalar m_exponent;
485 };
486 template<typename Scalar>
487 struct functor_traits<scalar_pow_op<Scalar> >
488 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
489 
494 template<typename Scalar>
495 struct scalar_inverse_mult_op {
496  scalar_inverse_mult_op(const Scalar& other) : m_other(other) {}
497  EIGEN_DEVICE_FUNC inline Scalar operator() (const Scalar& a) const { return m_other / a; }
498  template<typename Packet>
499  inline const Packet packetOp(const Packet& a) const
500  { return internal::pdiv(pset1<Packet>(m_other),a); }
501  Scalar m_other;
502 };
503 
504 } // end namespace internal
505 
506 } // end namespace Eigen
507 
508 #endif // EIGEN_BINARY_FUNCTORS_H
Definition: LDLT.h:16
Definition: Eigen_Colamd.h:54