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