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
13namespace Eigen {
14
15namespace internal {
16
17//---------- associative binary functors ----------
18
19template<typename Arg1, typename Arg2>
20struct 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 */
31template<typename LhsScalar,typename RhsScalar>
32struct 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};
50template<typename LhsScalar,typename RhsScalar>
51struct 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 */
64template<> 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 */
75template<typename LhsScalar,typename RhsScalar>
76struct 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};
94template<typename LhsScalar,typename RhsScalar>
95struct 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 */
108template<typename LhsScalar,typename RhsScalar>
109struct 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};
126template<typename LhsScalar,typename RhsScalar>
127struct 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 */
139template<typename LhsScalar,typename RhsScalar>
140struct 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};
152template<typename LhsScalar,typename RhsScalar>
153struct 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 */
165template<typename LhsScalar,typename RhsScalar>
166struct 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};
178template<typename LhsScalar,typename RhsScalar>
179struct 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 */
190template<typename LhsScalar, typename RhsScalar, ComparisonName cmp> struct scalar_cmp_op;
191
192template<typename LhsScalar, typename RhsScalar, ComparisonName cmp>
193struct 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
200template<ComparisonName Cmp, typename LhsScalar, typename RhsScalar>
201struct result_of<scalar_cmp_op<LhsScalar, RhsScalar, Cmp>(LhsScalar,RhsScalar)> {
202 typedef bool type;
203};
204
205
206template<typename LhsScalar, typename RhsScalar>
207struct 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};
213template<typename LhsScalar, typename RhsScalar>
214struct 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};
220template<typename LhsScalar, typename RhsScalar>
221struct 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};
227template<typename LhsScalar, typename RhsScalar>
228struct 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};
234template<typename LhsScalar, typename RhsScalar>
235struct 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};
241template<typename LhsScalar, typename RhsScalar>
242struct 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};
248template<typename LhsScalar, typename RhsScalar>
249struct 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 */
262template<typename Scalar>
263struct 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};
277template<typename Scalar>
278struct 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 */
291template<typename Scalar, typename Exponent>
292struct 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};
307template<typename Scalar, typename Exponent>
308struct 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 */
321template<typename LhsScalar,typename RhsScalar>
322struct 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};
337template<typename LhsScalar,typename RhsScalar>
338struct 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 */
350template<typename LhsScalar,typename RhsScalar>
351struct 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};
366template<typename LhsScalar,typename RhsScalar>
367struct 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 */
382struct 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};
386template<> 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 */
398struct 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};
402template<> 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 */
414struct 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};
418template<> 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)
433template<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};
449template<typename BinaryOp> struct functor_traits<bind1st_op<BinaryOp> > : functor_traits<BinaryOp> {};
450
451
452template<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};
468template<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