Eigen  3.2.93
CoreEvaluators.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
6 // Copyright (C) 2011-2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
7 //
8 // This Source Code Form is subject to the terms of the Mozilla
9 // Public License v. 2.0. If a copy of the MPL was not distributed
10 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 
12 
13 #ifndef EIGEN_COREEVALUATORS_H
14 #define EIGEN_COREEVALUATORS_H
15 
16 namespace Eigen {
17 
18 namespace internal {
19 
20 // This class returns the evaluator kind from the expression storage kind.
21 // Default assumes index based accessors
22 template<typename StorageKind>
23 struct storage_kind_to_evaluator_kind {
24  typedef IndexBased Kind;
25 };
26 
27 // This class returns the evaluator shape from the expression storage kind.
28 // It can be Dense, Sparse, Triangular, Diagonal, SelfAdjoint, Band, etc.
29 template<typename StorageKind> struct storage_kind_to_shape;
30 
31 template<> struct storage_kind_to_shape<Dense> { typedef DenseShape Shape; };
32 template<> struct storage_kind_to_shape<SolverStorage> { typedef SolverShape Shape; };
33 template<> struct storage_kind_to_shape<PermutationStorage> { typedef PermutationShape Shape; };
34 template<> struct storage_kind_to_shape<TranspositionsStorage> { typedef TranspositionsShape Shape; };
35 
36 // Evaluators have to be specialized with respect to various criteria such as:
37 // - storage/structure/shape
38 // - scalar type
39 // - etc.
40 // Therefore, we need specialization of evaluator providing additional template arguments for each kind of evaluators.
41 // We currently distinguish the following kind of evaluators:
42 // - unary_evaluator for expressions taking only one arguments (CwiseUnaryOp, CwiseUnaryView, Transpose, MatrixWrapper, ArrayWrapper, Reverse, Replicate)
43 // - binary_evaluator for expression taking two arguments (CwiseBinaryOp)
44 // - ternary_evaluator for expression taking three arguments (CwiseTernaryOp)
45 // - product_evaluator for linear algebra products (Product); special case of binary_evaluator because it requires additional tags for dispatching.
46 // - mapbase_evaluator for Map, Block, Ref
47 // - block_evaluator for Block (special dispatching to a mapbase_evaluator or unary_evaluator)
48 
49 template< typename T,
50  typename Arg1Kind = typename evaluator_traits<typename T::Arg1>::Kind,
51  typename Arg2Kind = typename evaluator_traits<typename T::Arg2>::Kind,
52  typename Arg3Kind = typename evaluator_traits<typename T::Arg3>::Kind,
53  typename Arg1Scalar = typename traits<typename T::Arg1>::Scalar,
54  typename Arg2Scalar = typename traits<typename T::Arg2>::Scalar,
55  typename Arg3Scalar = typename traits<typename T::Arg3>::Scalar> struct ternary_evaluator;
56 
57 template< typename T,
58  typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
59  typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
60  typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
61  typename RhsScalar = typename traits<typename T::Rhs>::Scalar> struct binary_evaluator;
62 
63 template< typename T,
64  typename Kind = typename evaluator_traits<typename T::NestedExpression>::Kind,
65  typename Scalar = typename T::Scalar> struct unary_evaluator;
66 
67 // evaluator_traits<T> contains traits for evaluator<T>
68 
69 template<typename T>
70 struct evaluator_traits_base
71 {
72  // by default, get evaluator kind and shape from storage
73  typedef typename storage_kind_to_evaluator_kind<typename traits<T>::StorageKind>::Kind Kind;
74  typedef typename storage_kind_to_shape<typename traits<T>::StorageKind>::Shape Shape;
75 };
76 
77 // Default evaluator traits
78 template<typename T>
79 struct evaluator_traits : public evaluator_traits_base<T>
80 {
81 };
82 
83 template<typename T, typename Shape = typename evaluator_traits<T>::Shape >
84 struct evaluator_assume_aliasing {
85  static const bool value = false;
86 };
87 
88 // By default, we assume a unary expression:
89 template<typename T>
90 struct evaluator : public unary_evaluator<T>
91 {
92  typedef unary_evaluator<T> Base;
93  EIGEN_DEVICE_FUNC explicit evaluator(const T& xpr) : Base(xpr) {}
94 };
95 
96 
97 // TODO: Think about const-correctness
98 template<typename T>
99 struct evaluator<const T>
100  : evaluator<T>
101 {
102  EIGEN_DEVICE_FUNC
103  explicit evaluator(const T& xpr) : evaluator<T>(xpr) {}
104 };
105 
106 // ---------- base class for all evaluators ----------
107 
108 template<typename ExpressionType>
109 struct evaluator_base : public noncopyable
110 {
111  // TODO that's not very nice to have to propagate all these traits. They are currently only needed to handle outer,inner indices.
112  typedef traits<ExpressionType> ExpressionTraits;
113 
114  enum {
115  Alignment = 0
116  };
117 };
118 
119 // -------------------- Matrix and Array --------------------
120 //
121 // evaluator<PlainObjectBase> is a common base class for the
122 // Matrix and Array evaluators.
123 // Here we directly specialize evaluator. This is not really a unary expression, and it is, by definition, dense,
124 // so no need for more sophisticated dispatching.
125 
126 template<typename Derived>
127 struct evaluator<PlainObjectBase<Derived> >
128  : evaluator_base<Derived>
129 {
130  typedef PlainObjectBase<Derived> PlainObjectType;
131  typedef typename PlainObjectType::Scalar Scalar;
132  typedef typename PlainObjectType::CoeffReturnType CoeffReturnType;
133 
134  enum {
135  IsRowMajor = PlainObjectType::IsRowMajor,
136  IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime,
137  RowsAtCompileTime = PlainObjectType::RowsAtCompileTime,
138  ColsAtCompileTime = PlainObjectType::ColsAtCompileTime,
139 
140  CoeffReadCost = NumTraits<Scalar>::ReadCost,
141  Flags = traits<Derived>::EvaluatorFlags,
142  Alignment = traits<Derived>::Alignment
143  };
144 
145  EIGEN_DEVICE_FUNC evaluator()
146  : m_data(0),
147  m_outerStride(IsVectorAtCompileTime ? 0
148  : int(IsRowMajor) ? ColsAtCompileTime
149  : RowsAtCompileTime)
150  {
151  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
152  }
153 
154  EIGEN_DEVICE_FUNC explicit evaluator(const PlainObjectType& m)
155  : m_data(m.data()), m_outerStride(IsVectorAtCompileTime ? 0 : m.outerStride())
156  {
157  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
158  }
159 
160  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
161  CoeffReturnType coeff(Index row, Index col) const
162  {
163  if (IsRowMajor)
164  return m_data[row * m_outerStride.value() + col];
165  else
166  return m_data[row + col * m_outerStride.value()];
167  }
168 
169  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
170  CoeffReturnType coeff(Index index) const
171  {
172  return m_data[index];
173  }
174 
175  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
176  Scalar& coeffRef(Index row, Index col)
177  {
178  if (IsRowMajor)
179  return const_cast<Scalar*>(m_data)[row * m_outerStride.value() + col];
180  else
181  return const_cast<Scalar*>(m_data)[row + col * m_outerStride.value()];
182  }
183 
184  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
185  Scalar& coeffRef(Index index)
186  {
187  return const_cast<Scalar*>(m_data)[index];
188  }
189 
190  template<int LoadMode, typename PacketType>
191  EIGEN_STRONG_INLINE
192  PacketType packet(Index row, Index col) const
193  {
194  if (IsRowMajor)
195  return ploadt<PacketType, LoadMode>(m_data + row * m_outerStride.value() + col);
196  else
197  return ploadt<PacketType, LoadMode>(m_data + row + col * m_outerStride.value());
198  }
199 
200  template<int LoadMode, typename PacketType>
201  EIGEN_STRONG_INLINE
202  PacketType packet(Index index) const
203  {
204  return ploadt<PacketType, LoadMode>(m_data + index);
205  }
206 
207  template<int StoreMode,typename PacketType>
208  EIGEN_STRONG_INLINE
209  void writePacket(Index row, Index col, const PacketType& x)
210  {
211  if (IsRowMajor)
212  return pstoret<Scalar, PacketType, StoreMode>
213  (const_cast<Scalar*>(m_data) + row * m_outerStride.value() + col, x);
214  else
215  return pstoret<Scalar, PacketType, StoreMode>
216  (const_cast<Scalar*>(m_data) + row + col * m_outerStride.value(), x);
217  }
218 
219  template<int StoreMode, typename PacketType>
220  EIGEN_STRONG_INLINE
221  void writePacket(Index index, const PacketType& x)
222  {
223  return pstoret<Scalar, PacketType, StoreMode>(const_cast<Scalar*>(m_data) + index, x);
224  }
225 
226 protected:
227  const Scalar *m_data;
228 
229  // We do not need to know the outer stride for vectors
230  variable_if_dynamic<Index, IsVectorAtCompileTime ? 0
231  : int(IsRowMajor) ? ColsAtCompileTime
232  : RowsAtCompileTime> m_outerStride;
233 };
234 
235 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
236 struct evaluator<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
237  : evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > >
238 {
239  typedef Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
240 
241  EIGEN_DEVICE_FUNC evaluator() {}
242 
243  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& m)
244  : evaluator<PlainObjectBase<XprType> >(m)
245  { }
246 };
247 
248 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
249 struct evaluator<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
250  : evaluator<PlainObjectBase<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > >
251 {
252  typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
253 
254  EIGEN_DEVICE_FUNC evaluator() {}
255 
256  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& m)
257  : evaluator<PlainObjectBase<XprType> >(m)
258  { }
259 };
260 
261 // -------------------- Transpose --------------------
262 
263 template<typename ArgType>
264 struct unary_evaluator<Transpose<ArgType>, IndexBased>
265  : evaluator_base<Transpose<ArgType> >
266 {
267  typedef Transpose<ArgType> XprType;
268 
269  enum {
270  CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
271  Flags = evaluator<ArgType>::Flags ^ RowMajorBit,
272  Alignment = evaluator<ArgType>::Alignment
273  };
274 
275  EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& t) : m_argImpl(t.nestedExpression()) {}
276 
277  typedef typename XprType::Scalar Scalar;
278  typedef typename XprType::CoeffReturnType CoeffReturnType;
279 
280  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
281  CoeffReturnType coeff(Index row, Index col) const
282  {
283  return m_argImpl.coeff(col, row);
284  }
285 
286  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
287  CoeffReturnType coeff(Index index) const
288  {
289  return m_argImpl.coeff(index);
290  }
291 
292  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
293  Scalar& coeffRef(Index row, Index col)
294  {
295  return m_argImpl.coeffRef(col, row);
296  }
297 
298  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
299  typename XprType::Scalar& coeffRef(Index index)
300  {
301  return m_argImpl.coeffRef(index);
302  }
303 
304  template<int LoadMode, typename PacketType>
305  EIGEN_STRONG_INLINE
306  PacketType packet(Index row, Index col) const
307  {
308  return m_argImpl.template packet<LoadMode,PacketType>(col, row);
309  }
310 
311  template<int LoadMode, typename PacketType>
312  EIGEN_STRONG_INLINE
313  PacketType packet(Index index) const
314  {
315  return m_argImpl.template packet<LoadMode,PacketType>(index);
316  }
317 
318  template<int StoreMode, typename PacketType>
319  EIGEN_STRONG_INLINE
320  void writePacket(Index row, Index col, const PacketType& x)
321  {
322  m_argImpl.template writePacket<StoreMode,PacketType>(col, row, x);
323  }
324 
325  template<int StoreMode, typename PacketType>
326  EIGEN_STRONG_INLINE
327  void writePacket(Index index, const PacketType& x)
328  {
329  m_argImpl.template writePacket<StoreMode,PacketType>(index, x);
330  }
331 
332 protected:
333  evaluator<ArgType> m_argImpl;
334 };
335 
336 // -------------------- CwiseNullaryOp --------------------
337 // Like Matrix and Array, this is not really a unary expression, so we directly specialize evaluator.
338 // Likewise, there is not need to more sophisticated dispatching here.
339 
340 template<typename NullaryOp, typename PlainObjectType>
341 struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
342  : evaluator_base<CwiseNullaryOp<NullaryOp,PlainObjectType> >
343 {
344  typedef CwiseNullaryOp<NullaryOp,PlainObjectType> XprType;
345  typedef typename internal::remove_all<PlainObjectType>::type PlainObjectTypeCleaned;
346 
347  enum {
348  CoeffReadCost = internal::functor_traits<NullaryOp>::Cost,
349 
350  Flags = (evaluator<PlainObjectTypeCleaned>::Flags
351  & ( HereditaryBits
352  | (functor_has_linear_access<NullaryOp>::ret ? LinearAccessBit : 0)
353  | (functor_traits<NullaryOp>::PacketAccess ? PacketAccessBit : 0)))
354  | (functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit),
355  Alignment = AlignedMax
356  };
357 
358  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& n)
359  : m_functor(n.functor())
360  {
361  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
362  }
363 
364  typedef typename XprType::CoeffReturnType CoeffReturnType;
365 
366  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
367  CoeffReturnType coeff(Index row, Index col) const
368  {
369  return m_functor(row, col);
370  }
371 
372  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
373  CoeffReturnType coeff(Index index) const
374  {
375  return m_functor(index);
376  }
377 
378  template<int LoadMode, typename PacketType>
379  EIGEN_STRONG_INLINE
380  PacketType packet(Index row, Index col) const
381  {
382  return m_functor.template packetOp<Index,PacketType>(row, col);
383  }
384 
385  template<int LoadMode, typename PacketType>
386  EIGEN_STRONG_INLINE
387  PacketType packet(Index index) const
388  {
389  return m_functor.template packetOp<Index,PacketType>(index);
390  }
391 
392 protected:
393  const NullaryOp m_functor;
394 };
395 
396 // -------------------- CwiseUnaryOp --------------------
397 
398 template<typename UnaryOp, typename ArgType>
399 struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
400  : evaluator_base<CwiseUnaryOp<UnaryOp, ArgType> >
401 {
402  typedef CwiseUnaryOp<UnaryOp, ArgType> XprType;
403 
404  enum {
405  CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
406 
407  Flags = evaluator<ArgType>::Flags
408  & (HereditaryBits | LinearAccessBit | (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
409  Alignment = evaluator<ArgType>::Alignment
410  };
411 
412  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
413  explicit unary_evaluator(const XprType& op)
414  : m_functor(op.functor()),
415  m_argImpl(op.nestedExpression())
416  {
417  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
418  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
419  }
420 
421  typedef typename XprType::CoeffReturnType CoeffReturnType;
422 
423  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
424  CoeffReturnType coeff(Index row, Index col) const
425  {
426  return m_functor(m_argImpl.coeff(row, col));
427  }
428 
429  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
430  CoeffReturnType coeff(Index index) const
431  {
432  return m_functor(m_argImpl.coeff(index));
433  }
434 
435  template<int LoadMode, typename PacketType>
436  EIGEN_STRONG_INLINE
437  PacketType packet(Index row, Index col) const
438  {
439  return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(row, col));
440  }
441 
442  template<int LoadMode, typename PacketType>
443  EIGEN_STRONG_INLINE
444  PacketType packet(Index index) const
445  {
446  return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(index));
447  }
448 
449 protected:
450  const UnaryOp m_functor;
451  evaluator<ArgType> m_argImpl;
452 };
453 
454 // -------------------- CwiseTernaryOp --------------------
455 
456 // this is a ternary expression
457 template<typename TernaryOp, typename Arg1, typename Arg2, typename Arg3>
458 struct evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >
459  : public ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >
460 {
461  typedef CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> XprType;
462  typedef ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> > Base;
463 
464  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {}
465 };
466 
467 template<typename TernaryOp, typename Arg1, typename Arg2, typename Arg3>
468 struct ternary_evaluator<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3>, IndexBased, IndexBased>
469  : evaluator_base<CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> >
470 {
471  typedef CwiseTernaryOp<TernaryOp, Arg1, Arg2, Arg3> XprType;
472 
473  enum {
474  CoeffReadCost = evaluator<Arg1>::CoeffReadCost + evaluator<Arg2>::CoeffReadCost + evaluator<Arg3>::CoeffReadCost + functor_traits<TernaryOp>::Cost,
475 
476  Arg1Flags = evaluator<Arg1>::Flags,
477  Arg2Flags = evaluator<Arg2>::Flags,
478  Arg3Flags = evaluator<Arg3>::Flags,
479  SameType = is_same<typename Arg1::Scalar,typename Arg2::Scalar>::value && is_same<typename Arg1::Scalar,typename Arg3::Scalar>::value,
480  StorageOrdersAgree = (int(Arg1Flags)&RowMajorBit)==(int(Arg2Flags)&RowMajorBit) && (int(Arg1Flags)&RowMajorBit)==(int(Arg3Flags)&RowMajorBit),
481  Flags0 = (int(Arg1Flags) | int(Arg2Flags) | int(Arg3Flags)) & (
482  HereditaryBits
483  | (int(Arg1Flags) & int(Arg2Flags) & int(Arg3Flags) &
484  ( (StorageOrdersAgree ? LinearAccessBit : 0)
485  | (functor_traits<TernaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
486  )
487  )
488  ),
489  Flags = (Flags0 & ~RowMajorBit) | (Arg1Flags & RowMajorBit),
490  Alignment = EIGEN_PLAIN_ENUM_MIN(
491  EIGEN_PLAIN_ENUM_MIN(evaluator<Arg1>::Alignment, evaluator<Arg2>::Alignment),
492  evaluator<Arg3>::Alignment)
493  };
494 
495  EIGEN_DEVICE_FUNC explicit ternary_evaluator(const XprType& xpr)
496  : m_functor(xpr.functor()),
497  m_arg1Impl(xpr.arg1()),
498  m_arg2Impl(xpr.arg2()),
499  m_arg3Impl(xpr.arg3())
500  {
501  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<TernaryOp>::Cost);
502  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
503  }
504 
505  typedef typename XprType::CoeffReturnType CoeffReturnType;
506 
507  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
508  CoeffReturnType coeff(Index row, Index col) const
509  {
510  return m_functor(m_arg1Impl.coeff(row, col), m_arg2Impl.coeff(row, col), m_arg3Impl.coeff(row, col));
511  }
512 
513  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
514  CoeffReturnType coeff(Index index) const
515  {
516  return m_functor(m_arg1Impl.coeff(index), m_arg2Impl.coeff(index), m_arg3Impl.coeff(index));
517  }
518 
519  template<int LoadMode, typename PacketType>
520  EIGEN_STRONG_INLINE
521  PacketType packet(Index row, Index col) const
522  {
523  return m_functor.packetOp(m_arg1Impl.template packet<LoadMode,PacketType>(row, col),
524  m_arg2Impl.template packet<LoadMode,PacketType>(row, col),
525  m_arg3Impl.template packet<LoadMode,PacketType>(row, col));
526  }
527 
528  template<int LoadMode, typename PacketType>
529  EIGEN_STRONG_INLINE
530  PacketType packet(Index index) const
531  {
532  return m_functor.packetOp(m_arg1Impl.template packet<LoadMode,PacketType>(index),
533  m_arg2Impl.template packet<LoadMode,PacketType>(index),
534  m_arg3Impl.template packet<LoadMode,PacketType>(index));
535  }
536 
537 protected:
538  const TernaryOp m_functor;
539  evaluator<Arg1> m_arg1Impl;
540  evaluator<Arg2> m_arg2Impl;
541  evaluator<Arg3> m_arg3Impl;
542 };
543 
544 // -------------------- CwiseBinaryOp --------------------
545 
546 // this is a binary expression
547 template<typename BinaryOp, typename Lhs, typename Rhs>
548 struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
549  : public binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
550 {
551  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
552  typedef binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > Base;
553 
554  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {}
555 };
556 
557 template<typename BinaryOp, typename Lhs, typename Rhs>
558 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBased>
559  : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
560 {
561  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
562 
563  enum {
564  CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
565 
566  LhsFlags = evaluator<Lhs>::Flags,
567  RhsFlags = evaluator<Rhs>::Flags,
568  SameType = is_same<typename Lhs::Scalar,typename Rhs::Scalar>::value,
569  StorageOrdersAgree = (int(LhsFlags)&RowMajorBit)==(int(RhsFlags)&RowMajorBit),
570  Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
571  HereditaryBits
572  | (int(LhsFlags) & int(RhsFlags) &
573  ( (StorageOrdersAgree ? LinearAccessBit : 0)
574  | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
575  )
576  )
577  ),
578  Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
579  Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<Lhs>::Alignment,evaluator<Rhs>::Alignment)
580  };
581 
582  EIGEN_DEVICE_FUNC explicit binary_evaluator(const XprType& xpr)
583  : m_functor(xpr.functor()),
584  m_lhsImpl(xpr.lhs()),
585  m_rhsImpl(xpr.rhs())
586  {
587  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
588  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
589  }
590 
591  typedef typename XprType::CoeffReturnType CoeffReturnType;
592 
593  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
594  CoeffReturnType coeff(Index row, Index col) const
595  {
596  return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col));
597  }
598 
599  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
600  CoeffReturnType coeff(Index index) const
601  {
602  return m_functor(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index));
603  }
604 
605  template<int LoadMode, typename PacketType>
606  EIGEN_STRONG_INLINE
607  PacketType packet(Index row, Index col) const
608  {
609  return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(row, col),
610  m_rhsImpl.template packet<LoadMode,PacketType>(row, col));
611  }
612 
613  template<int LoadMode, typename PacketType>
614  EIGEN_STRONG_INLINE
615  PacketType packet(Index index) const
616  {
617  return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(index),
618  m_rhsImpl.template packet<LoadMode,PacketType>(index));
619  }
620 
621 protected:
622  const BinaryOp m_functor;
623  evaluator<Lhs> m_lhsImpl;
624  evaluator<Rhs> m_rhsImpl;
625 };
626 
627 // -------------------- CwiseUnaryView --------------------
628 
629 template<typename UnaryOp, typename ArgType>
630 struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, IndexBased>
631  : evaluator_base<CwiseUnaryView<UnaryOp, ArgType> >
632 {
633  typedef CwiseUnaryView<UnaryOp, ArgType> XprType;
634 
635  enum {
636  CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
637 
638  Flags = (evaluator<ArgType>::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit)),
639 
640  Alignment = 0 // FIXME it is not very clear why alignment is necessarily lost...
641  };
642 
643  EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
644  : m_unaryOp(op.functor()),
645  m_argImpl(op.nestedExpression())
646  {
647  EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
648  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
649  }
650 
651  typedef typename XprType::Scalar Scalar;
652  typedef typename XprType::CoeffReturnType CoeffReturnType;
653 
654  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
655  CoeffReturnType coeff(Index row, Index col) const
656  {
657  return m_unaryOp(m_argImpl.coeff(row, col));
658  }
659 
660  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
661  CoeffReturnType coeff(Index index) const
662  {
663  return m_unaryOp(m_argImpl.coeff(index));
664  }
665 
666  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
667  Scalar& coeffRef(Index row, Index col)
668  {
669  return m_unaryOp(m_argImpl.coeffRef(row, col));
670  }
671 
672  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
673  Scalar& coeffRef(Index index)
674  {
675  return m_unaryOp(m_argImpl.coeffRef(index));
676  }
677 
678 protected:
679  const UnaryOp m_unaryOp;
680  evaluator<ArgType> m_argImpl;
681 };
682 
683 // -------------------- Map --------------------
684 
685 // FIXME perhaps the PlainObjectType could be provided by Derived::PlainObject ?
686 // but that might complicate template specialization
687 template<typename Derived, typename PlainObjectType>
688 struct mapbase_evaluator;
689 
690 template<typename Derived, typename PlainObjectType>
691 struct mapbase_evaluator : evaluator_base<Derived>
692 {
693  typedef Derived XprType;
694  typedef typename XprType::PointerType PointerType;
695  typedef typename XprType::Scalar Scalar;
696  typedef typename XprType::CoeffReturnType CoeffReturnType;
697 
698  enum {
699  IsRowMajor = XprType::RowsAtCompileTime,
700  ColsAtCompileTime = XprType::ColsAtCompileTime,
701  CoeffReadCost = NumTraits<Scalar>::ReadCost
702  };
703 
704  EIGEN_DEVICE_FUNC explicit mapbase_evaluator(const XprType& map)
705  : m_data(const_cast<PointerType>(map.data())),
706  m_xpr(map)
707  {
708  EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(evaluator<Derived>::Flags&PacketAccessBit, internal::inner_stride_at_compile_time<Derived>::ret==1),
709  PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
710  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
711  }
712 
713  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
714  CoeffReturnType coeff(Index row, Index col) const
715  {
716  return m_data[col * m_xpr.colStride() + row * m_xpr.rowStride()];
717  }
718 
719  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
720  CoeffReturnType coeff(Index index) const
721  {
722  return m_data[index * m_xpr.innerStride()];
723  }
724 
725  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
726  Scalar& coeffRef(Index row, Index col)
727  {
728  return m_data[col * m_xpr.colStride() + row * m_xpr.rowStride()];
729  }
730 
731  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
732  Scalar& coeffRef(Index index)
733  {
734  return m_data[index * m_xpr.innerStride()];
735  }
736 
737  template<int LoadMode, typename PacketType>
738  EIGEN_STRONG_INLINE
739  PacketType packet(Index row, Index col) const
740  {
741  PointerType ptr = m_data + row * m_xpr.rowStride() + col * m_xpr.colStride();
742  return internal::ploadt<PacketType, LoadMode>(ptr);
743  }
744 
745  template<int LoadMode, typename PacketType>
746  EIGEN_STRONG_INLINE
747  PacketType packet(Index index) const
748  {
749  return internal::ploadt<PacketType, LoadMode>(m_data + index * m_xpr.innerStride());
750  }
751 
752  template<int StoreMode, typename PacketType>
753  EIGEN_STRONG_INLINE
754  void writePacket(Index row, Index col, const PacketType& x)
755  {
756  PointerType ptr = m_data + row * m_xpr.rowStride() + col * m_xpr.colStride();
757  return internal::pstoret<Scalar, PacketType, StoreMode>(ptr, x);
758  }
759 
760  template<int StoreMode, typename PacketType>
761  EIGEN_STRONG_INLINE
762  void writePacket(Index index, const PacketType& x)
763  {
764  internal::pstoret<Scalar, PacketType, StoreMode>(m_data + index * m_xpr.innerStride(), x);
765  }
766 
767 protected:
768  PointerType m_data;
769  const XprType& m_xpr;
770 };
771 
772 template<typename PlainObjectType, int MapOptions, typename StrideType>
773 struct evaluator<Map<PlainObjectType, MapOptions, StrideType> >
774  : public mapbase_evaluator<Map<PlainObjectType, MapOptions, StrideType>, PlainObjectType>
775 {
776  typedef Map<PlainObjectType, MapOptions, StrideType> XprType;
777  typedef typename XprType::Scalar Scalar;
778  // TODO: should check for smaller packet types once we can handle multi-sized packet types
779  typedef typename packet_traits<Scalar>::type PacketScalar;
780 
781  enum {
782  InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0
783  ? int(PlainObjectType::InnerStrideAtCompileTime)
784  : int(StrideType::InnerStrideAtCompileTime),
785  OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0
786  ? int(PlainObjectType::OuterStrideAtCompileTime)
787  : int(StrideType::OuterStrideAtCompileTime),
788  HasNoInnerStride = InnerStrideAtCompileTime == 1,
789  HasNoOuterStride = StrideType::OuterStrideAtCompileTime == 0,
790  HasNoStride = HasNoInnerStride && HasNoOuterStride,
791  IsDynamicSize = PlainObjectType::SizeAtCompileTime==Dynamic,
792 
793  PacketAccessMask = bool(HasNoInnerStride) ? ~int(0) : ~int(PacketAccessBit),
794  LinearAccessMask = bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime) ? ~int(0) : ~int(LinearAccessBit),
795  Flags = int( evaluator<PlainObjectType>::Flags) & (LinearAccessMask&PacketAccessMask),
796 
797  Alignment = int(MapOptions)&int(AlignedMask)
798  };
799 
800  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& map)
801  : mapbase_evaluator<XprType, PlainObjectType>(map)
802  { }
803 };
804 
805 // -------------------- Ref --------------------
806 
807 template<typename PlainObjectType, int RefOptions, typename StrideType>
808 struct evaluator<Ref<PlainObjectType, RefOptions, StrideType> >
809  : public mapbase_evaluator<Ref<PlainObjectType, RefOptions, StrideType>, PlainObjectType>
810 {
811  typedef Ref<PlainObjectType, RefOptions, StrideType> XprType;
812 
813  enum {
814  Flags = evaluator<Map<PlainObjectType, RefOptions, StrideType> >::Flags,
815  Alignment = evaluator<Map<PlainObjectType, RefOptions, StrideType> >::Alignment
816  };
817 
818  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& ref)
819  : mapbase_evaluator<XprType, PlainObjectType>(ref)
820  { }
821 };
822 
823 // -------------------- Block --------------------
824 
825 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel,
826  bool HasDirectAccess = internal::has_direct_access<ArgType>::ret> struct block_evaluator;
827 
828 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
829 struct evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
830  : block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel>
831 {
832  typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
833  typedef typename XprType::Scalar Scalar;
834  // TODO: should check for smaller packet types once we can handle multi-sized packet types
835  typedef typename packet_traits<Scalar>::type PacketScalar;
836 
837  enum {
838  CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
839 
840  RowsAtCompileTime = traits<XprType>::RowsAtCompileTime,
841  ColsAtCompileTime = traits<XprType>::ColsAtCompileTime,
842  MaxRowsAtCompileTime = traits<XprType>::MaxRowsAtCompileTime,
843  MaxColsAtCompileTime = traits<XprType>::MaxColsAtCompileTime,
844 
845  ArgTypeIsRowMajor = (int(evaluator<ArgType>::Flags)&RowMajorBit) != 0,
846  IsRowMajor = (MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1) ? 1
847  : (MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1) ? 0
848  : ArgTypeIsRowMajor,
849  HasSameStorageOrderAsArgType = (IsRowMajor == ArgTypeIsRowMajor),
850  InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
851  InnerStrideAtCompileTime = HasSameStorageOrderAsArgType
852  ? int(inner_stride_at_compile_time<ArgType>::ret)
853  : int(outer_stride_at_compile_time<ArgType>::ret),
854  OuterStrideAtCompileTime = HasSameStorageOrderAsArgType
855  ? int(outer_stride_at_compile_time<ArgType>::ret)
856  : int(inner_stride_at_compile_time<ArgType>::ret),
857  MaskPacketAccessBit = (InnerStrideAtCompileTime == 1) ? PacketAccessBit : 0,
858 
859  FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (evaluator<ArgType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0,
860  FlagsRowMajorBit = XprType::Flags&RowMajorBit,
861  Flags0 = evaluator<ArgType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
863  MaskPacketAccessBit),
864  Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit,
865 
866  PacketAlignment = unpacket_traits<PacketScalar>::alignment,
867  Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0,
868  Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<ArgType>::Alignment, Alignment0)
869  };
870  typedef block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel> block_evaluator_type;
871  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& block) : block_evaluator_type(block)
872  {
873  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
874  }
875 };
876 
877 // no direct-access => dispatch to a unary evaluator
878 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
879 struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAccess*/ false>
880  : unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
881 {
882  typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
883 
884  EIGEN_DEVICE_FUNC explicit block_evaluator(const XprType& block)
885  : unary_evaluator<XprType>(block)
886  {}
887 };
888 
889 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
890 struct unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IndexBased>
891  : evaluator_base<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
892 {
893  typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
894 
895  EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& block)
896  : m_argImpl(block.nestedExpression()),
897  m_startRow(block.startRow()),
898  m_startCol(block.startCol())
899  { }
900 
901  typedef typename XprType::Scalar Scalar;
902  typedef typename XprType::CoeffReturnType CoeffReturnType;
903 
904  enum {
905  RowsAtCompileTime = XprType::RowsAtCompileTime
906  };
907 
908  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
909  CoeffReturnType coeff(Index row, Index col) const
910  {
911  return m_argImpl.coeff(m_startRow.value() + row, m_startCol.value() + col);
912  }
913 
914  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
915  CoeffReturnType coeff(Index index) const
916  {
917  return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
918  }
919 
920  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
921  Scalar& coeffRef(Index row, Index col)
922  {
923  return m_argImpl.coeffRef(m_startRow.value() + row, m_startCol.value() + col);
924  }
925 
926  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
927  Scalar& coeffRef(Index index)
928  {
929  return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
930  }
931 
932  template<int LoadMode, typename PacketType>
933  EIGEN_STRONG_INLINE
934  PacketType packet(Index row, Index col) const
935  {
936  return m_argImpl.template packet<LoadMode,PacketType>(m_startRow.value() + row, m_startCol.value() + col);
937  }
938 
939  template<int LoadMode, typename PacketType>
940  EIGEN_STRONG_INLINE
941  PacketType packet(Index index) const
942  {
943  return packet<LoadMode,PacketType>(RowsAtCompileTime == 1 ? 0 : index,
944  RowsAtCompileTime == 1 ? index : 0);
945  }
946 
947  template<int StoreMode, typename PacketType>
948  EIGEN_STRONG_INLINE
949  void writePacket(Index row, Index col, const PacketType& x)
950  {
951  return m_argImpl.template writePacket<StoreMode,PacketType>(m_startRow.value() + row, m_startCol.value() + col, x);
952  }
953 
954  template<int StoreMode, typename PacketType>
955  EIGEN_STRONG_INLINE
956  void writePacket(Index index, const PacketType& x)
957  {
958  return writePacket<StoreMode,PacketType>(RowsAtCompileTime == 1 ? 0 : index,
959  RowsAtCompileTime == 1 ? index : 0,
960  x);
961  }
962 
963 protected:
964  evaluator<ArgType> m_argImpl;
965  const variable_if_dynamic<Index, (ArgType::RowsAtCompileTime == 1 && BlockRows==1) ? 0 : Dynamic> m_startRow;
966  const variable_if_dynamic<Index, (ArgType::ColsAtCompileTime == 1 && BlockCols==1) ? 0 : Dynamic> m_startCol;
967 };
968 
969 // TODO: This evaluator does not actually use the child evaluator;
970 // all action is via the data() as returned by the Block expression.
971 
972 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
973 struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAccess */ true>
974  : mapbase_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>,
975  typename Block<ArgType, BlockRows, BlockCols, InnerPanel>::PlainObject>
976 {
977  typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
978  typedef typename XprType::Scalar Scalar;
979 
980  EIGEN_DEVICE_FUNC explicit block_evaluator(const XprType& block)
981  : mapbase_evaluator<XprType, typename XprType::PlainObject>(block)
982  {
983  // TODO: for the 3.3 release, this should be turned to an internal assertion, but let's keep it as is for the beta lifetime
984  eigen_assert(((internal::UIntPtr(block.data()) % EIGEN_PLAIN_ENUM_MAX(1,evaluator<XprType>::Alignment)) == 0) && "data is not aligned");
985  }
986 };
987 
988 
989 // -------------------- Select --------------------
990 // NOTE shall we introduce a ternary_evaluator?
991 
992 // TODO enable vectorization for Select
993 template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
994 struct evaluator<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
995  : evaluator_base<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
996 {
997  typedef Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> XprType;
998  enum {
999  CoeffReadCost = evaluator<ConditionMatrixType>::CoeffReadCost
1000  + EIGEN_PLAIN_ENUM_MAX(evaluator<ThenMatrixType>::CoeffReadCost,
1001  evaluator<ElseMatrixType>::CoeffReadCost),
1002 
1003  Flags = (unsigned int)evaluator<ThenMatrixType>::Flags & evaluator<ElseMatrixType>::Flags & HereditaryBits,
1004 
1005  Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<ThenMatrixType>::Alignment, evaluator<ElseMatrixType>::Alignment)
1006  };
1007 
1008  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& select)
1009  : m_conditionImpl(select.conditionMatrix()),
1010  m_thenImpl(select.thenMatrix()),
1011  m_elseImpl(select.elseMatrix())
1012  {
1013  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
1014  }
1015 
1016  typedef typename XprType::CoeffReturnType CoeffReturnType;
1017 
1018  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1019  CoeffReturnType coeff(Index row, Index col) const
1020  {
1021  if (m_conditionImpl.coeff(row, col))
1022  return m_thenImpl.coeff(row, col);
1023  else
1024  return m_elseImpl.coeff(row, col);
1025  }
1026 
1027  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1028  CoeffReturnType coeff(Index index) const
1029  {
1030  if (m_conditionImpl.coeff(index))
1031  return m_thenImpl.coeff(index);
1032  else
1033  return m_elseImpl.coeff(index);
1034  }
1035 
1036 protected:
1037  evaluator<ConditionMatrixType> m_conditionImpl;
1038  evaluator<ThenMatrixType> m_thenImpl;
1039  evaluator<ElseMatrixType> m_elseImpl;
1040 };
1041 
1042 
1043 // -------------------- Replicate --------------------
1044 
1045 template<typename ArgType, int RowFactor, int ColFactor>
1046 struct unary_evaluator<Replicate<ArgType, RowFactor, ColFactor> >
1047  : evaluator_base<Replicate<ArgType, RowFactor, ColFactor> >
1048 {
1049  typedef Replicate<ArgType, RowFactor, ColFactor> XprType;
1050  typedef typename XprType::CoeffReturnType CoeffReturnType;
1051  enum {
1052  Factor = (RowFactor==Dynamic || ColFactor==Dynamic) ? Dynamic : RowFactor*ColFactor
1053  };
1054  typedef typename internal::nested_eval<ArgType,Factor>::type ArgTypeNested;
1055  typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
1056 
1057  enum {
1058  CoeffReadCost = evaluator<ArgTypeNestedCleaned>::CoeffReadCost,
1059  LinearAccessMask = XprType::IsVectorAtCompileTime ? LinearAccessBit : 0,
1060  Flags = (evaluator<ArgTypeNestedCleaned>::Flags & (HereditaryBits|LinearAccessMask) & ~RowMajorBit) | (traits<XprType>::Flags & RowMajorBit),
1061 
1062  Alignment = evaluator<ArgTypeNestedCleaned>::Alignment
1063  };
1064 
1065  EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& replicate)
1066  : m_arg(replicate.nestedExpression()),
1067  m_argImpl(m_arg),
1068  m_rows(replicate.nestedExpression().rows()),
1069  m_cols(replicate.nestedExpression().cols())
1070  {}
1071 
1072  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1073  CoeffReturnType coeff(Index row, Index col) const
1074  {
1075  // try to avoid using modulo; this is a pure optimization strategy
1076  const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0
1077  : RowFactor==1 ? row
1078  : row % m_rows.value();
1079  const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0
1080  : ColFactor==1 ? col
1081  : col % m_cols.value();
1082 
1083  return m_argImpl.coeff(actual_row, actual_col);
1084  }
1085 
1086  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1087  CoeffReturnType coeff(Index index) const
1088  {
1089  // try to avoid using modulo; this is a pure optimization strategy
1090  const Index actual_index = internal::traits<XprType>::RowsAtCompileTime==1
1091  ? (ColFactor==1 ? index : index%m_cols.value())
1092  : (RowFactor==1 ? index : index%m_rows.value());
1093 
1094  return m_argImpl.coeff(actual_index);
1095  }
1096 
1097  template<int LoadMode, typename PacketType>
1098  EIGEN_STRONG_INLINE
1099  PacketType packet(Index row, Index col) const
1100  {
1101  const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0
1102  : RowFactor==1 ? row
1103  : row % m_rows.value();
1104  const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0
1105  : ColFactor==1 ? col
1106  : col % m_cols.value();
1107 
1108  return m_argImpl.template packet<LoadMode,PacketType>(actual_row, actual_col);
1109  }
1110 
1111  template<int LoadMode, typename PacketType>
1112  EIGEN_STRONG_INLINE
1113  PacketType packet(Index index) const
1114  {
1115  const Index actual_index = internal::traits<XprType>::RowsAtCompileTime==1
1116  ? (ColFactor==1 ? index : index%m_cols.value())
1117  : (RowFactor==1 ? index : index%m_rows.value());
1118 
1119  return m_argImpl.template packet<LoadMode,PacketType>(actual_index);
1120  }
1121 
1122 protected:
1123  const ArgTypeNested m_arg;
1124  evaluator<ArgTypeNestedCleaned> m_argImpl;
1125  const variable_if_dynamic<Index, ArgType::RowsAtCompileTime> m_rows;
1126  const variable_if_dynamic<Index, ArgType::ColsAtCompileTime> m_cols;
1127 };
1128 
1129 
1130 // -------------------- PartialReduxExpr --------------------
1131 
1132 template< typename ArgType, typename MemberOp, int Direction>
1133 struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
1134  : evaluator_base<PartialReduxExpr<ArgType, MemberOp, Direction> >
1135 {
1136  typedef PartialReduxExpr<ArgType, MemberOp, Direction> XprType;
1137  typedef typename internal::nested_eval<ArgType,1>::type ArgTypeNested;
1138  typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
1139  typedef typename ArgType::Scalar InputScalar;
1140  typedef typename XprType::Scalar Scalar;
1141  enum {
1142  TraversalSize = Direction==int(Vertical) ? int(ArgType::RowsAtCompileTime) : int(ArgType::ColsAtCompileTime)
1143  };
1144  typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
1145  enum {
1146  CoeffReadCost = TraversalSize==Dynamic ? HugeCost
1147  : TraversalSize * evaluator<ArgType>::CoeffReadCost + int(CostOpType::value),
1148 
1149  Flags = (traits<XprType>::Flags&RowMajorBit) | (evaluator<ArgType>::Flags&(HereditaryBits&(~RowMajorBit))) | LinearAccessBit,
1150 
1151  Alignment = 0 // FIXME this will need to be improved once PartialReduxExpr is vectorized
1152  };
1153 
1154  EIGEN_DEVICE_FUNC explicit evaluator(const XprType xpr)
1155  : m_arg(xpr.nestedExpression()), m_functor(xpr.functor())
1156  {
1157  EIGEN_INTERNAL_CHECK_COST_VALUE(TraversalSize==Dynamic ? HugeCost : int(CostOpType::value));
1158  EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
1159  }
1160 
1161  typedef typename XprType::CoeffReturnType CoeffReturnType;
1162 
1163  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1164  const Scalar coeff(Index i, Index j) const
1165  {
1166  if (Direction==Vertical)
1167  return m_functor(m_arg.col(j));
1168  else
1169  return m_functor(m_arg.row(i));
1170  }
1171 
1172  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1173  const Scalar coeff(Index index) const
1174  {
1175  if (Direction==Vertical)
1176  return m_functor(m_arg.col(index));
1177  else
1178  return m_functor(m_arg.row(index));
1179  }
1180 
1181 protected:
1182  const ArgTypeNested m_arg;
1183  const MemberOp m_functor;
1184 };
1185 
1186 
1187 // -------------------- MatrixWrapper and ArrayWrapper --------------------
1188 //
1189 // evaluator_wrapper_base<T> is a common base class for the
1190 // MatrixWrapper and ArrayWrapper evaluators.
1191 
1192 template<typename XprType>
1193 struct evaluator_wrapper_base
1194  : evaluator_base<XprType>
1195 {
1196  typedef typename remove_all<typename XprType::NestedExpressionType>::type ArgType;
1197  enum {
1198  CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
1199  Flags = evaluator<ArgType>::Flags,
1200  Alignment = evaluator<ArgType>::Alignment
1201  };
1202 
1203  EIGEN_DEVICE_FUNC explicit evaluator_wrapper_base(const ArgType& arg) : m_argImpl(arg) {}
1204 
1205  typedef typename ArgType::Scalar Scalar;
1206  typedef typename ArgType::CoeffReturnType CoeffReturnType;
1207 
1208  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1209  CoeffReturnType coeff(Index row, Index col) const
1210  {
1211  return m_argImpl.coeff(row, col);
1212  }
1213 
1214  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1215  CoeffReturnType coeff(Index index) const
1216  {
1217  return m_argImpl.coeff(index);
1218  }
1219 
1220  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1221  Scalar& coeffRef(Index row, Index col)
1222  {
1223  return m_argImpl.coeffRef(row, col);
1224  }
1225 
1226  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1227  Scalar& coeffRef(Index index)
1228  {
1229  return m_argImpl.coeffRef(index);
1230  }
1231 
1232  template<int LoadMode, typename PacketType>
1233  EIGEN_STRONG_INLINE
1234  PacketType packet(Index row, Index col) const
1235  {
1236  return m_argImpl.template packet<LoadMode,PacketType>(row, col);
1237  }
1238 
1239  template<int LoadMode, typename PacketType>
1240  EIGEN_STRONG_INLINE
1241  PacketType packet(Index index) const
1242  {
1243  return m_argImpl.template packet<LoadMode,PacketType>(index);
1244  }
1245 
1246  template<int StoreMode, typename PacketType>
1247  EIGEN_STRONG_INLINE
1248  void writePacket(Index row, Index col, const PacketType& x)
1249  {
1250  m_argImpl.template writePacket<StoreMode>(row, col, x);
1251  }
1252 
1253  template<int StoreMode, typename PacketType>
1254  EIGEN_STRONG_INLINE
1255  void writePacket(Index index, const PacketType& x)
1256  {
1257  m_argImpl.template writePacket<StoreMode>(index, x);
1258  }
1259 
1260 protected:
1261  evaluator<ArgType> m_argImpl;
1262 };
1263 
1264 template<typename TArgType>
1265 struct unary_evaluator<MatrixWrapper<TArgType> >
1266  : evaluator_wrapper_base<MatrixWrapper<TArgType> >
1267 {
1268  typedef MatrixWrapper<TArgType> XprType;
1269 
1270  EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& wrapper)
1271  : evaluator_wrapper_base<MatrixWrapper<TArgType> >(wrapper.nestedExpression())
1272  { }
1273 };
1274 
1275 template<typename TArgType>
1276 struct unary_evaluator<ArrayWrapper<TArgType> >
1277  : evaluator_wrapper_base<ArrayWrapper<TArgType> >
1278 {
1279  typedef ArrayWrapper<TArgType> XprType;
1280 
1281  EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& wrapper)
1282  : evaluator_wrapper_base<ArrayWrapper<TArgType> >(wrapper.nestedExpression())
1283  { }
1284 };
1285 
1286 
1287 // -------------------- Reverse --------------------
1288 
1289 // defined in Reverse.h:
1290 template<typename PacketType, bool ReversePacket> struct reverse_packet_cond;
1291 
1292 template<typename ArgType, int Direction>
1293 struct unary_evaluator<Reverse<ArgType, Direction> >
1294  : evaluator_base<Reverse<ArgType, Direction> >
1295 {
1296  typedef Reverse<ArgType, Direction> XprType;
1297  typedef typename XprType::Scalar Scalar;
1298  typedef typename XprType::CoeffReturnType CoeffReturnType;
1299 
1300  enum {
1301  IsRowMajor = XprType::IsRowMajor,
1302  IsColMajor = !IsRowMajor,
1303  ReverseRow = (Direction == Vertical) || (Direction == BothDirections),
1304  ReverseCol = (Direction == Horizontal) || (Direction == BothDirections),
1305  ReversePacket = (Direction == BothDirections)
1306  || ((Direction == Vertical) && IsColMajor)
1307  || ((Direction == Horizontal) && IsRowMajor),
1308 
1309  CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
1310 
1311  // let's enable LinearAccess only with vectorization because of the product overhead
1312  // FIXME enable DirectAccess with negative strides?
1313  Flags0 = evaluator<ArgType>::Flags,
1314  LinearAccess = ( (Direction==BothDirections) && (int(Flags0)&PacketAccessBit) )
1315  || ((ReverseRow && XprType::ColsAtCompileTime==1) || (ReverseCol && XprType::RowsAtCompileTime==1))
1316  ? LinearAccessBit : 0,
1317 
1318  Flags = int(Flags0) & (HereditaryBits | PacketAccessBit | LinearAccess),
1319 
1320  Alignment = 0 // FIXME in some rare cases, Alignment could be preserved, like a Vector4f.
1321  };
1322 
1323  EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& reverse)
1324  : m_argImpl(reverse.nestedExpression()),
1325  m_rows(ReverseRow ? reverse.nestedExpression().rows() : 1),
1326  m_cols(ReverseCol ? reverse.nestedExpression().cols() : 1)
1327  { }
1328 
1329  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1330  CoeffReturnType coeff(Index row, Index col) const
1331  {
1332  return m_argImpl.coeff(ReverseRow ? m_rows.value() - row - 1 : row,
1333  ReverseCol ? m_cols.value() - col - 1 : col);
1334  }
1335 
1336  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1337  CoeffReturnType coeff(Index index) const
1338  {
1339  return m_argImpl.coeff(m_rows.value() * m_cols.value() - index - 1);
1340  }
1341 
1342  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1343  Scalar& coeffRef(Index row, Index col)
1344  {
1345  return m_argImpl.coeffRef(ReverseRow ? m_rows.value() - row - 1 : row,
1346  ReverseCol ? m_cols.value() - col - 1 : col);
1347  }
1348 
1349  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1350  Scalar& coeffRef(Index index)
1351  {
1352  return m_argImpl.coeffRef(m_rows.value() * m_cols.value() - index - 1);
1353  }
1354 
1355  template<int LoadMode, typename PacketType>
1356  EIGEN_STRONG_INLINE
1357  PacketType packet(Index row, Index col) const
1358  {
1359  enum {
1360  PacketSize = unpacket_traits<PacketType>::size,
1361  OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1,
1362  OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1
1363  };
1364  typedef internal::reverse_packet_cond<PacketType,ReversePacket> reverse_packet;
1365  return reverse_packet::run(m_argImpl.template packet<LoadMode,PacketType>(
1366  ReverseRow ? m_rows.value() - row - OffsetRow : row,
1367  ReverseCol ? m_cols.value() - col - OffsetCol : col));
1368  }
1369 
1370  template<int LoadMode, typename PacketType>
1371  EIGEN_STRONG_INLINE
1372  PacketType packet(Index index) const
1373  {
1374  enum { PacketSize = unpacket_traits<PacketType>::size };
1375  return preverse(m_argImpl.template packet<LoadMode,PacketType>(m_rows.value() * m_cols.value() - index - PacketSize));
1376  }
1377 
1378  template<int LoadMode, typename PacketType>
1379  EIGEN_STRONG_INLINE
1380  void writePacket(Index row, Index col, const PacketType& x)
1381  {
1382  // FIXME we could factorize some code with packet(i,j)
1383  enum {
1384  PacketSize = unpacket_traits<PacketType>::size,
1385  OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1,
1386  OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1
1387  };
1388  typedef internal::reverse_packet_cond<PacketType,ReversePacket> reverse_packet;
1389  m_argImpl.template writePacket<LoadMode>(
1390  ReverseRow ? m_rows.value() - row - OffsetRow : row,
1391  ReverseCol ? m_cols.value() - col - OffsetCol : col,
1392  reverse_packet::run(x));
1393  }
1394 
1395  template<int LoadMode, typename PacketType>
1396  EIGEN_STRONG_INLINE
1397  void writePacket(Index index, const PacketType& x)
1398  {
1399  enum { PacketSize = unpacket_traits<PacketType>::size };
1400  m_argImpl.template writePacket<LoadMode>
1401  (m_rows.value() * m_cols.value() - index - PacketSize, preverse(x));
1402  }
1403 
1404 protected:
1405  evaluator<ArgType> m_argImpl;
1406 
1407  // If we do not reverse rows, then we do not need to know the number of rows; same for columns
1408  // Nonetheless, in this case it is important to set to 1 such that the coeff(index) method works fine for vectors.
1409  const variable_if_dynamic<Index, ReverseRow ? ArgType::RowsAtCompileTime : 1> m_rows;
1410  const variable_if_dynamic<Index, ReverseCol ? ArgType::ColsAtCompileTime : 1> m_cols;
1411 };
1412 
1413 
1414 // -------------------- Diagonal --------------------
1415 
1416 template<typename ArgType, int DiagIndex>
1417 struct evaluator<Diagonal<ArgType, DiagIndex> >
1418  : evaluator_base<Diagonal<ArgType, DiagIndex> >
1419 {
1420  typedef Diagonal<ArgType, DiagIndex> XprType;
1421 
1422  enum {
1423  CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
1424 
1425  Flags = (unsigned int)(evaluator<ArgType>::Flags & (HereditaryBits | DirectAccessBit) & ~RowMajorBit) | LinearAccessBit,
1426 
1427  Alignment = 0
1428  };
1429 
1430  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& diagonal)
1431  : m_argImpl(diagonal.nestedExpression()),
1432  m_index(diagonal.index())
1433  { }
1434 
1435  typedef typename XprType::Scalar Scalar;
1436  // FIXME having to check whether ArgType is sparse here i not very nice.
1437  typedef typename internal::conditional<!internal::is_same<typename ArgType::StorageKind,Sparse>::value,
1438  typename XprType::CoeffReturnType,Scalar>::type CoeffReturnType;
1439 
1440  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1441  CoeffReturnType coeff(Index row, Index) const
1442  {
1443  return m_argImpl.coeff(row + rowOffset(), row + colOffset());
1444  }
1445 
1446  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1447  CoeffReturnType coeff(Index index) const
1448  {
1449  return m_argImpl.coeff(index + rowOffset(), index + colOffset());
1450  }
1451 
1452  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1453  Scalar& coeffRef(Index row, Index)
1454  {
1455  return m_argImpl.coeffRef(row + rowOffset(), row + colOffset());
1456  }
1457 
1458  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
1459  Scalar& coeffRef(Index index)
1460  {
1461  return m_argImpl.coeffRef(index + rowOffset(), index + colOffset());
1462  }
1463 
1464 protected:
1465  evaluator<ArgType> m_argImpl;
1466  const internal::variable_if_dynamicindex<Index, XprType::DiagIndex> m_index;
1467 
1468 private:
1469  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value() > 0 ? 0 : -m_index.value(); }
1470  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value() > 0 ? m_index.value() : 0; }
1471 };
1472 
1473 
1474 //----------------------------------------------------------------------
1475 // deprecated code
1476 //----------------------------------------------------------------------
1477 
1478 // -------------------- EvalToTemp --------------------
1479 
1480 // expression class for evaluating nested expression to a temporary
1481 
1482 template<typename ArgType> class EvalToTemp;
1483 
1484 template<typename ArgType>
1485 struct traits<EvalToTemp<ArgType> >
1486  : public traits<ArgType>
1487 { };
1488 
1489 template<typename ArgType>
1490 class EvalToTemp
1491  : public dense_xpr_base<EvalToTemp<ArgType> >::type
1492 {
1493  public:
1494 
1495  typedef typename dense_xpr_base<EvalToTemp>::type Base;
1496  EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp)
1497 
1498  explicit EvalToTemp(const ArgType& arg)
1499  : m_arg(arg)
1500  { }
1501 
1502  const ArgType& arg() const
1503  {
1504  return m_arg;
1505  }
1506 
1507  Index rows() const
1508  {
1509  return m_arg.rows();
1510  }
1511 
1512  Index cols() const
1513  {
1514  return m_arg.cols();
1515  }
1516 
1517  private:
1518  const ArgType& m_arg;
1519 };
1520 
1521 template<typename ArgType>
1522 struct evaluator<EvalToTemp<ArgType> >
1523  : public evaluator<typename ArgType::PlainObject>
1524 {
1525  typedef EvalToTemp<ArgType> XprType;
1526  typedef typename ArgType::PlainObject PlainObject;
1527  typedef evaluator<PlainObject> Base;
1528 
1529  EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
1530  : m_result(xpr.arg())
1531  {
1532  ::new (static_cast<Base*>(this)) Base(m_result);
1533  }
1534 
1535  // This constructor is used when nesting an EvalTo evaluator in another evaluator
1536  EIGEN_DEVICE_FUNC evaluator(const ArgType& arg)
1537  : m_result(arg)
1538  {
1539  ::new (static_cast<Base*>(this)) Base(m_result);
1540  }
1541 
1542 protected:
1543  PlainObject m_result;
1544 };
1545 
1546 } // namespace internal
1547 
1548 } // end namespace Eigen
1549 
1550 #endif // EIGEN_COREEVALUATORS_H
const int HugeCost
Definition: Constants.h:39
Definition: Constants.h:265
const unsigned int DirectAccessBit
Definition: Constants.h:150
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_arg_op< typename Derived::Scalar >, const Derived > arg(const Eigen::ArrayBase< Derived > &x)
Namespace containing all symbols from the Eigen library.
Definition: Core:271
const unsigned int RowMajorBit
Definition: Constants.h:61
const unsigned int PacketAccessBit
Definition: Constants.h:89
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: XprHelper.h:35
Definition: Constants.h:268
Definition: Constants.h:271
Definition: Eigen_Colamd.h:50
const int Dynamic
Definition: Constants.h:21
const unsigned int EvalBeforeNestingBit
Definition: Constants.h:65
const unsigned int LinearAccessBit
Definition: Constants.h:125