Branch data Line data Source code
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 : 82498 : EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
37 : : #else
38 : : scalar_sum_op() {
39 : : EIGEN_SCALAR_BINARY_OP_PLUGIN
40 : : }
41 : : #endif
42 : 26708 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a + b; }
43 : : template<typename Packet>
44 : 28956 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
45 : 28956 : { return internal::padd(a,b); }
46 : : template<typename Packet>
47 : 21036 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
48 : 21036 : { return internal::predux(a); }
49 : : };
50 : : template<typename LhsScalar,typename RhsScalar>
51 : : struct functor_traits<scalar_sum_op<LhsScalar,RhsScalar> > {
52 : : enum {
53 : : Cost = (int(NumTraits<LhsScalar>::AddCost) + int(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 : :
60 : : template<>
61 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool scalar_sum_op<bool,bool>::operator() (const bool& a, const bool& b) const { return a || b; }
62 : :
63 : :
64 : : /** \internal
65 : : * \brief Template functor to compute the product of two scalars
66 : : *
67 : : * \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
68 : : */
69 : : template<typename LhsScalar,typename RhsScalar>
70 : : struct scalar_product_op : binary_op_base<LhsScalar,RhsScalar>
71 : : {
72 : : typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_product_op>::ReturnType result_type;
73 : : #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
74 : 111224 : EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
75 : : #else
76 : : scalar_product_op() {
77 : : EIGEN_SCALAR_BINARY_OP_PLUGIN
78 : : }
79 : : #endif
80 : 37456 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
81 : : template<typename Packet>
82 : 22890 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
83 : 22890 : { return internal::pmul(a,b); }
84 : : template<typename Packet>
85 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
86 : : { return internal::predux_mul(a); }
87 : : };
88 : : template<typename LhsScalar,typename RhsScalar>
89 : : struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
90 : : enum {
91 : : Cost = (int(NumTraits<LhsScalar>::MulCost) + int(NumTraits<RhsScalar>::MulCost))/2, // rough estimate!
92 : : PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
93 : : // TODO vectorize mixed product
94 : : };
95 : : };
96 : :
97 : : template<>
98 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool scalar_product_op<bool,bool>::operator() (const bool& a, const bool& b) const { return a && b; }
99 : :
100 : :
101 : : /** \internal
102 : : * \brief Template functor to compute the conjugate product of two scalars
103 : : *
104 : : * This is a short cut for conj(x) * y which is needed for optimization purpose; in Eigen2 support mode, this becomes x * conj(y)
105 : : */
106 : : template<typename LhsScalar,typename RhsScalar>
107 : : struct scalar_conj_product_op : binary_op_base<LhsScalar,RhsScalar>
108 : : {
109 : :
110 : : enum {
111 : : Conj = NumTraits<LhsScalar>::IsComplex
112 : : };
113 : :
114 : : typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_conj_product_op>::ReturnType result_type;
115 : :
116 : 18 : EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
117 : 2 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const
118 : 2 : { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
119 : :
120 : : template<typename Packet>
121 : 6 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
122 : 6 : { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
123 : : };
124 : : template<typename LhsScalar,typename RhsScalar>
125 : : struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
126 : : enum {
127 : : Cost = NumTraits<LhsScalar>::MulCost,
128 : : PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
129 : : };
130 : : };
131 : :
132 : : /** \internal
133 : : * \brief Template functor to compute the min of two scalars
134 : : *
135 : : * \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
136 : : */
137 : : template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
138 : : struct scalar_min_op : binary_op_base<LhsScalar,RhsScalar>
139 : : {
140 : : typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_min_op>::ReturnType result_type;
141 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
142 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const {
143 : : return internal::pmin<NaNPropagation>(a, b);
144 : : }
145 : : template<typename Packet>
146 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
147 : : {
148 : : return internal::pmin<NaNPropagation>(a,b);
149 : : }
150 : : template<typename Packet>
151 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
152 : : {
153 : : return internal::predux_min<NaNPropagation>(a);
154 : : }
155 : : };
156 : :
157 : : template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
158 : : struct 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 : :
165 : : /** \internal
166 : : * \brief Template functor to compute the max of two scalars
167 : : *
168 : : * \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
169 : : */
170 : : template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
171 : : struct scalar_max_op : binary_op_base<LhsScalar,RhsScalar>
172 : : {
173 : : typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_max_op>::ReturnType result_type;
174 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
175 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const {
176 : : return internal::pmax<NaNPropagation>(a,b);
177 : : }
178 : : template<typename Packet>
179 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
180 : : {
181 : : return internal::pmax<NaNPropagation>(a,b);
182 : : }
183 : : template<typename Packet>
184 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type predux(const Packet& a) const
185 : : {
186 : : return internal::predux_max<NaNPropagation>(a);
187 : : }
188 : : };
189 : :
190 : : template<typename LhsScalar,typename RhsScalar, int NaNPropagation>
191 : : struct functor_traits<scalar_max_op<LhsScalar,RhsScalar, NaNPropagation> > {
192 : : enum {
193 : : Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
194 : : PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMax
195 : : };
196 : : };
197 : :
198 : : /** \internal
199 : : * \brief Template functors for comparison of two scalars
200 : : * \todo Implement packet-comparisons
201 : : */
202 : : template<typename LhsScalar, typename RhsScalar, ComparisonName cmp> struct scalar_cmp_op;
203 : :
204 : : template<typename LhsScalar, typename RhsScalar, ComparisonName cmp>
205 : : struct functor_traits<scalar_cmp_op<LhsScalar,RhsScalar, cmp> > {
206 : : enum {
207 : : Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
208 : : PacketAccess = false
209 : : };
210 : : };
211 : :
212 : : template<ComparisonName Cmp, typename LhsScalar, typename RhsScalar>
213 : : struct result_of<scalar_cmp_op<LhsScalar, RhsScalar, Cmp>(LhsScalar,RhsScalar)> {
214 : : typedef bool type;
215 : : };
216 : :
217 : :
218 : : template<typename LhsScalar, typename RhsScalar>
219 : : struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_EQ> : binary_op_base<LhsScalar,RhsScalar>
220 : : {
221 : : typedef bool result_type;
222 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
223 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a==b;}
224 : : };
225 : : template<typename LhsScalar, typename RhsScalar>
226 : : struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LT> : binary_op_base<LhsScalar,RhsScalar>
227 : : {
228 : : typedef bool result_type;
229 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
230 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<b;}
231 : : };
232 : : template<typename LhsScalar, typename RhsScalar>
233 : : struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_LE> : binary_op_base<LhsScalar,RhsScalar>
234 : : {
235 : : typedef bool result_type;
236 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
237 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a<=b;}
238 : : };
239 : : template<typename LhsScalar, typename RhsScalar>
240 : : struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GT> : binary_op_base<LhsScalar,RhsScalar>
241 : : {
242 : : typedef bool result_type;
243 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
244 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>b;}
245 : : };
246 : : template<typename LhsScalar, typename RhsScalar>
247 : : struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_GE> : binary_op_base<LhsScalar,RhsScalar>
248 : : {
249 : : typedef bool result_type;
250 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
251 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a>=b;}
252 : : };
253 : : template<typename LhsScalar, typename RhsScalar>
254 : : struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_UNORD> : binary_op_base<LhsScalar,RhsScalar>
255 : : {
256 : : typedef bool result_type;
257 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
258 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return !(a<=b || b<=a);}
259 : : };
260 : : template<typename LhsScalar, typename RhsScalar>
261 : : struct scalar_cmp_op<LhsScalar,RhsScalar, cmp_NEQ> : binary_op_base<LhsScalar,RhsScalar>
262 : : {
263 : : typedef bool result_type;
264 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_cmp_op)
265 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator()(const LhsScalar& a, const RhsScalar& b) const {return a!=b;}
266 : : };
267 : :
268 : : /** \internal
269 : : * \brief Template functor to compute the hypot of two \b positive \b and \b real scalars
270 : : *
271 : : * \sa MatrixBase::stableNorm(), class Redux
272 : : */
273 : : template<typename Scalar>
274 : : struct scalar_hypot_op<Scalar,Scalar> : binary_op_base<Scalar,Scalar>
275 : : {
276 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
277 : :
278 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar &x, const Scalar &y) const
279 : : {
280 : : // This functor is used by hypotNorm only for which it is faster to first apply abs
281 : : // on all coefficients prior to reduction through hypot.
282 : : // This way we avoid calling abs on positive and real entries, and this also permits
283 : : // to seamlessly handle complexes. Otherwise we would have to handle both real and complexes
284 : : // through the same functor...
285 : : return internal::positive_real_hypot(x,y);
286 : : }
287 : : };
288 : : template<typename Scalar>
289 : : struct functor_traits<scalar_hypot_op<Scalar,Scalar> > {
290 : : enum
291 : : {
292 : : Cost = 3 * NumTraits<Scalar>::AddCost +
293 : : 2 * NumTraits<Scalar>::MulCost +
294 : : 2 * scalar_div_cost<Scalar,false>::value,
295 : : PacketAccess = false
296 : : };
297 : : };
298 : :
299 : : /** \internal
300 : : * \brief Template functor to compute the pow of two scalars
301 : : * See the specification of pow in https://en.cppreference.com/w/cpp/numeric/math/pow
302 : : */
303 : : template<typename Scalar, typename Exponent>
304 : : struct scalar_pow_op : binary_op_base<Scalar,Exponent>
305 : : {
306 : : typedef typename ScalarBinaryOpTraits<Scalar,Exponent,scalar_pow_op>::ReturnType result_type;
307 : : #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
308 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_pow_op)
309 : : #else
310 : : scalar_pow_op() {
311 : : typedef Scalar LhsScalar;
312 : : typedef Exponent RhsScalar;
313 : : EIGEN_SCALAR_BINARY_OP_PLUGIN
314 : : }
315 : : #endif
316 : :
317 : : EIGEN_DEVICE_FUNC
318 : : inline result_type operator() (const Scalar& a, const Exponent& b) const { return numext::pow(a, b); }
319 : :
320 : : template<typename Packet>
321 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
322 : : {
323 : : return generic_pow(a,b);
324 : : }
325 : : };
326 : :
327 : : template<typename Scalar, typename Exponent>
328 : : struct functor_traits<scalar_pow_op<Scalar,Exponent> > {
329 : : enum {
330 : : Cost = 5 * NumTraits<Scalar>::MulCost,
331 : : PacketAccess = (!NumTraits<Scalar>::IsComplex && !NumTraits<Scalar>::IsInteger &&
332 : : packet_traits<Scalar>::HasExp && packet_traits<Scalar>::HasLog &&
333 : : packet_traits<Scalar>::HasRound && packet_traits<Scalar>::HasCmp &&
334 : : // Temporarly disable packet access for half/bfloat16 until
335 : : // accuracy is improved.
336 : : !is_same<Scalar, half>::value && !is_same<Scalar, bfloat16>::value
337 : : )
338 : : };
339 : : };
340 : :
341 : : //---------- non associative binary functors ----------
342 : :
343 : : /** \internal
344 : : * \brief Template functor to compute the difference of two scalars
345 : : *
346 : : * \sa class CwiseBinaryOp, MatrixBase::operator-
347 : : */
348 : : template<typename LhsScalar,typename RhsScalar>
349 : : struct scalar_difference_op : binary_op_base<LhsScalar,RhsScalar>
350 : : {
351 : : typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_difference_op>::ReturnType result_type;
352 : : #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
353 : 33816 : EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
354 : : #else
355 : : scalar_difference_op() {
356 : : EIGEN_SCALAR_BINARY_OP_PLUGIN
357 : : }
358 : : #endif
359 : 10126 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a - b; }
360 : : template<typename Packet>
361 : 8150 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
362 : 8150 : { return internal::psub(a,b); }
363 : : };
364 : : template<typename LhsScalar,typename RhsScalar>
365 : : struct functor_traits<scalar_difference_op<LhsScalar,RhsScalar> > {
366 : : enum {
367 : : Cost = (int(NumTraits<LhsScalar>::AddCost) + int(NumTraits<RhsScalar>::AddCost)) / 2,
368 : : PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasSub && packet_traits<RhsScalar>::HasSub
369 : : };
370 : : };
371 : :
372 : : /** \internal
373 : : * \brief Template functor to compute the quotient of two scalars
374 : : *
375 : : * \sa class CwiseBinaryOp, Cwise::operator/()
376 : : */
377 : : template<typename LhsScalar,typename RhsScalar>
378 : : struct scalar_quotient_op : binary_op_base<LhsScalar,RhsScalar>
379 : : {
380 : : typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_quotient_op>::ReturnType result_type;
381 : : #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
382 : 11742 : EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
383 : : #else
384 : : scalar_quotient_op() {
385 : : EIGEN_SCALAR_BINARY_OP_PLUGIN
386 : : }
387 : : #endif
388 : 3913 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a / b; }
389 : : template<typename Packet>
390 : 3915 : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
391 : 3915 : { return internal::pdiv(a,b); }
392 : : };
393 : : template<typename LhsScalar,typename RhsScalar>
394 : : struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
395 : : typedef typename scalar_quotient_op<LhsScalar,RhsScalar>::result_type result_type;
396 : : enum {
397 : : PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasDiv && packet_traits<RhsScalar>::HasDiv,
398 : : Cost = scalar_div_cost<result_type,PacketAccess>::value
399 : : };
400 : : };
401 : :
402 : :
403 : :
404 : : /** \internal
405 : : * \brief Template functor to compute the and of two booleans
406 : : *
407 : : * \sa class CwiseBinaryOp, ArrayBase::operator&&
408 : : */
409 : : struct scalar_boolean_and_op {
410 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
411 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
412 : : template<typename Packet>
413 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
414 : : { return internal::pand(a,b); }
415 : : };
416 : : template<> struct functor_traits<scalar_boolean_and_op> {
417 : : enum {
418 : : Cost = NumTraits<bool>::AddCost,
419 : : PacketAccess = true
420 : : };
421 : : };
422 : :
423 : : /** \internal
424 : : * \brief Template functor to compute the or of two booleans
425 : : *
426 : : * \sa class CwiseBinaryOp, ArrayBase::operator||
427 : : */
428 : : struct scalar_boolean_or_op {
429 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
430 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
431 : : template<typename Packet>
432 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
433 : : { return internal::por(a,b); }
434 : : };
435 : : template<> struct functor_traits<scalar_boolean_or_op> {
436 : : enum {
437 : : Cost = NumTraits<bool>::AddCost,
438 : : PacketAccess = true
439 : : };
440 : : };
441 : :
442 : : /** \internal
443 : : * \brief Template functor to compute the xor of two booleans
444 : : *
445 : : * \sa class CwiseBinaryOp, ArrayBase::operator^
446 : : */
447 : : struct scalar_boolean_xor_op {
448 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_xor_op)
449 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a ^ b; }
450 : : template<typename Packet>
451 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
452 : : { return internal::pxor(a,b); }
453 : : };
454 : : template<> struct functor_traits<scalar_boolean_xor_op> {
455 : : enum {
456 : : Cost = NumTraits<bool>::AddCost,
457 : : PacketAccess = true
458 : : };
459 : : };
460 : :
461 : : /** \internal
462 : : * \brief Template functor to compute the absolute difference of two scalars
463 : : *
464 : : * \sa class CwiseBinaryOp, MatrixBase::absolute_difference
465 : : */
466 : : template<typename LhsScalar,typename RhsScalar>
467 : : struct scalar_absolute_difference_op : binary_op_base<LhsScalar,RhsScalar>
468 : : {
469 : : typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_absolute_difference_op>::ReturnType result_type;
470 : : #ifndef EIGEN_SCALAR_BINARY_OP_PLUGIN
471 : : EIGEN_EMPTY_STRUCT_CTOR(scalar_absolute_difference_op)
472 : : #else
473 : : scalar_absolute_difference_op() {
474 : : EIGEN_SCALAR_BINARY_OP_PLUGIN
475 : : }
476 : : #endif
477 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
478 : : { return numext::absdiff(a,b); }
479 : : template<typename Packet>
480 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
481 : : { return internal::pabsdiff(a,b); }
482 : : };
483 : : template<typename LhsScalar,typename RhsScalar>
484 : : struct functor_traits<scalar_absolute_difference_op<LhsScalar,RhsScalar> > {
485 : : enum {
486 : : Cost = (NumTraits<LhsScalar>::AddCost+NumTraits<RhsScalar>::AddCost)/2,
487 : : PacketAccess = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasAbsDiff
488 : : };
489 : : };
490 : :
491 : :
492 : :
493 : : //---------- binary functors bound to a constant, thus appearing as a unary functor ----------
494 : :
495 : : // The following two classes permits to turn any binary functor into a unary one with one argument bound to a constant value.
496 : : // They are analogues to std::binder1st/binder2nd but with the following differences:
497 : : // - they are compatible with packetOp
498 : : // - they are portable across C++ versions (the std::binder* are deprecated in C++11)
499 : : template<typename BinaryOp> struct bind1st_op : BinaryOp {
500 : :
501 : : typedef typename BinaryOp::first_argument_type first_argument_type;
502 : : typedef typename BinaryOp::second_argument_type second_argument_type;
503 : : typedef typename BinaryOp::result_type result_type;
504 : :
505 : : EIGEN_DEVICE_FUNC explicit bind1st_op(const first_argument_type &val) : m_value(val) {}
506 : :
507 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const second_argument_type& b) const { return BinaryOp::operator()(m_value,b); }
508 : :
509 : : template<typename Packet>
510 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& b) const
511 : : { return BinaryOp::packetOp(internal::pset1<Packet>(m_value), b); }
512 : :
513 : : first_argument_type m_value;
514 : : };
515 : : template<typename BinaryOp> struct functor_traits<bind1st_op<BinaryOp> > : functor_traits<BinaryOp> {};
516 : :
517 : :
518 : : template<typename BinaryOp> struct bind2nd_op : BinaryOp {
519 : :
520 : : typedef typename BinaryOp::first_argument_type first_argument_type;
521 : : typedef typename BinaryOp::second_argument_type second_argument_type;
522 : : typedef typename BinaryOp::result_type result_type;
523 : :
524 : : EIGEN_DEVICE_FUNC explicit bind2nd_op(const second_argument_type &val) : m_value(val) {}
525 : :
526 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const result_type operator() (const first_argument_type& a) const { return BinaryOp::operator()(a,m_value); }
527 : :
528 : : template<typename Packet>
529 : : EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
530 : : { return BinaryOp::packetOp(a,internal::pset1<Packet>(m_value)); }
531 : :
532 : : second_argument_type m_value;
533 : : };
534 : : template<typename BinaryOp> struct functor_traits<bind2nd_op<BinaryOp> > : functor_traits<BinaryOp> {};
535 : :
536 : :
537 : : } // end namespace internal
538 : :
539 : : } // end namespace Eigen
540 : :
541 : : #endif // EIGEN_BINARY_FUNCTORS_H
|