Eigen  5.0.1-dev+284dcc12
 
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
13// IWYU pragma: private
14#include "../InternalHeaderCheck.h"
15
16namespace Eigen {
17
18namespace internal {
19
20//---------- associative binary functors ----------
21
22template <typename Arg1, typename Arg2>
23struct binary_op_base {
24 typedef Arg1 first_argument_type;
25 typedef Arg2 second_argument_type;
26};
27
33template <typename LhsScalar, typename RhsScalar>
34struct scalar_sum_op : binary_op_base<LhsScalar, RhsScalar> {
35 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_sum_op>::ReturnType result_type;
36#ifdef EIGEN_SCALAR_BINARY_OP_PLUGIN
37 scalar_sum_op(){EIGEN_SCALAR_BINARY_OP_PLUGIN}
38#endif
39 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type
40 operator()(const LhsScalar& a, const RhsScalar& b) const {
41 return a + b;
42 }
43 template <typename Packet>
44 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
45 return internal::padd(a, b);
46 }
47 template <typename Packet>
48 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const {
49 return internal::predux(a);
50 }
51};
52template <typename LhsScalar, typename RhsScalar>
53struct functor_traits<scalar_sum_op<LhsScalar, RhsScalar>> {
54 enum {
55 Cost = (int(NumTraits<LhsScalar>::AddCost) + int(NumTraits<RhsScalar>::AddCost)) / 2, // rough estimate!
56 PacketAccess =
57 is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasAdd && packet_traits<RhsScalar>::HasAdd
58 // TODO vectorize mixed sum
59 };
60};
61
62template <>
63EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool scalar_sum_op<bool, bool>::operator()(const bool& a, const bool& b) const {
64 return a || b;
65}
66
72template <typename LhsScalar, typename RhsScalar>
73struct scalar_product_op : binary_op_base<LhsScalar, RhsScalar> {
74 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_product_op>::ReturnType result_type;
75#ifdef EIGEN_SCALAR_BINARY_OP_PLUGIN
76 scalar_product_op(){EIGEN_SCALAR_BINARY_OP_PLUGIN}
77#endif
78 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type
79 operator()(const LhsScalar& a, const RhsScalar& b) const {
80 return a * b;
81 }
82 template <typename Packet>
83 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
84 return internal::pmul(a, b);
85 }
86 template <typename Packet>
87 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const {
88 return internal::predux_mul(a);
89 }
90};
91template <typename LhsScalar, typename RhsScalar>
92struct functor_traits<scalar_product_op<LhsScalar, RhsScalar>> {
93 enum {
94 Cost = (int(NumTraits<LhsScalar>::MulCost) + int(NumTraits<RhsScalar>::MulCost)) / 2, // rough estimate!
95 PacketAccess =
96 is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
97 // TODO vectorize mixed product
98 };
99};
100
101template <>
102EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool scalar_product_op<bool, bool>::operator()(const bool& a,
103 const bool& b) const {
104 return a && b;
105}
106
113template <typename LhsScalar, typename RhsScalar>
114struct scalar_conj_product_op : binary_op_base<LhsScalar, RhsScalar> {
115 enum { Conj = NumTraits<LhsScalar>::IsComplex };
116
117 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_conj_product_op>::ReturnType result_type;
118
119 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
120 return conj_helper<LhsScalar, RhsScalar, Conj, false>().pmul(a, b);
121 }
122
123 template <typename Packet>
124 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
125 return conj_helper<Packet, Packet, Conj, false>().pmul(a, b);
126 }
127};
128template <typename LhsScalar, typename RhsScalar>
129struct functor_traits<scalar_conj_product_op<LhsScalar, RhsScalar>> {
130 enum {
131 Cost = NumTraits<LhsScalar>::MulCost,
132 PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
133 };
134};
135
141template <typename LhsScalar, typename RhsScalar, int NaNPropagation>
142struct scalar_min_op : binary_op_base<LhsScalar, RhsScalar> {
143 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_min_op>::ReturnType result_type;
144 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
145 return internal::pmin<NaNPropagation>(a, b);
146 }
147 template <typename Packet>
148 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
149 return internal::pmin<NaNPropagation>(a, b);
150 }
151 template <typename Packet>
152 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const {
153 return internal::predux_min<NaNPropagation>(a);
154 }
155};
156
157template <typename LhsScalar, typename RhsScalar, int NaNPropagation>
158struct functor_traits<scalar_min_op<LhsScalar, RhsScalar, NaNPropagation>> {
159 enum {
160 Cost = (NumTraits<LhsScalar>::AddCost + NumTraits<RhsScalar>::AddCost) / 2,
161 PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMin
162 };
163};
164
170template <typename LhsScalar, typename RhsScalar, int NaNPropagation>
171struct scalar_max_op : binary_op_base<LhsScalar, RhsScalar> {
172 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_max_op>::ReturnType result_type;
173 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
174 return internal::pmax<NaNPropagation>(a, b);
175 }
176 template <typename Packet>
177 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
178 return internal::pmax<NaNPropagation>(a, b);
179 }
180 template <typename Packet>
181 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const {
182 return internal::predux_max<NaNPropagation>(a);
183 }
184};
185
186template <typename LhsScalar, typename RhsScalar, int NaNPropagation>
187struct functor_traits<scalar_max_op<LhsScalar, RhsScalar, NaNPropagation>> {
188 enum {
189 Cost = (NumTraits<LhsScalar>::AddCost + NumTraits<RhsScalar>::AddCost) / 2,
190 PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMax
191 };
192};
193
198template <typename LhsScalar, typename RhsScalar, ComparisonName cmp, bool UseTypedComparators = false>
199struct scalar_cmp_op;
200
201template <typename LhsScalar, typename RhsScalar, ComparisonName cmp, bool UseTypedComparators>
202struct functor_traits<scalar_cmp_op<LhsScalar, RhsScalar, cmp, UseTypedComparators>> {
203 enum {
204 Cost = (NumTraits<LhsScalar>::AddCost + NumTraits<RhsScalar>::AddCost) / 2,
205 PacketAccess = (UseTypedComparators || is_same<LhsScalar, bool>::value) && is_same<LhsScalar, RhsScalar>::value &&
206 packet_traits<LhsScalar>::HasCmp
207 };
208};
209
210template <typename LhsScalar, typename RhsScalar, bool UseTypedComparators>
211struct scalar_cmp_op<LhsScalar, RhsScalar, cmp_EQ, UseTypedComparators> : binary_op_base<LhsScalar, RhsScalar> {
212 using result_type = std::conditional_t<UseTypedComparators, LhsScalar, bool>;
213 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
214 return a == b ? result_type(1) : result_type(0);
215 }
216 template <typename Packet>
217 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
218 const Packet cst_one = pset1<Packet>(result_type(1));
219 return pand(pcmp_eq(a, b), cst_one);
220 }
221};
222
223template <typename LhsScalar, typename RhsScalar, bool UseTypedComparators>
224struct scalar_cmp_op<LhsScalar, RhsScalar, cmp_LT, UseTypedComparators> : binary_op_base<LhsScalar, RhsScalar> {
225 using result_type = std::conditional_t<UseTypedComparators, LhsScalar, bool>;
226 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
227 return a < b ? result_type(1) : result_type(0);
228 }
229 template <typename Packet>
230 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
231 const Packet cst_one = pset1<Packet>(result_type(1));
232 return pand(pcmp_lt(a, b), cst_one);
233 }
234};
235
236template <typename LhsScalar, typename RhsScalar, bool UseTypedComparators>
237struct scalar_cmp_op<LhsScalar, RhsScalar, cmp_LE, UseTypedComparators> : binary_op_base<LhsScalar, RhsScalar> {
238 using result_type = std::conditional_t<UseTypedComparators, LhsScalar, bool>;
239 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
240 return a <= b ? result_type(1) : result_type(0);
241 }
242 template <typename Packet>
243 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
244 const Packet cst_one = pset1<Packet>(result_type(1));
245 return pand(cst_one, pcmp_le(a, b));
246 }
247};
248
249template <typename LhsScalar, typename RhsScalar, bool UseTypedComparators>
250struct scalar_cmp_op<LhsScalar, RhsScalar, cmp_GT, UseTypedComparators> : binary_op_base<LhsScalar, RhsScalar> {
251 using result_type = std::conditional_t<UseTypedComparators, LhsScalar, bool>;
252 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
253 return a > b ? result_type(1) : result_type(0);
254 }
255 template <typename Packet>
256 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
257 const Packet cst_one = pset1<Packet>(result_type(1));
258 return pand(cst_one, pcmp_lt(b, a));
259 }
260};
261
262template <typename LhsScalar, typename RhsScalar, bool UseTypedComparators>
263struct scalar_cmp_op<LhsScalar, RhsScalar, cmp_GE, UseTypedComparators> : binary_op_base<LhsScalar, RhsScalar> {
264 using result_type = std::conditional_t<UseTypedComparators, LhsScalar, bool>;
265 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
266 return a >= b ? result_type(1) : result_type(0);
267 }
268 template <typename Packet>
269 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
270 const Packet cst_one = pset1<Packet>(result_type(1));
271 return pand(cst_one, pcmp_le(b, a));
272 }
273};
274
275template <typename LhsScalar, typename RhsScalar, bool UseTypedComparators>
276struct scalar_cmp_op<LhsScalar, RhsScalar, cmp_UNORD, UseTypedComparators> : binary_op_base<LhsScalar, RhsScalar> {
277 using result_type = std::conditional_t<UseTypedComparators, LhsScalar, bool>;
278 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
279 return !(a <= b || b <= a) ? result_type(1) : result_type(0);
280 }
281 template <typename Packet>
282 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
283 const Packet cst_one = pset1<Packet>(result_type(1));
284 return pandnot(cst_one, por(pcmp_le(a, b), pcmp_le(b, a)));
285 }
286};
287
288template <typename LhsScalar, typename RhsScalar, bool UseTypedComparators>
289struct scalar_cmp_op<LhsScalar, RhsScalar, cmp_NEQ, UseTypedComparators> : binary_op_base<LhsScalar, RhsScalar> {
290 using result_type = std::conditional_t<UseTypedComparators, LhsScalar, bool>;
291 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {
292 return a != b ? result_type(1) : result_type(0);
293 }
294 template <typename Packet>
295 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
296 const Packet cst_one = pset1<Packet>(result_type(1));
297 return pandnot(cst_one, pcmp_eq(a, b));
298 }
299};
300
306template <typename Scalar>
307struct scalar_hypot_op<Scalar, Scalar> : binary_op_base<Scalar, Scalar> {
308 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& x, const Scalar& y) const {
309 // This functor is used by hypotNorm only for which it is faster to first apply abs
310 // on all coefficients prior to reduction through hypot.
311 // This way we avoid calling abs on positive and real entries, and this also permits
312 // to seamlessly handle complexes. Otherwise we would have to handle both real and complexes
313 // through the same functor...
314 return internal::positive_real_hypot(x, y);
315 }
316};
317template <typename Scalar>
318struct functor_traits<scalar_hypot_op<Scalar, Scalar>> {
319 enum {
320 Cost = 3 * NumTraits<Scalar>::AddCost + 2 * NumTraits<Scalar>::MulCost + 2 * scalar_div_cost<Scalar, false>::value,
321 PacketAccess = false
322 };
323};
324
329template <typename Scalar, typename Exponent>
330struct scalar_pow_op : binary_op_base<Scalar, Exponent> {
331 typedef typename ScalarBinaryOpTraits<Scalar, Exponent, scalar_pow_op>::ReturnType result_type;
332#ifdef EIGEN_SCALAR_BINARY_OP_PLUGIN
333 scalar_pow_op() {
334 typedef Scalar LhsScalar;
335 typedef Exponent RhsScalar;
336 EIGEN_SCALAR_BINARY_OP_PLUGIN
337 }
338#endif
339
340 EIGEN_DEVICE_FUNC inline result_type operator()(const Scalar& a, const Exponent& b) const {
341 return numext::pow(a, b);
342 }
343
344 template <typename Packet>
345 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const {
346 return generic_pow(a, b);
347 }
348};
349
350template <typename Scalar, typename Exponent>
351struct functor_traits<scalar_pow_op<Scalar, Exponent>> {
352 enum {
353 Cost = 5 * NumTraits<Scalar>::MulCost,
354 PacketAccess = (!NumTraits<Scalar>::IsComplex && !NumTraits<Scalar>::IsInteger && packet_traits<Scalar>::HasPow)
355 };
356};
357
358//---------- non associative binary functors ----------
359
365template <typename LhsScalar, typename RhsScalar>
366struct scalar_difference_op : binary_op_base<LhsScalar, RhsScalar> {
367 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_difference_op>::ReturnType result_type;
368#ifdef EIGEN_SCALAR_BINARY_OP_PLUGIN
369 scalar_difference_op(){EIGEN_SCALAR_BINARY_OP_PLUGIN}
370#endif
371 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type
372 operator()(const LhsScalar& a, const RhsScalar& b) const {
373 return a - b;
374 }
375 template <typename Packet>
376 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const {
377 return internal::psub(a, b);
378 }
379};
380template <typename LhsScalar, typename RhsScalar>
381struct functor_traits<scalar_difference_op<LhsScalar, RhsScalar>> {
382 enum {
383 Cost = (int(NumTraits<LhsScalar>::AddCost) + int(NumTraits<RhsScalar>::AddCost)) / 2,
384 PacketAccess =
385 is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasSub && packet_traits<RhsScalar>::HasSub
386 };
387};
388
389template <typename Packet, bool IsInteger = NumTraits<typename unpacket_traits<Packet>::type>::IsInteger>
390struct maybe_raise_div_by_zero {
391 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Packet x) { EIGEN_UNUSED_VARIABLE(x); }
392};
393
394#ifndef EIGEN_GPU_COMPILE_PHASE
395template <typename Packet>
396struct maybe_raise_div_by_zero<Packet, true> {
397 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Packet x) {
398 if (EIGEN_PREDICT_FALSE(predux_any(pcmp_eq(x, pzero(x))))) {
399 // Use volatile variables to force a division by zero, which will
400 // result in the default platform behaviour (usually SIGFPE).
401 volatile typename unpacket_traits<Packet>::type zero = 0;
402 volatile typename unpacket_traits<Packet>::type val = 1;
403 val = val / zero;
404 }
405 }
406};
407#endif
408
414template <typename LhsScalar, typename RhsScalar>
415struct scalar_quotient_op : binary_op_base<LhsScalar, RhsScalar> {
416 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_quotient_op>::ReturnType result_type;
417#ifdef EIGEN_SCALAR_BINARY_OP_PLUGIN
418 scalar_quotient_op(){EIGEN_SCALAR_BINARY_OP_PLUGIN}
419#endif
420 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type
421 operator()(const LhsScalar& a, const RhsScalar& b) const {
422 return a / b;
423 }
424 template <typename Packet>
425 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const {
426 return internal::pdiv(a, b);
427 }
428};
429template <typename LhsScalar, typename RhsScalar>
430struct functor_traits<scalar_quotient_op<LhsScalar, RhsScalar>> {
431 typedef typename scalar_quotient_op<LhsScalar, RhsScalar>::result_type result_type;
432 enum {
433 PacketAccess =
434 is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv,
435 Cost = scalar_div_cost<result_type, PacketAccess>::value
436 };
437};
438
444template <typename Scalar>
445struct scalar_boolean_and_op {
446 using result_type = Scalar;
447 // `false` any value `a` that satisfies `a == Scalar(0)`
448 // `true` is the complement of `false`
449 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
450 return (a != Scalar(0)) && (b != Scalar(0)) ? Scalar(1) : Scalar(0);
451 }
452 template <typename Packet>
453 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
454 const Packet cst_one = pset1<Packet>(Scalar(1));
455 // and(a,b) == !or(!a,!b)
456 Packet not_a = pcmp_eq(a, pzero(a));
457 Packet not_b = pcmp_eq(b, pzero(b));
458 Packet a_nand_b = por(not_a, not_b);
459 return pandnot(cst_one, a_nand_b);
460 }
461};
462template <typename Scalar>
463struct functor_traits<scalar_boolean_and_op<Scalar>> {
464 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
465};
466
472template <typename Scalar>
473struct scalar_boolean_or_op {
474 using result_type = Scalar;
475 // `false` any value `a` that satisfies `a == Scalar(0)`
476 // `true` is the complement of `false`
477 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
478 return (a != Scalar(0)) || (b != Scalar(0)) ? Scalar(1) : Scalar(0);
479 }
480 template <typename Packet>
481 EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
482 const Packet cst_one = pset1<Packet>(Scalar(1));
483 // if or(a,b) == 0, then a == 0 and b == 0
484 // or(a,b) == !nor(a,b)
485 Packet a_nor_b = pcmp_eq(por(a, b), pzero(a));
486 return pandnot(cst_one, a_nor_b);
487 }
488};
489template <typename Scalar>
490struct functor_traits<scalar_boolean_or_op<Scalar>> {
491 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
492};
493
499template <typename Scalar>
500struct scalar_boolean_xor_op {
501 using result_type = Scalar;
502 // `false` any value `a` that satisfies `a == Scalar(0)`
503 // `true` is the complement of `false`
504 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
505 return (a != Scalar(0)) != (b != Scalar(0)) ? Scalar(1) : Scalar(0);
506 }
507 template <typename Packet>
508 EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
509 const Packet cst_one = pset1<Packet>(Scalar(1));
510 // xor(a,b) == xor(!a,!b)
511 Packet not_a = pcmp_eq(a, pzero(a));
512 Packet not_b = pcmp_eq(b, pzero(b));
513 Packet a_xor_b = pxor(not_a, not_b);
514 return pand(cst_one, a_xor_b);
515 }
516};
517template <typename Scalar>
518struct functor_traits<scalar_boolean_xor_op<Scalar>> {
519 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
520};
521
522template <typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex>
523struct bitwise_binary_impl {
524 static constexpr size_t Size = sizeof(Scalar);
525 using uint_t = typename numext::get_integer_by_size<Size>::unsigned_type;
526 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_and(const Scalar& a, const Scalar& b) {
527 uint_t a_as_uint = numext::bit_cast<uint_t, Scalar>(a);
528 uint_t b_as_uint = numext::bit_cast<uint_t, Scalar>(b);
529 uint_t result = a_as_uint & b_as_uint;
530 return numext::bit_cast<Scalar, uint_t>(result);
531 }
532 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_or(const Scalar& a, const Scalar& b) {
533 uint_t a_as_uint = numext::bit_cast<uint_t, Scalar>(a);
534 uint_t b_as_uint = numext::bit_cast<uint_t, Scalar>(b);
535 uint_t result = a_as_uint | b_as_uint;
536 return numext::bit_cast<Scalar, uint_t>(result);
537 }
538 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_xor(const Scalar& a, const Scalar& b) {
539 uint_t a_as_uint = numext::bit_cast<uint_t, Scalar>(a);
540 uint_t b_as_uint = numext::bit_cast<uint_t, Scalar>(b);
541 uint_t result = a_as_uint ^ b_as_uint;
542 return numext::bit_cast<Scalar, uint_t>(result);
543 }
544};
545
546template <typename Scalar>
547struct bitwise_binary_impl<Scalar, true> {
548 using Real = typename NumTraits<Scalar>::Real;
549 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_and(const Scalar& a, const Scalar& b) {
550 Real real_result = bitwise_binary_impl<Real>::run_and(numext::real(a), numext::real(b));
551 Real imag_result = bitwise_binary_impl<Real>::run_and(numext::imag(a), numext::imag(b));
552 return Scalar(real_result, imag_result);
553 }
554 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_or(const Scalar& a, const Scalar& b) {
555 Real real_result = bitwise_binary_impl<Real>::run_or(numext::real(a), numext::real(b));
556 Real imag_result = bitwise_binary_impl<Real>::run_or(numext::imag(a), numext::imag(b));
557 return Scalar(real_result, imag_result);
558 }
559 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar run_xor(const Scalar& a, const Scalar& b) {
560 Real real_result = bitwise_binary_impl<Real>::run_xor(numext::real(a), numext::real(b));
561 Real imag_result = bitwise_binary_impl<Real>::run_xor(numext::imag(a), numext::imag(b));
562 return Scalar(real_result, imag_result);
563 }
564};
565
571template <typename Scalar>
572struct scalar_bitwise_and_op {
573 EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization,
574 BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES)
575 EIGEN_STATIC_ASSERT((!internal::is_same<Scalar, bool>::value), DONT USE BITWISE OPS ON BOOLEAN TYPES)
576 using result_type = Scalar;
577 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
578 return bitwise_binary_impl<Scalar>::run_and(a, b);
579 }
580 template <typename Packet>
581 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
582 return pand(a, b);
583 }
584};
585template <typename Scalar>
586struct functor_traits<scalar_bitwise_and_op<Scalar>> {
587 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
588};
589
595template <typename Scalar>
596struct scalar_bitwise_or_op {
597 EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization,
598 BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES)
599 EIGEN_STATIC_ASSERT((!internal::is_same<Scalar, bool>::value), DONT USE BITWISE OPS ON BOOLEAN TYPES)
600 using result_type = Scalar;
601 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
602 return bitwise_binary_impl<Scalar>::run_or(a, b);
603 }
604 template <typename Packet>
605 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
606 return por(a, b);
607 }
608};
609template <typename Scalar>
610struct functor_traits<scalar_bitwise_or_op<Scalar>> {
611 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
612};
613
619template <typename Scalar>
620struct scalar_bitwise_xor_op {
621 EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization,
622 BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES)
623 EIGEN_STATIC_ASSERT((!internal::is_same<Scalar, bool>::value), DONT USE BITWISE OPS ON BOOLEAN TYPES)
624 using result_type = Scalar;
625 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
626 return bitwise_binary_impl<Scalar>::run_xor(a, b);
627 }
628 template <typename Packet>
629 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
630 return pxor(a, b);
631 }
632};
633template <typename Scalar>
634struct functor_traits<scalar_bitwise_xor_op<Scalar>> {
635 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
636};
637
643template <typename LhsScalar, typename RhsScalar>
644struct scalar_absolute_difference_op : binary_op_base<LhsScalar, RhsScalar> {
645 typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar, scalar_absolute_difference_op>::ReturnType result_type;
646#ifdef EIGEN_SCALAR_BINARY_OP_PLUGIN
647 scalar_absolute_difference_op(){EIGEN_SCALAR_BINARY_OP_PLUGIN}
648#endif
649 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type
650 operator()(const LhsScalar& a, const RhsScalar& b) const {
651 return numext::absdiff(a, b);
652 }
653 template <typename Packet>
654 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const {
655 return internal::pabsdiff(a, b);
656 }
657};
658template <typename LhsScalar, typename RhsScalar>
659struct functor_traits<scalar_absolute_difference_op<LhsScalar, RhsScalar>> {
660 enum {
661 Cost = (NumTraits<LhsScalar>::AddCost + NumTraits<RhsScalar>::AddCost) / 2,
662 PacketAccess = is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasAbsDiff
663 };
664};
665
666template <typename LhsScalar, typename RhsScalar>
667struct scalar_atan2_op {
668 using Scalar = LhsScalar;
669
670 static constexpr bool Enable =
671 is_same<LhsScalar, RhsScalar>::value && !NumTraits<Scalar>::IsInteger && !NumTraits<Scalar>::IsComplex;
672 EIGEN_STATIC_ASSERT(Enable, "LhsScalar and RhsScalar must be the same non-integer, non-complex type")
673
674 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& y, const Scalar& x) const {
675 return numext::atan2(y, x);
676 }
677 template <typename Packet>
678 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& y, const Packet& x) const {
679 return internal::patan2(y, x);
680 }
681};
682
683template <typename LhsScalar, typename RhsScalar>
684struct functor_traits<scalar_atan2_op<LhsScalar, RhsScalar>> {
685 using Scalar = LhsScalar;
686 enum {
687 PacketAccess = is_same<LhsScalar, RhsScalar>::value && packet_traits<Scalar>::HasATan &&
688 packet_traits<Scalar>::HasDiv && !NumTraits<Scalar>::IsInteger && !NumTraits<Scalar>::IsComplex,
689 Cost = int(scalar_div_cost<Scalar, PacketAccess>::value) + int(functor_traits<scalar_atan_op<Scalar>>::Cost)
690 };
691};
692
693//---------- binary functors bound to a constant, thus appearing as a unary functor ----------
694
695// The following two classes permits to turn any binary functor into a unary one with one argument bound to a constant
696// value. They are analogues to std::binder1st/binder2nd but with the following differences:
697// - they are compatible with packetOp
698// - they are portable across C++ versions (the std::binder* are deprecated in C++11)
699template <typename BinaryOp>
700struct bind1st_op : BinaryOp {
701 typedef typename BinaryOp::first_argument_type first_argument_type;
702 typedef typename BinaryOp::second_argument_type second_argument_type;
703 typedef typename BinaryOp::result_type result_type;
704
705 EIGEN_DEVICE_FUNC explicit bind1st_op(const first_argument_type& val) : m_value(val) {}
706
707 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator()(const second_argument_type& b) const {
708 return BinaryOp::operator()(m_value, b);
709 }
710
711 template <typename Packet>
712 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& b) const {
713 return BinaryOp::packetOp(internal::pset1<Packet>(m_value), b);
714 }
715
716 first_argument_type m_value;
717};
718template <typename BinaryOp>
719struct functor_traits<bind1st_op<BinaryOp>> : functor_traits<BinaryOp> {};
720
721template <typename BinaryOp>
722struct bind2nd_op : BinaryOp {
723 typedef typename BinaryOp::first_argument_type first_argument_type;
724 typedef typename BinaryOp::second_argument_type second_argument_type;
725 typedef typename BinaryOp::result_type result_type;
726
727 EIGEN_DEVICE_FUNC explicit bind2nd_op(const second_argument_type& val) : m_value(val) {}
728
729 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator()(const first_argument_type& a) const {
730 return BinaryOp::operator()(a, m_value);
731 }
732
733 template <typename Packet>
734 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const {
735 return BinaryOp::packetOp(a, internal::pset1<Packet>(m_value));
736 }
737
738 second_argument_type m_value;
739};
740template <typename BinaryOp>
741struct functor_traits<bind2nd_op<BinaryOp>> : functor_traits<BinaryOp> {};
742
743} // end namespace internal
744
745} // end namespace Eigen
746
747#endif // EIGEN_BINARY_FUNCTORS_H
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1