Functors.h
Go to the documentation of this file.
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 // Eigen is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // Alternatively, you can redistribute it and/or
12 // modify it under the terms of the GNU General Public License as
13 // published by the Free Software Foundation; either version 2 of
14 // the License, or (at your option) any later version.
15 //
16 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License and a copy of the GNU General Public License along with
23 // Eigen. If not, see <http://www.gnu.org/licenses/>.
24 
25 #ifndef EIGEN_FUNCTORS_H
26 #define EIGEN_FUNCTORS_H
27 
28 namespace Eigen {
29 
30 namespace internal {
31 
32 // associative functors:
33 
39 template<typename Scalar> struct scalar_sum_op {
40  EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
41  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
42  template<typename Packet>
43  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
44  { return internal::padd(a,b); }
45  template<typename Packet>
46  EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
47  { return internal::predux(a); }
48 };
49 template<typename Scalar>
50 struct functor_traits<scalar_sum_op<Scalar> > {
51  enum {
53  PacketAccess = packet_traits<Scalar>::HasAdd
54  };
55 };
56 
62 template<typename LhsScalar,typename RhsScalar> struct scalar_product_op {
63  enum {
64  // TODO vectorize mixed product
65  Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
66  };
67  typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
68  EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
69  EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
70  template<typename Packet>
71  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
72  { return internal::pmul(a,b); }
73  template<typename Packet>
74  EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
75  { return internal::predux_mul(a); }
76 };
77 template<typename LhsScalar,typename RhsScalar>
78 struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
79  enum {
80  Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
81  PacketAccess = scalar_product_op<LhsScalar,RhsScalar>::Vectorizable
82  };
83 };
84 
90 template<typename LhsScalar,typename RhsScalar> struct scalar_conj_product_op {
91 
92  enum {
94  };
95 
96  typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
97 
98  EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
99  EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const
100  { return conj_helper<LhsScalar,RhsScalar,Conj,false>().pmul(a,b); }
101 
102  template<typename Packet>
103  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
104  { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
105 };
106 template<typename LhsScalar,typename RhsScalar>
107 struct functor_traits<scalar_conj_product_op<LhsScalar,RhsScalar> > {
108  enum {
109  Cost = NumTraits<LhsScalar>::MulCost,
110  PacketAccess = internal::is_same<LhsScalar, RhsScalar>::value && packet_traits<LhsScalar>::HasMul
111  };
112 };
113 
119 template<typename Scalar> struct scalar_min_op {
120  EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
121  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::min; return (min)(a, b); }
122  template<typename Packet>
123  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
124  { return internal::pmin(a,b); }
125  template<typename Packet>
126  EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
127  { return internal::predux_min(a); }
128 };
129 template<typename Scalar>
130 struct functor_traits<scalar_min_op<Scalar> > {
131  enum {
133  PacketAccess = packet_traits<Scalar>::HasMin
134  };
135 };
136 
142 template<typename Scalar> struct scalar_max_op {
143  EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
144  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { using std::max; return (max)(a, b); }
145  template<typename Packet>
146  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
147  { return internal::pmax(a,b); }
148  template<typename Packet>
149  EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
150  { return internal::predux_max(a); }
151 };
152 template<typename Scalar>
153 struct functor_traits<scalar_max_op<Scalar> > {
154  enum {
156  PacketAccess = packet_traits<Scalar>::HasMax
157  };
158 };
159 
165 template<typename Scalar> struct scalar_hypot_op {
166  EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
167 // typedef typename NumTraits<Scalar>::Real result_type;
168  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
169  {
170  using std::max;
171  using std::min;
172  Scalar p = (max)(_x, _y);
173  Scalar q = (min)(_x, _y);
174  Scalar qp = q/p;
175  return p * sqrt(Scalar(1) + qp*qp);
176  }
177 };
178 template<typename Scalar>
179 struct functor_traits<scalar_hypot_op<Scalar> > {
180  enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
181 };
182 
186 template<typename Scalar, typename OtherScalar> struct scalar_binary_pow_op {
187  EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op)
188  inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return internal::pow(a, b); }
189 };
190 template<typename Scalar, typename OtherScalar>
191 struct functor_traits<scalar_binary_pow_op<Scalar,OtherScalar> > {
192  enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false };
193 };
194 
195 // other binary functors:
196 
202 template<typename Scalar> struct scalar_difference_op {
203  EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
204  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
205  template<typename Packet>
206  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
207  { return internal::psub(a,b); }
208 };
209 template<typename Scalar>
210 struct functor_traits<scalar_difference_op<Scalar> > {
211  enum {
213  PacketAccess = packet_traits<Scalar>::HasSub
214  };
215 };
216 
222 template<typename Scalar> struct scalar_quotient_op {
223  EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
224  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
225  template<typename Packet>
226  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
227  { return internal::pdiv(a,b); }
228 };
229 template<typename Scalar>
230 struct functor_traits<scalar_quotient_op<Scalar> > {
231  enum {
232  Cost = 2 * NumTraits<Scalar>::MulCost,
233  PacketAccess = packet_traits<Scalar>::HasDiv
234  };
235 };
236 
242 struct scalar_boolean_and_op {
243  EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op)
244  EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
245 };
246 template<> struct functor_traits<scalar_boolean_and_op> {
247  enum {
248  Cost = NumTraits<bool>::AddCost,
249  PacketAccess = false
250  };
251 };
252 
258 struct scalar_boolean_or_op {
259  EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op)
260  EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
261 };
262 template<> struct functor_traits<scalar_boolean_or_op> {
263  enum {
264  Cost = NumTraits<bool>::AddCost,
265  PacketAccess = false
266  };
267 };
268 
269 // unary functors:
270 
276 template<typename Scalar> struct scalar_opposite_op {
277  EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op)
278  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; }
279  template<typename Packet>
280  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
281  { return internal::pnegate(a); }
282 };
283 template<typename Scalar>
284 struct functor_traits<scalar_opposite_op<Scalar> >
285 { enum {
287  PacketAccess = packet_traits<Scalar>::HasNegate };
288 };
289 
295 template<typename Scalar> struct scalar_abs_op {
296  EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op)
297  typedef typename NumTraits<Scalar>::Real result_type;
298  EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs(a); }
299  template<typename Packet>
300  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
301  { return internal::pabs(a); }
302 };
303 template<typename Scalar>
304 struct functor_traits<scalar_abs_op<Scalar> >
305 {
306  enum {
308  PacketAccess = packet_traits<Scalar>::HasAbs
309  };
310 };
311 
317 template<typename Scalar> struct scalar_abs2_op {
318  EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
319  typedef typename NumTraits<Scalar>::Real result_type;
320  EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs2(a); }
321  template<typename Packet>
322  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
323  { return internal::pmul(a,a); }
324 };
325 template<typename Scalar>
326 struct functor_traits<scalar_abs2_op<Scalar> >
327 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; };
328 
334 template<typename Scalar> struct scalar_conjugate_op {
335  EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
336  EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return internal::conj(a); }
337  template<typename Packet>
338  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
339 };
340 template<typename Scalar>
341 struct functor_traits<scalar_conjugate_op<Scalar> >
342 {
343  enum {
345  PacketAccess = packet_traits<Scalar>::HasConj
346  };
347 };
348 
354 template<typename Scalar, typename NewType>
355 struct scalar_cast_op {
356  EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op)
357  typedef NewType result_type;
358  EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); }
359 };
360 template<typename Scalar, typename NewType>
361 struct functor_traits<scalar_cast_op<Scalar,NewType> >
362 { enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; };
363 
369 template<typename Scalar>
370 struct scalar_real_op {
371  EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
372  typedef typename NumTraits<Scalar>::Real result_type;
373  EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::real(a); }
374 };
375 template<typename Scalar>
376 struct functor_traits<scalar_real_op<Scalar> >
377 { enum { Cost = 0, PacketAccess = false }; };
378 
384 template<typename Scalar>
385 struct scalar_imag_op {
386  EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
387  typedef typename NumTraits<Scalar>::Real result_type;
388  EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::imag(a); }
389 };
390 template<typename Scalar>
391 struct functor_traits<scalar_imag_op<Scalar> >
392 { enum { Cost = 0, PacketAccess = false }; };
393 
399 template<typename Scalar>
400 struct scalar_real_ref_op {
401  EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
402  typedef typename NumTraits<Scalar>::Real result_type;
403  EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::real_ref(*const_cast<Scalar*>(&a)); }
404 };
405 template<typename Scalar>
406 struct functor_traits<scalar_real_ref_op<Scalar> >
407 { enum { Cost = 0, PacketAccess = false }; };
408 
414 template<typename Scalar>
415 struct scalar_imag_ref_op {
416  EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
417  typedef typename NumTraits<Scalar>::Real result_type;
418  EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::imag_ref(*const_cast<Scalar*>(&a)); }
419 };
420 template<typename Scalar>
421 struct functor_traits<scalar_imag_ref_op<Scalar> >
422 { enum { Cost = 0, PacketAccess = false }; };
423 
430 template<typename Scalar> struct scalar_exp_op {
431  EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op)
432  inline const Scalar operator() (const Scalar& a) const { return internal::exp(a); }
433  typedef typename packet_traits<Scalar>::type Packet;
434  inline Packet packetOp(const Packet& a) const { return internal::pexp(a); }
435 };
436 template<typename Scalar>
437 struct functor_traits<scalar_exp_op<Scalar> >
438 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasExp }; };
439 
446 template<typename Scalar> struct scalar_log_op {
447  EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op)
448  inline const Scalar operator() (const Scalar& a) const { return internal::log(a); }
449  typedef typename packet_traits<Scalar>::type Packet;
450  inline Packet packetOp(const Packet& a) const { return internal::plog(a); }
451 };
452 template<typename Scalar>
453 struct functor_traits<scalar_log_op<Scalar> >
454 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; };
455 
461 /* NOTE why doing the pset1() in packetOp *is* an optimization ?
462  * indeed it seems better to declare m_other as a Packet and do the pset1() once
463  * in the constructor. However, in practice:
464  * - GCC does not like m_other as a Packet and generate a load every time it needs it
465  * - on the other hand GCC is able to moves the pset1() away the loop :)
466  * - simpler code ;)
467  * (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
468  */
469 template<typename Scalar>
470 struct scalar_multiple_op {
471  typedef typename packet_traits<Scalar>::type Packet;
472  // FIXME default copy constructors seems bugged with std::complex<>
473  EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
474  EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
475  EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
476  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
477  { return internal::pmul(a, pset1<Packet>(m_other)); }
478  typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
479 };
480 template<typename Scalar>
481 struct functor_traits<scalar_multiple_op<Scalar> >
482 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
483 
484 template<typename Scalar1, typename Scalar2>
485 struct scalar_multiple2_op {
486  typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
487  EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { }
488  EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { }
489  EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; }
490  typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
491 };
492 template<typename Scalar1,typename Scalar2>
493 struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
494 { enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
495 
496 template<typename Scalar, bool IsInteger>
497 struct scalar_quotient1_impl {
498  typedef typename packet_traits<Scalar>::type Packet;
499  // FIXME default copy constructors seems bugged with std::complex<>
500  EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
501  EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(static_cast<Scalar>(1) / other) {}
502  EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
503  EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
504  { return internal::pmul(a, pset1<Packet>(m_other)); }
505  const Scalar m_other;
506 };
507 template<typename Scalar>
508 struct functor_traits<scalar_quotient1_impl<Scalar,false> >
509 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
510 
511 template<typename Scalar>
512 struct scalar_quotient1_impl<Scalar,true> {
513  // FIXME default copy constructors seems bugged with std::complex<>
514  EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
515  EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
516  EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
517  typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
518 };
519 template<typename Scalar>
520 struct functor_traits<scalar_quotient1_impl<Scalar,true> >
521 { enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
522 
531 template<typename Scalar>
532 struct scalar_quotient1_op : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger > {
533  EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other)
534  : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger >(other) {}
535 };
536 template<typename Scalar>
537 struct functor_traits<scalar_quotient1_op<Scalar> >
538 : functor_traits<scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger> >
539 {};
540 
541 // nullary functors
542 
543 template<typename Scalar>
544 struct scalar_constant_op {
545  typedef typename packet_traits<Scalar>::type Packet;
546  EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { }
547  EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { }
548  template<typename Index>
549  EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; }
550  template<typename Index>
551  EIGEN_STRONG_INLINE const Packet packetOp(Index, Index = 0) const { return internal::pset1<Packet>(m_other); }
552  const Scalar m_other;
553 };
554 template<typename Scalar>
555 struct functor_traits<scalar_constant_op<Scalar> >
556 // FIXME replace this packet test by a safe one
557 { enum { Cost = 1, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = true }; };
558 
559 template<typename Scalar> struct scalar_identity_op {
560  EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
561  template<typename Index>
562  EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); }
563 };
564 template<typename Scalar>
565 struct functor_traits<scalar_identity_op<Scalar> >
566 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
567 
568 template <typename Scalar, bool RandomAccess> struct linspaced_op_impl;
569 
570 // linear access for packet ops:
571 // 1) initialization
572 // base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0])
573 // 2) each step
574 // base += [size*step, ..., size*step]
575 template <typename Scalar>
576 struct linspaced_op_impl<Scalar,false>
577 {
578  typedef typename packet_traits<Scalar>::type Packet;
579 
580  linspaced_op_impl(Scalar low, Scalar step) :
581  m_low(low), m_step(step),
582  m_packetStep(pset1<Packet>(packet_traits<Scalar>::size*step)),
583  m_base(padd(pset1<Packet>(low),pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {}
584 
585  template<typename Index>
586  EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
587  template<typename Index>
588  EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); }
589 
590  const Scalar m_low;
591  const Scalar m_step;
592  const Packet m_packetStep;
593  mutable Packet m_base;
594 };
595 
596 // random access for packet ops:
597 // 1) each step
598 // [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
599 template <typename Scalar>
600 struct linspaced_op_impl<Scalar,true>
601 {
602  typedef typename packet_traits<Scalar>::type Packet;
603 
604  linspaced_op_impl(Scalar low, Scalar step) :
605  m_low(low), m_step(step),
606  m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Scalar>(0)) {}
607 
608  template<typename Index>
609  EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
610 
611  template<typename Index>
612  EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
613  { return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(i),m_interPacket))); }
614 
615  const Scalar m_low;
616  const Scalar m_step;
617  const Packet m_lowPacket;
618  const Packet m_stepPacket;
619  const Packet m_interPacket;
620 };
621 
622 // ----- Linspace functor ----------------------------------------------------------------
623 
624 // Forward declaration (we default to random access which does not really give
625 // us a speed gain when using packet access but it allows to use the functor in
626 // nested expressions).
627 template <typename Scalar, bool RandomAccess = true> struct linspaced_op;
628 template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,RandomAccess> >
629 { enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasSetLinear, IsRepeatable = true }; };
630 template <typename Scalar, bool RandomAccess> struct linspaced_op
631 {
632  typedef typename packet_traits<Scalar>::type Packet;
633  linspaced_op(Scalar low, Scalar high, int num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {}
634 
635  template<typename Index>
636  EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
637 
638  // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
639  // there row==0 and col is used for the actual iteration.
640  template<typename Index>
641  EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const
642  {
643  eigen_assert(col==0 || row==0);
644  return impl(col + row);
645  }
646 
647  template<typename Index>
648  EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); }
649 
650  // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
651  // there row==0 and col is used for the actual iteration.
652  template<typename Index>
653  EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
654  {
655  eigen_assert(col==0 || row==0);
656  return impl.packetOp(col + row);
657  }
658 
659  // This proxy object handles the actual required temporaries, the different
660  // implementations (random vs. sequential access) as well as the
661  // correct piping to size 2/4 packet operations.
662  const linspaced_op_impl<Scalar,RandomAccess> impl;
663 };
664 
665 // all functors allow linear access, except scalar_identity_op. So we fix here a quick meta
666 // to indicate whether a functor allows linear access, just always answering 'yes' except for
667 // scalar_identity_op.
668 // FIXME move this to functor_traits adding a functor_default
669 template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
670 template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
671 
672 // in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
673 // where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
674 // FIXME move this to functor_traits adding a functor_default
675 template<typename Functor> struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; };
676 template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
677 template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_conj_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
678 
679 
684 /* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */
685 template<typename Scalar>
686 struct scalar_add_op {
687  typedef typename packet_traits<Scalar>::type Packet;
688  // FIXME default copy constructors seems bugged with std::complex<>
689  inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { }
690  inline scalar_add_op(const Scalar& other) : m_other(other) { }
691  inline Scalar operator() (const Scalar& a) const { return a + m_other; }
692  inline const Packet packetOp(const Packet& a) const
693  { return internal::padd(a, pset1<Packet>(m_other)); }
694  const Scalar m_other;
695 };
696 template<typename Scalar>
697 struct functor_traits<scalar_add_op<Scalar> >
698 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
699 
704 template<typename Scalar> struct scalar_sqrt_op {
705  EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op)
706  inline const Scalar operator() (const Scalar& a) const { return internal::sqrt(a); }
707  typedef typename packet_traits<Scalar>::type Packet;
708  inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); }
709 };
710 template<typename Scalar>
711 struct functor_traits<scalar_sqrt_op<Scalar> >
712 { enum {
713  Cost = 5 * NumTraits<Scalar>::MulCost,
714  PacketAccess = packet_traits<Scalar>::HasSqrt
715  };
716 };
717 
722 template<typename Scalar> struct scalar_cos_op {
723  EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op)
724  inline Scalar operator() (const Scalar& a) const { return internal::cos(a); }
725  typedef typename packet_traits<Scalar>::type Packet;
726  inline Packet packetOp(const Packet& a) const { return internal::pcos(a); }
727 };
728 template<typename Scalar>
729 struct functor_traits<scalar_cos_op<Scalar> >
730 {
731  enum {
732  Cost = 5 * NumTraits<Scalar>::MulCost,
733  PacketAccess = packet_traits<Scalar>::HasCos
734  };
735 };
736 
741 template<typename Scalar> struct scalar_sin_op {
742  EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op)
743  inline const Scalar operator() (const Scalar& a) const { return internal::sin(a); }
744  typedef typename packet_traits<Scalar>::type Packet;
745  inline Packet packetOp(const Packet& a) const { return internal::psin(a); }
746 };
747 template<typename Scalar>
748 struct functor_traits<scalar_sin_op<Scalar> >
749 {
750  enum {
751  Cost = 5 * NumTraits<Scalar>::MulCost,
752  PacketAccess = packet_traits<Scalar>::HasSin
753  };
754 };
755 
756 
761 template<typename Scalar> struct scalar_tan_op {
762  EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op)
763  inline const Scalar operator() (const Scalar& a) const { return internal::tan(a); }
764  typedef typename packet_traits<Scalar>::type Packet;
765  inline Packet packetOp(const Packet& a) const { return internal::ptan(a); }
766 };
767 template<typename Scalar>
768 struct functor_traits<scalar_tan_op<Scalar> >
769 {
770  enum {
771  Cost = 5 * NumTraits<Scalar>::MulCost,
772  PacketAccess = packet_traits<Scalar>::HasTan
773  };
774 };
775 
780 template<typename Scalar> struct scalar_acos_op {
781  EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op)
782  inline const Scalar operator() (const Scalar& a) const { return internal::acos(a); }
783  typedef typename packet_traits<Scalar>::type Packet;
784  inline Packet packetOp(const Packet& a) const { return internal::pacos(a); }
785 };
786 template<typename Scalar>
787 struct functor_traits<scalar_acos_op<Scalar> >
788 {
789  enum {
790  Cost = 5 * NumTraits<Scalar>::MulCost,
791  PacketAccess = packet_traits<Scalar>::HasACos
792  };
793 };
794 
799 template<typename Scalar> struct scalar_asin_op {
800  EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op)
801  inline const Scalar operator() (const Scalar& a) const { return internal::asin(a); }
802  typedef typename packet_traits<Scalar>::type Packet;
803  inline Packet packetOp(const Packet& a) const { return internal::pasin(a); }
804 };
805 template<typename Scalar>
806 struct functor_traits<scalar_asin_op<Scalar> >
807 {
808  enum {
809  Cost = 5 * NumTraits<Scalar>::MulCost,
810  PacketAccess = packet_traits<Scalar>::HasASin
811  };
812 };
813 
818 template<typename Scalar>
819 struct scalar_pow_op {
820  // FIXME default copy constructors seems bugged with std::complex<>
821  inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
822  inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
823  inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); }
824  const Scalar m_exponent;
825 };
826 template<typename Scalar>
827 struct functor_traits<scalar_pow_op<Scalar> >
828 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
829 
834 template<typename Scalar>
835 struct scalar_inverse_mult_op {
836  scalar_inverse_mult_op(const Scalar& other) : m_other(other) {}
837  inline Scalar operator() (const Scalar& a) const { return m_other / a; }
838  template<typename Packet>
839  inline const Packet packetOp(const Packet& a) const
840  { return internal::pdiv(pset1<Packet>(m_other),a); }
841  Scalar m_other;
842 };
843 
848 template<typename Scalar>
849 struct scalar_inverse_op {
850  EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op)
851  inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; }
852  template<typename Packet>
853  inline const Packet packetOp(const Packet& a) const
854  { return internal::pdiv(pset1<Packet>(Scalar(1)),a); }
855 };
856 template<typename Scalar>
857 struct functor_traits<scalar_inverse_op<Scalar> >
858 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
859 
864 template<typename Scalar>
865 struct scalar_square_op {
866  EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op)
867  inline Scalar operator() (const Scalar& a) const { return a*a; }
868  template<typename Packet>
869  inline const Packet packetOp(const Packet& a) const
870  { return internal::pmul(a,a); }
871 };
872 template<typename Scalar>
873 struct functor_traits<scalar_square_op<Scalar> >
874 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
875 
880 template<typename Scalar>
881 struct scalar_cube_op {
882  EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op)
883  inline Scalar operator() (const Scalar& a) const { return a*a*a; }
884  template<typename Packet>
885  inline const Packet packetOp(const Packet& a) const
886  { return internal::pmul(a,pmul(a,a)); }
887 };
888 template<typename Scalar>
889 struct functor_traits<scalar_cube_op<Scalar> >
890 { enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
891 
892 // default functor traits for STL functors:
893 
894 template<typename T>
895 struct functor_traits<std::multiplies<T> >
896 { enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
897 
898 template<typename T>
899 struct functor_traits<std::divides<T> >
900 { enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
901 
902 template<typename T>
903 struct functor_traits<std::plus<T> >
904 { enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
905 
906 template<typename T>
907 struct functor_traits<std::minus<T> >
908 { enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
909 
910 template<typename T>
911 struct functor_traits<std::negate<T> >
912 { enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
913 
914 template<typename T>
915 struct functor_traits<std::logical_or<T> >
916 { enum { Cost = 1, PacketAccess = false }; };
917 
918 template<typename T>
919 struct functor_traits<std::logical_and<T> >
920 { enum { Cost = 1, PacketAccess = false }; };
921 
922 template<typename T>
923 struct functor_traits<std::logical_not<T> >
924 { enum { Cost = 1, PacketAccess = false }; };
925 
926 template<typename T>
927 struct functor_traits<std::greater<T> >
928 { enum { Cost = 1, PacketAccess = false }; };
929 
930 template<typename T>
931 struct functor_traits<std::less<T> >
932 { enum { Cost = 1, PacketAccess = false }; };
933 
934 template<typename T>
935 struct functor_traits<std::greater_equal<T> >
936 { enum { Cost = 1, PacketAccess = false }; };
937 
938 template<typename T>
939 struct functor_traits<std::less_equal<T> >
940 { enum { Cost = 1, PacketAccess = false }; };
941 
942 template<typename T>
943 struct functor_traits<std::equal_to<T> >
944 { enum { Cost = 1, PacketAccess = false }; };
945 
946 template<typename T>
947 struct functor_traits<std::not_equal_to<T> >
948 { enum { Cost = 1, PacketAccess = false }; };
949 
950 template<typename T>
951 struct functor_traits<std::binder2nd<T> >
952 { enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
953 
954 template<typename T>
955 struct functor_traits<std::binder1st<T> >
956 { enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
957 
958 template<typename T>
959 struct functor_traits<std::unary_negate<T> >
960 { enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
961 
962 template<typename T>
963 struct functor_traits<std::binary_negate<T> >
964 { enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
965 
966 #ifdef EIGEN_STDEXT_SUPPORT
967 
968 template<typename T0,typename T1>
969 struct functor_traits<std::project1st<T0,T1> >
970 { enum { Cost = 0, PacketAccess = false }; };
971 
972 template<typename T0,typename T1>
973 struct functor_traits<std::project2nd<T0,T1> >
974 { enum { Cost = 0, PacketAccess = false }; };
975 
976 template<typename T0,typename T1>
977 struct functor_traits<std::select2nd<std::pair<T0,T1> > >
978 { enum { Cost = 0, PacketAccess = false }; };
979 
980 template<typename T0,typename T1>
981 struct functor_traits<std::select1st<std::pair<T0,T1> > >
982 { enum { Cost = 0, PacketAccess = false }; };
983 
984 template<typename T0,typename T1>
985 struct functor_traits<std::unary_compose<T0,T1> >
986 { enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost, PacketAccess = false }; };
987 
988 template<typename T0,typename T1,typename T2>
989 struct functor_traits<std::binary_compose<T0,T1,T2> >
990 { enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost + functor_traits<T2>::Cost, PacketAccess = false }; };
991 
992 #endif // EIGEN_STDEXT_SUPPORT
993 
994 // allow to add new functors and specializations of functor_traits from outside Eigen.
995 // this macro is really needed because functor_traits must be specialized after it is declared but before it is used...
996 #ifdef EIGEN_FUNCTORS_PLUGIN
997 #include EIGEN_FUNCTORS_PLUGIN
998 #endif
999 
1000 } // end namespace internal
1001 
1002 } // end namespace Eigen
1003 
1004 #endif // EIGEN_FUNCTORS_H