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