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 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 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 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 = (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   EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
75 #else
76   scalar_product_op() {
77     EIGEN_SCALAR_BINARY_OP_PLUGIN
78   }
79 #endif
80   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
81   template<typename Packet>
82   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
83   { 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   EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
117   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const
118   { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
119 
120   template<typename Packet>
121   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const
122   { 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   EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
354 #else
355   scalar_difference_op() {
356     EIGEN_SCALAR_BINARY_OP_PLUGIN
357   }
358 #endif
359   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   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
362   { 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   EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
383 #else
384   scalar_quotient_op() {
385     EIGEN_SCALAR_BINARY_OP_PLUGIN
386   }
387 #endif
388   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   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
391   { 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
542