Medial Code Documentation
Loading...
Searching...
No Matches
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
13namespace Eigen {
14
15namespace internal {
16
17//---------- associative binary functors ----------
18
24template<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};
35template<typename Scalar>
36struct functor_traits<scalar_sum_op<Scalar> > {
37 enum {
40 };
41};
42
48template<> struct scalar_sum_op<bool> : scalar_sum_op<int> {
49 EIGEN_DEPRECATED
50 scalar_sum_op() {}
51};
52
53
59template<typename LhsScalar,typename RhsScalar> struct scalar_product_op {
60 enum {
61 // TODO vectorize mixed product
63 };
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};
74template<typename LhsScalar,typename RhsScalar>
75struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
76 enum {
79 };
80};
81
87template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op {
88
89 enum {
91 };
92
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
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};
103template<typename LhsScalar,typename RhsScalar>
110
116template<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};
126template<typename Scalar>
128 enum {
130 PacketAccess = packet_traits<Scalar>::HasMin
131 };
132};
133
139template<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};
149template<typename Scalar>
151 enum {
153 PacketAccess = packet_traits<Scalar>::HasMax
154 };
155};
156
161template<typename Scalar, ComparisonName cmp> struct scalar_cmp_op;
162
163template<typename Scalar, ComparisonName cmp>
165 enum {
167 PacketAccess = false
168 };
169};
170
171template<ComparisonName Cmp, typename Scalar>
172struct result_of<scalar_cmp_op<Scalar, Cmp>(Scalar,Scalar)> {
173 typedef bool type;
174};
175
176
177template<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};
182template<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};
187template<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};
192template<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};
197template<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};
202template<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};
207template<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
219template<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};
239template<typename Scalar>
241 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
242};
243
247template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
248 EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
250 inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return numext::pow(a, b); }
251};
252template<typename Scalar, typename OtherScalar>
254 enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
255};
256
257
258
259//---------- non associative binary functors ----------
260
266template<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};
273template<typename Scalar>
275 enum {
277 PacketAccess = packet_traits<Scalar>::HasSub
278 };
279};
280
286template<typename LhsScalar,typename RhsScalar> struct scalar_quotient_op {
287 enum {
288 // TODO vectorize mixed product
290 };
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};
298template<typename LhsScalar,typename RhsScalar>
299struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
300 enum {
303 };
304};
305
306
307
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};
318 enum {
320 PacketAccess = false
321 };
322};
323
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};
334 enum {
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 */
357template<typename Scalar>
359 // FIXME default copy constructors seems bugged with std::complex<>
361 EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
363 EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
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)); }
370};
371template<typename Scalar>
373{ enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
374
375template<typename Scalar1, typename Scalar2>
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; }
382};
383template<typename Scalar1,typename Scalar2>
385{ enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
386
395template<typename Scalar>
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)); }
405};
406template<typename Scalar>
408{ enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
409
410template<typename Scalar1, typename Scalar2>
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; }
417};
418template<typename Scalar1,typename 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
426template<typename Functor> struct functor_is_product_like { enum { ret = 0 }; };
427template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
428template<typename LhsScalar,typename RhsScalar> struct functor_is_product_like<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
429template<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 */
437template<typename Scalar>
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};
448template<typename Scalar>
450{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
451
456template<typename Scalar>
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};
466template<typename Scalar>
468{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
469
474template<typename Scalar>
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};
484template<typename Scalar>
486{ enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
487
492template<typename Scalar>
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) {}
498 inline Scalar operator() (const Scalar& a) const { return numext::pow(a, m_exponent); }
499 const Scalar m_exponent;
500};
501template<typename Scalar>
503{ enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
504
509template<typename Scalar>
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
Pseudo expression representing a solving operation.
Definition Solve.h:63
Holds information about the various numeric (i.e.
Definition NumTraits.h:108
Definition BinaryFunctors.h:426
Definition XprHelper.h:107
Definition Meta.h:39
Definition GenericPacketMath.h:90
Definition Meta.h:253
Definition BinaryFunctors.h:438
Definition BinaryFunctors.h:247
Definition BinaryFunctors.h:313
Definition BinaryFunctors.h:329
Definition BinaryFunctors.h:161
Definition BinaryFunctors.h:87
Definition BinaryFunctors.h:266
Definition BinaryFunctors.h:219
Definition BinaryFunctors.h:510
Definition BinaryFunctors.h:139
Definition BinaryFunctors.h:116
Definition BinaryFunctors.h:376
Definition BinaryFunctors.h:358
Definition BinaryFunctors.h:493
Definition BinaryFunctors.h:59
Definition BinaryFunctors.h:396
Definition BinaryFunctors.h:411
Definition BinaryFunctors.h:286
Definition BinaryFunctors.h:475
Definition BinaryFunctors.h:457
Definition BinaryFunctors.h:24