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