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