MOAB  4.9.3pre
CoreEvaluators.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2011 Benoit Jacob <[email protected]>
00005 // Copyright (C) 2011-2014 Gael Guennebaud <[email protected]>
00006 // Copyright (C) 2011-2012 Jitse Niesen <[email protected]>
00007 //
00008 // This Source Code Form is subject to the terms of the Mozilla
00009 // Public License v. 2.0. If a copy of the MPL was not distributed
00010 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00011 
00012 
00013 #ifndef EIGEN_COREEVALUATORS_H
00014 #define EIGEN_COREEVALUATORS_H
00015 
00016 namespace Eigen {
00017   
00018 namespace internal {
00019 
00020 // This class returns the evaluator kind from the expression storage kind.
00021 // Default assumes index based accessors
00022 template<typename StorageKind>
00023 struct storage_kind_to_evaluator_kind {
00024   typedef IndexBased Kind;
00025 };
00026 
00027 // This class returns the evaluator shape from the expression storage kind.
00028 // It can be Dense, Sparse, Triangular, Diagonal, SelfAdjoint, Band, etc.
00029 template<typename StorageKind> struct storage_kind_to_shape;
00030 
00031 template<> struct storage_kind_to_shape<Dense>                  { typedef DenseShape Shape;           };
00032 template<> struct storage_kind_to_shape<SolverStorage>          { typedef SolverShape Shape;           };
00033 template<> struct storage_kind_to_shape<PermutationStorage>     { typedef PermutationShape Shape;     };
00034 template<> struct storage_kind_to_shape<TranspositionsStorage>  { typedef TranspositionsShape Shape;  };
00035 
00036 // Evaluators have to be specialized with respect to various criteria such as:
00037 //  - storage/structure/shape
00038 //  - scalar type
00039 //  - etc.
00040 // Therefore, we need specialization of evaluator providing additional template arguments for each kind of evaluators.
00041 // We currently distinguish the following kind of evaluators:
00042 // - unary_evaluator    for expressions taking only one arguments (CwiseUnaryOp, CwiseUnaryView, Transpose, MatrixWrapper, ArrayWrapper, Reverse, Replicate)
00043 // - binary_evaluator   for expression taking two arguments (CwiseBinaryOp)
00044 // - product_evaluator  for linear algebra products (Product); special case of binary_evaluator because it requires additional tags for dispatching.
00045 // - mapbase_evaluator  for Map, Block, Ref
00046 // - block_evaluator    for Block (special dispatching to a mapbase_evaluator or unary_evaluator)
00047 
00048 template< typename T,
00049           typename LhsKind   = typename evaluator_traits<typename T::Lhs>::Kind,
00050           typename RhsKind   = typename evaluator_traits<typename T::Rhs>::Kind,
00051           typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
00052           typename RhsScalar = typename traits<typename T::Rhs>::Scalar> struct binary_evaluator;
00053 
00054 template< typename T,
00055           typename Kind   = typename evaluator_traits<typename T::NestedExpression>::Kind,
00056           typename Scalar = typename T::Scalar> struct unary_evaluator;
00057           
00058 // evaluator_traits<T> contains traits for evaluator<T> 
00059 
00060 template<typename T>
00061 struct evaluator_traits_base
00062 {
00063   // by default, get evaluator kind and shape from storage
00064   typedef typename storage_kind_to_evaluator_kind<typename traits<T>::StorageKind>::Kind Kind;
00065   typedef typename storage_kind_to_shape<typename traits<T>::StorageKind>::Shape Shape;
00066 };
00067 
00068 // Default evaluator traits
00069 template<typename T>
00070 struct evaluator_traits : public evaluator_traits_base<T>
00071 {
00072 };
00073 
00074 template<typename T, typename Shape = typename evaluator_traits<T>::Shape >
00075 struct evaluator_assume_aliasing {
00076   static const bool value = false;
00077 };
00078 
00079 // By default, we assume a unary expression:
00080 template<typename T>
00081 struct evaluator : public unary_evaluator<T>
00082 {
00083   typedef unary_evaluator<T> Base;
00084   EIGEN_DEVICE_FUNC explicit evaluator(const T& xpr) : Base(xpr) {}
00085 };
00086 
00087 
00088 // TODO: Think about const-correctness
00089 template<typename T>
00090 struct evaluator<const T>
00091   : evaluator<T>
00092 {
00093   EIGEN_DEVICE_FUNC
00094   explicit evaluator(const T& xpr) : evaluator<T>(xpr) {}
00095 };
00096 
00097 // ---------- base class for all evaluators ----------
00098 
00099 template<typename ExpressionType>
00100 struct evaluator_base : public noncopyable
00101 {
00102   // TODO that's not very nice to have to propagate all these traits. They are currently only needed to handle outer,inner indices.
00103   typedef traits<ExpressionType> ExpressionTraits;
00104   
00105   enum {
00106     Alignment = 0
00107   };
00108 };
00109 
00110 // -------------------- Matrix and Array --------------------
00111 //
00112 // evaluator<PlainObjectBase> is a common base class for the
00113 // Matrix and Array evaluators.
00114 // Here we directly specialize evaluator. This is not really a unary expression, and it is, by definition, dense,
00115 // so no need for more sophisticated dispatching.
00116 
00117 template<typename Derived>
00118 struct evaluator<PlainObjectBase<Derived> >
00119   : evaluator_base<Derived>
00120 {
00121   typedef PlainObjectBase<Derived> PlainObjectType;
00122   typedef typename PlainObjectType::Scalar Scalar;
00123   typedef typename PlainObjectType::CoeffReturnType CoeffReturnType;
00124 
00125   enum {
00126     IsRowMajor = PlainObjectType::IsRowMajor,
00127     IsVectorAtCompileTime = PlainObjectType::IsVectorAtCompileTime,
00128     RowsAtCompileTime = PlainObjectType::RowsAtCompileTime,
00129     ColsAtCompileTime = PlainObjectType::ColsAtCompileTime,
00130     
00131     CoeffReadCost = NumTraits<Scalar>::ReadCost,
00132     Flags = traits<Derived>::EvaluatorFlags,
00133     Alignment = traits<Derived>::Alignment
00134   };
00135   
00136   EIGEN_DEVICE_FUNC evaluator()
00137     : m_data(0),
00138       m_outerStride(IsVectorAtCompileTime  ? 0 
00139                                            : int(IsRowMajor) ? ColsAtCompileTime 
00140                                            : RowsAtCompileTime)
00141   {
00142     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00143   }
00144   
00145   EIGEN_DEVICE_FUNC explicit evaluator(const PlainObjectType& m)
00146     : m_data(m.data()), m_outerStride(IsVectorAtCompileTime ? 0 : m.outerStride()) 
00147   {
00148     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00149   }
00150 
00151   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00152   CoeffReturnType coeff(Index row, Index col) const
00153   {
00154     if (IsRowMajor)
00155       return m_data[row * m_outerStride.value() + col];
00156     else
00157       return m_data[row + col * m_outerStride.value()];
00158   }
00159 
00160   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00161   CoeffReturnType coeff(Index index) const
00162   {
00163     return m_data[index];
00164   }
00165 
00166   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00167   Scalar& coeffRef(Index row, Index col)
00168   {
00169     if (IsRowMajor)
00170       return const_cast<Scalar*>(m_data)[row * m_outerStride.value() + col];
00171     else
00172       return const_cast<Scalar*>(m_data)[row + col * m_outerStride.value()];
00173   }
00174 
00175   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00176   Scalar& coeffRef(Index index)
00177   {
00178     return const_cast<Scalar*>(m_data)[index];
00179   }
00180 
00181   template<int LoadMode, typename PacketType>
00182   EIGEN_STRONG_INLINE
00183   PacketType packet(Index row, Index col) const
00184   {
00185     if (IsRowMajor)
00186       return ploadt<PacketType, LoadMode>(m_data + row * m_outerStride.value() + col);
00187     else
00188       return ploadt<PacketType, LoadMode>(m_data + row + col * m_outerStride.value());
00189   }
00190 
00191   template<int LoadMode, typename PacketType>
00192   EIGEN_STRONG_INLINE
00193   PacketType packet(Index index) const
00194   {
00195     return ploadt<PacketType, LoadMode>(m_data + index);
00196   }
00197 
00198   template<int StoreMode,typename PacketType>
00199   EIGEN_STRONG_INLINE
00200   void writePacket(Index row, Index col, const PacketType& x)
00201   {
00202     if (IsRowMajor)
00203       return pstoret<Scalar, PacketType, StoreMode>
00204                 (const_cast<Scalar*>(m_data) + row * m_outerStride.value() + col, x);
00205     else
00206       return pstoret<Scalar, PacketType, StoreMode>
00207                     (const_cast<Scalar*>(m_data) + row + col * m_outerStride.value(), x);
00208   }
00209 
00210   template<int StoreMode, typename PacketType>
00211   EIGEN_STRONG_INLINE
00212   void writePacket(Index index, const PacketType& x)
00213   {
00214     return pstoret<Scalar, PacketType, StoreMode>(const_cast<Scalar*>(m_data) + index, x);
00215   }
00216 
00217 protected:
00218   const Scalar *m_data;
00219 
00220   // We do not need to know the outer stride for vectors
00221   variable_if_dynamic<Index, IsVectorAtCompileTime  ? 0 
00222                                                     : int(IsRowMajor) ? ColsAtCompileTime 
00223                                                     : RowsAtCompileTime> m_outerStride;
00224 };
00225 
00226 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
00227 struct evaluator<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
00228   : evaluator<PlainObjectBase<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > >
00229 {
00230   typedef Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
00231   
00232   EIGEN_DEVICE_FUNC evaluator() {}
00233 
00234   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& m)
00235     : evaluator<PlainObjectBase<XprType> >(m) 
00236   { }
00237 };
00238 
00239 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
00240 struct evaluator<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
00241   : evaluator<PlainObjectBase<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > >
00242 {
00243   typedef Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> XprType;
00244 
00245   EIGEN_DEVICE_FUNC evaluator() {}
00246   
00247   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& m)
00248     : evaluator<PlainObjectBase<XprType> >(m) 
00249   { }
00250 };
00251 
00252 // -------------------- Transpose --------------------
00253 
00254 template<typename ArgType>
00255 struct unary_evaluator<Transpose<ArgType>, IndexBased>
00256   : evaluator_base<Transpose<ArgType> >
00257 {
00258   typedef Transpose<ArgType> XprType;
00259   
00260   enum {
00261     CoeffReadCost = evaluator<ArgType>::CoeffReadCost,    
00262     Flags = evaluator<ArgType>::Flags ^ RowMajorBit,
00263     Alignment = evaluator<ArgType>::Alignment
00264   };
00265 
00266   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& t) : m_argImpl(t.nestedExpression()) {}
00267 
00268   typedef typename XprType::Scalar Scalar;
00269   typedef typename XprType::CoeffReturnType CoeffReturnType;
00270 
00271   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00272   CoeffReturnType coeff(Index row, Index col) const
00273   {
00274     return m_argImpl.coeff(col, row);
00275   }
00276 
00277   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00278   CoeffReturnType coeff(Index index) const
00279   {
00280     return m_argImpl.coeff(index);
00281   }
00282 
00283   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00284   Scalar& coeffRef(Index row, Index col)
00285   {
00286     return m_argImpl.coeffRef(col, row);
00287   }
00288 
00289   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00290   typename XprType::Scalar& coeffRef(Index index)
00291   {
00292     return m_argImpl.coeffRef(index);
00293   }
00294 
00295   template<int LoadMode, typename PacketType>
00296   EIGEN_STRONG_INLINE
00297   PacketType packet(Index row, Index col) const
00298   {
00299     return m_argImpl.template packet<LoadMode,PacketType>(col, row);
00300   }
00301 
00302   template<int LoadMode, typename PacketType>
00303   EIGEN_STRONG_INLINE
00304   PacketType packet(Index index) const
00305   {
00306     return m_argImpl.template packet<LoadMode,PacketType>(index);
00307   }
00308 
00309   template<int StoreMode, typename PacketType>
00310   EIGEN_STRONG_INLINE
00311   void writePacket(Index row, Index col, const PacketType& x)
00312   {
00313     m_argImpl.template writePacket<StoreMode,PacketType>(col, row, x);
00314   }
00315 
00316   template<int StoreMode, typename PacketType>
00317   EIGEN_STRONG_INLINE
00318   void writePacket(Index index, const PacketType& x)
00319   {
00320     m_argImpl.template writePacket<StoreMode,PacketType>(index, x);
00321   }
00322 
00323 protected:
00324   evaluator<ArgType> m_argImpl;
00325 };
00326 
00327 // -------------------- CwiseNullaryOp --------------------
00328 // Like Matrix and Array, this is not really a unary expression, so we directly specialize evaluator.
00329 // Likewise, there is not need to more sophisticated dispatching here.
00330 
00331 template<typename NullaryOp, typename PlainObjectType>
00332 struct evaluator<CwiseNullaryOp<NullaryOp,PlainObjectType> >
00333   : evaluator_base<CwiseNullaryOp<NullaryOp,PlainObjectType> >
00334 {
00335   typedef CwiseNullaryOp<NullaryOp,PlainObjectType> XprType;
00336   typedef typename internal::remove_all<PlainObjectType>::type PlainObjectTypeCleaned;
00337   
00338   enum {
00339     CoeffReadCost = internal::functor_traits<NullaryOp>::Cost,
00340     
00341     Flags = (evaluator<PlainObjectTypeCleaned>::Flags
00342           &  (  HereditaryBits
00343               | (functor_has_linear_access<NullaryOp>::ret  ? LinearAccessBit : 0)
00344               | (functor_traits<NullaryOp>::PacketAccess    ? PacketAccessBit : 0)))
00345           | (functor_traits<NullaryOp>::IsRepeatable ? 0 : EvalBeforeNestingBit),
00346     Alignment = AlignedMax
00347   };
00348 
00349   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& n)
00350     : m_functor(n.functor()) 
00351   {
00352     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00353   }
00354 
00355   typedef typename XprType::CoeffReturnType CoeffReturnType;
00356 
00357   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00358   CoeffReturnType coeff(Index row, Index col) const
00359   {
00360     return m_functor(row, col);
00361   }
00362 
00363   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00364   CoeffReturnType coeff(Index index) const
00365   {
00366     return m_functor(index);
00367   }
00368 
00369   template<int LoadMode, typename PacketType>
00370   EIGEN_STRONG_INLINE
00371   PacketType packet(Index row, Index col) const
00372   {
00373     return m_functor.template packetOp<Index,PacketType>(row, col);
00374   }
00375 
00376   template<int LoadMode, typename PacketType>
00377   EIGEN_STRONG_INLINE
00378   PacketType packet(Index index) const
00379   {
00380     return m_functor.template packetOp<Index,PacketType>(index);
00381   }
00382 
00383 protected:
00384   const NullaryOp m_functor;
00385 };
00386 
00387 // -------------------- CwiseUnaryOp --------------------
00388 
00389 template<typename UnaryOp, typename ArgType>
00390 struct unary_evaluator<CwiseUnaryOp<UnaryOp, ArgType>, IndexBased >
00391   : evaluator_base<CwiseUnaryOp<UnaryOp, ArgType> >
00392 {
00393   typedef CwiseUnaryOp<UnaryOp, ArgType> XprType;
00394   
00395   enum {
00396     CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
00397     
00398     Flags = evaluator<ArgType>::Flags
00399           & (HereditaryBits | LinearAccessBit | (functor_traits<UnaryOp>::PacketAccess ? PacketAccessBit : 0)),
00400     Alignment = evaluator<ArgType>::Alignment
00401   };
00402 
00403   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00404   explicit unary_evaluator(const XprType& op)
00405     : m_functor(op.functor()), 
00406       m_argImpl(op.nestedExpression()) 
00407   {
00408     EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
00409     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00410   }
00411 
00412   typedef typename XprType::CoeffReturnType CoeffReturnType;
00413 
00414   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00415   CoeffReturnType coeff(Index row, Index col) const
00416   {
00417     return m_functor(m_argImpl.coeff(row, col));
00418   }
00419 
00420   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00421   CoeffReturnType coeff(Index index) const
00422   {
00423     return m_functor(m_argImpl.coeff(index));
00424   }
00425 
00426   template<int LoadMode, typename PacketType>
00427   EIGEN_STRONG_INLINE
00428   PacketType packet(Index row, Index col) const
00429   {
00430     return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(row, col));
00431   }
00432 
00433   template<int LoadMode, typename PacketType>
00434   EIGEN_STRONG_INLINE
00435   PacketType packet(Index index) const
00436   {
00437     return m_functor.packetOp(m_argImpl.template packet<LoadMode, PacketType>(index));
00438   }
00439 
00440 protected:
00441   const UnaryOp m_functor;
00442   evaluator<ArgType> m_argImpl;
00443 };
00444 
00445 // -------------------- CwiseBinaryOp --------------------
00446 
00447 // this is a binary expression
00448 template<typename BinaryOp, typename Lhs, typename Rhs>
00449 struct evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
00450   : public binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
00451 {
00452   typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
00453   typedef binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > Base;
00454   
00455   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) : Base(xpr) {}
00456 };
00457 
00458 template<typename BinaryOp, typename Lhs, typename Rhs>
00459 struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IndexBased>
00460   : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> >
00461 {
00462   typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
00463   
00464   enum {
00465     CoeffReadCost = evaluator<Lhs>::CoeffReadCost + evaluator<Rhs>::CoeffReadCost + functor_traits<BinaryOp>::Cost,
00466     
00467     LhsFlags = evaluator<Lhs>::Flags,
00468     RhsFlags = evaluator<Rhs>::Flags,
00469     SameType = is_same<typename Lhs::Scalar,typename Rhs::Scalar>::value,
00470     StorageOrdersAgree = (int(LhsFlags)&RowMajorBit)==(int(RhsFlags)&RowMajorBit),
00471     Flags0 = (int(LhsFlags) | int(RhsFlags)) & (
00472         HereditaryBits
00473       | (int(LhsFlags) & int(RhsFlags) &
00474            ( (StorageOrdersAgree ? LinearAccessBit : 0)
00475            | (functor_traits<BinaryOp>::PacketAccess && StorageOrdersAgree && SameType ? PacketAccessBit : 0)
00476            )
00477         )
00478      ),
00479     Flags = (Flags0 & ~RowMajorBit) | (LhsFlags & RowMajorBit),
00480     Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<Lhs>::Alignment,evaluator<Rhs>::Alignment)
00481   };
00482 
00483   EIGEN_DEVICE_FUNC explicit binary_evaluator(const XprType& xpr)
00484     : m_functor(xpr.functor()),
00485       m_lhsImpl(xpr.lhs()), 
00486       m_rhsImpl(xpr.rhs())  
00487   {
00488     EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
00489     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00490   }
00491 
00492   typedef typename XprType::CoeffReturnType CoeffReturnType;
00493 
00494   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00495   CoeffReturnType coeff(Index row, Index col) const
00496   {
00497     return m_functor(m_lhsImpl.coeff(row, col), m_rhsImpl.coeff(row, col));
00498   }
00499 
00500   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00501   CoeffReturnType coeff(Index index) const
00502   {
00503     return m_functor(m_lhsImpl.coeff(index), m_rhsImpl.coeff(index));
00504   }
00505 
00506   template<int LoadMode, typename PacketType>
00507   EIGEN_STRONG_INLINE
00508   PacketType packet(Index row, Index col) const
00509   {
00510     return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(row, col),
00511                               m_rhsImpl.template packet<LoadMode,PacketType>(row, col));
00512   }
00513 
00514   template<int LoadMode, typename PacketType>
00515   EIGEN_STRONG_INLINE
00516   PacketType packet(Index index) const
00517   {
00518     return m_functor.packetOp(m_lhsImpl.template packet<LoadMode,PacketType>(index),
00519                               m_rhsImpl.template packet<LoadMode,PacketType>(index));
00520   }
00521 
00522 protected:
00523   const BinaryOp m_functor;
00524   evaluator<Lhs> m_lhsImpl;
00525   evaluator<Rhs> m_rhsImpl;
00526 };
00527 
00528 // -------------------- CwiseUnaryView --------------------
00529 
00530 template<typename UnaryOp, typename ArgType>
00531 struct unary_evaluator<CwiseUnaryView<UnaryOp, ArgType>, IndexBased>
00532   : evaluator_base<CwiseUnaryView<UnaryOp, ArgType> >
00533 {
00534   typedef CwiseUnaryView<UnaryOp, ArgType> XprType;
00535   
00536   enum {
00537     CoeffReadCost = evaluator<ArgType>::CoeffReadCost + functor_traits<UnaryOp>::Cost,
00538     
00539     Flags = (evaluator<ArgType>::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit)),
00540     
00541     Alignment = 0 // FIXME it is not very clear why alignment is necessarily lost...
00542   };
00543 
00544   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
00545     : m_unaryOp(op.functor()), 
00546       m_argImpl(op.nestedExpression()) 
00547   {
00548     EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<UnaryOp>::Cost);
00549     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00550   }
00551 
00552   typedef typename XprType::Scalar Scalar;
00553   typedef typename XprType::CoeffReturnType CoeffReturnType;
00554 
00555   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00556   CoeffReturnType coeff(Index row, Index col) const
00557   {
00558     return m_unaryOp(m_argImpl.coeff(row, col));
00559   }
00560 
00561   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00562   CoeffReturnType coeff(Index index) const
00563   {
00564     return m_unaryOp(m_argImpl.coeff(index));
00565   }
00566 
00567   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00568   Scalar& coeffRef(Index row, Index col)
00569   {
00570     return m_unaryOp(m_argImpl.coeffRef(row, col));
00571   }
00572 
00573   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00574   Scalar& coeffRef(Index index)
00575   {
00576     return m_unaryOp(m_argImpl.coeffRef(index));
00577   }
00578 
00579 protected:
00580   const UnaryOp m_unaryOp;
00581   evaluator<ArgType> m_argImpl;
00582 };
00583 
00584 // -------------------- Map --------------------
00585 
00586 // FIXME perhaps the PlainObjectType could be provided by Derived::PlainObject ?
00587 // but that might complicate template specialization
00588 template<typename Derived, typename PlainObjectType>
00589 struct mapbase_evaluator;
00590 
00591 template<typename Derived, typename PlainObjectType>
00592 struct mapbase_evaluator : evaluator_base<Derived>
00593 {
00594   typedef Derived  XprType;
00595   typedef typename XprType::PointerType PointerType;
00596   typedef typename XprType::Scalar Scalar;
00597   typedef typename XprType::CoeffReturnType CoeffReturnType;
00598   
00599   enum {
00600     IsRowMajor = XprType::RowsAtCompileTime,
00601     ColsAtCompileTime = XprType::ColsAtCompileTime,
00602     CoeffReadCost = NumTraits<Scalar>::ReadCost
00603   };
00604   
00605   EIGEN_DEVICE_FUNC explicit mapbase_evaluator(const XprType& map)
00606     : m_data(const_cast<PointerType>(map.data())),  
00607       m_xpr(map)
00608   {
00609     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(evaluator<Derived>::Flags&PacketAccessBit, internal::inner_stride_at_compile_time<Derived>::ret==1),
00610                         PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
00611     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00612   }
00613  
00614   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00615   CoeffReturnType coeff(Index row, Index col) const
00616   {
00617     return m_data[col * m_xpr.colStride() + row * m_xpr.rowStride()];
00618   }
00619   
00620   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00621   CoeffReturnType coeff(Index index) const
00622   {
00623     return m_data[index * m_xpr.innerStride()];
00624   }
00625 
00626   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00627   Scalar& coeffRef(Index row, Index col)
00628   {
00629     return m_data[col * m_xpr.colStride() + row * m_xpr.rowStride()];
00630   }
00631   
00632   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00633   Scalar& coeffRef(Index index)
00634   {
00635     return m_data[index * m_xpr.innerStride()];
00636   }
00637  
00638   template<int LoadMode, typename PacketType>
00639   EIGEN_STRONG_INLINE
00640   PacketType packet(Index row, Index col) const 
00641   {
00642     PointerType ptr = m_data + row * m_xpr.rowStride() + col * m_xpr.colStride();
00643     return internal::ploadt<PacketType, LoadMode>(ptr);
00644   }
00645 
00646   template<int LoadMode, typename PacketType>
00647   EIGEN_STRONG_INLINE
00648   PacketType packet(Index index) const 
00649   {
00650     return internal::ploadt<PacketType, LoadMode>(m_data + index * m_xpr.innerStride());
00651   }
00652   
00653   template<int StoreMode, typename PacketType>
00654   EIGEN_STRONG_INLINE
00655   void writePacket(Index row, Index col, const PacketType& x) 
00656   {
00657     PointerType ptr = m_data + row * m_xpr.rowStride() + col * m_xpr.colStride();
00658     return internal::pstoret<Scalar, PacketType, StoreMode>(ptr, x);
00659   }
00660   
00661   template<int StoreMode, typename PacketType>
00662   EIGEN_STRONG_INLINE
00663   void writePacket(Index index, const PacketType& x) 
00664   {
00665     internal::pstoret<Scalar, PacketType, StoreMode>(m_data + index * m_xpr.innerStride(), x);
00666   }
00667  
00668 protected:
00669   PointerType m_data;
00670   const XprType& m_xpr;
00671 };
00672 
00673 template<typename PlainObjectType, int MapOptions, typename StrideType> 
00674 struct evaluator<Map<PlainObjectType, MapOptions, StrideType> >
00675   : public mapbase_evaluator<Map<PlainObjectType, MapOptions, StrideType>, PlainObjectType>
00676 {
00677   typedef Map<PlainObjectType, MapOptions, StrideType> XprType;
00678   typedef typename XprType::Scalar Scalar;
00679   // TODO: should check for smaller packet types once we can handle multi-sized packet types
00680   typedef typename packet_traits<Scalar>::type PacketScalar;
00681   
00682   enum {
00683     InnerStrideAtCompileTime = StrideType::InnerStrideAtCompileTime == 0
00684                              ? int(PlainObjectType::InnerStrideAtCompileTime)
00685                              : int(StrideType::InnerStrideAtCompileTime),
00686     OuterStrideAtCompileTime = StrideType::OuterStrideAtCompileTime == 0
00687                              ? int(PlainObjectType::OuterStrideAtCompileTime)
00688                              : int(StrideType::OuterStrideAtCompileTime),
00689     HasNoInnerStride = InnerStrideAtCompileTime == 1,
00690     HasNoOuterStride = StrideType::OuterStrideAtCompileTime == 0,
00691     HasNoStride = HasNoInnerStride && HasNoOuterStride,
00692     IsDynamicSize = PlainObjectType::SizeAtCompileTime==Dynamic,
00693     
00694     PacketAccessMask = bool(HasNoInnerStride) ? ~int(0) : ~int(PacketAccessBit),
00695     LinearAccessMask = bool(HasNoStride) || bool(PlainObjectType::IsVectorAtCompileTime) ? ~int(0) : ~int(LinearAccessBit),
00696     Flags = int( evaluator<PlainObjectType>::Flags) & (LinearAccessMask&PacketAccessMask),
00697     
00698     Alignment = int(MapOptions)&int(AlignedMask)
00699   };
00700 
00701   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& map)
00702     : mapbase_evaluator<XprType, PlainObjectType>(map) 
00703   { }
00704 };
00705 
00706 // -------------------- Ref --------------------
00707 
00708 template<typename PlainObjectType, int RefOptions, typename StrideType> 
00709 struct evaluator<Ref<PlainObjectType, RefOptions, StrideType> >
00710   : public mapbase_evaluator<Ref<PlainObjectType, RefOptions, StrideType>, PlainObjectType>
00711 {
00712   typedef Ref<PlainObjectType, RefOptions, StrideType> XprType;
00713   
00714   enum {
00715     Flags = evaluator<Map<PlainObjectType, RefOptions, StrideType> >::Flags,
00716     Alignment = evaluator<Map<PlainObjectType, RefOptions, StrideType> >::Alignment
00717   };
00718 
00719   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& ref)
00720     : mapbase_evaluator<XprType, PlainObjectType>(ref) 
00721   { }
00722 };
00723 
00724 // -------------------- Block --------------------
00725 
00726 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel,
00727          bool HasDirectAccess = internal::has_direct_access<ArgType>::ret> struct block_evaluator;
00728          
00729 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel> 
00730 struct evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
00731   : block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel>
00732 {
00733   typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
00734   typedef typename XprType::Scalar Scalar;
00735   // TODO: should check for smaller packet types once we can handle multi-sized packet types
00736   typedef typename packet_traits<Scalar>::type PacketScalar;
00737   
00738   enum {
00739     CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
00740     
00741     RowsAtCompileTime = traits<XprType>::RowsAtCompileTime,
00742     ColsAtCompileTime = traits<XprType>::ColsAtCompileTime,
00743     MaxRowsAtCompileTime = traits<XprType>::MaxRowsAtCompileTime,
00744     MaxColsAtCompileTime = traits<XprType>::MaxColsAtCompileTime,
00745     
00746     ArgTypeIsRowMajor = (int(evaluator<ArgType>::Flags)&RowMajorBit) != 0,
00747     IsRowMajor = (MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1) ? 1
00748                : (MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1) ? 0
00749                : ArgTypeIsRowMajor,
00750     HasSameStorageOrderAsArgType = (IsRowMajor == ArgTypeIsRowMajor),
00751     InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
00752     InnerStrideAtCompileTime = HasSameStorageOrderAsArgType
00753                              ? int(inner_stride_at_compile_time<ArgType>::ret)
00754                              : int(outer_stride_at_compile_time<ArgType>::ret),
00755     OuterStrideAtCompileTime = HasSameStorageOrderAsArgType
00756                              ? int(outer_stride_at_compile_time<ArgType>::ret)
00757                              : int(inner_stride_at_compile_time<ArgType>::ret),
00758     MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0)
00759                        && (InnerStrideAtCompileTime == 1)
00760                         ? PacketAccessBit : 0,
00761     
00762     FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (evaluator<ArgType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0,    
00763     FlagsRowMajorBit = XprType::Flags&RowMajorBit,
00764     Flags0 = evaluator<ArgType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
00765                                            DirectAccessBit |
00766                                            MaskPacketAccessBit),
00767     Flags = Flags0 | FlagsLinearAccessBit | FlagsRowMajorBit,
00768     
00769     PacketAlignment = unpacket_traits<PacketScalar>::alignment,
00770     Alignment0 = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % int(PacketAlignment)) == 0)) ? int(PacketAlignment) : 0,
00771     Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<ArgType>::Alignment, Alignment0)
00772   };
00773   typedef block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel> block_evaluator_type;
00774   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& block) : block_evaluator_type(block)
00775   {
00776     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00777   }
00778 };
00779 
00780 // no direct-access => dispatch to a unary evaluator
00781 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
00782 struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /*HasDirectAccess*/ false>
00783   : unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
00784 {
00785   typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
00786 
00787   EIGEN_DEVICE_FUNC explicit block_evaluator(const XprType& block)
00788     : unary_evaluator<XprType>(block) 
00789   {}
00790 };
00791 
00792 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel>
00793 struct unary_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>, IndexBased>
00794   : evaluator_base<Block<ArgType, BlockRows, BlockCols, InnerPanel> >
00795 {
00796   typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
00797 
00798   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& block)
00799     : m_argImpl(block.nestedExpression()), 
00800       m_startRow(block.startRow()), 
00801       m_startCol(block.startCol()) 
00802   { }
00803  
00804   typedef typename XprType::Scalar Scalar;
00805   typedef typename XprType::CoeffReturnType CoeffReturnType;
00806 
00807   enum {
00808     RowsAtCompileTime = XprType::RowsAtCompileTime
00809   };
00810  
00811   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00812   CoeffReturnType coeff(Index row, Index col) const
00813   { 
00814     return m_argImpl.coeff(m_startRow.value() + row, m_startCol.value() + col); 
00815   }
00816   
00817   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00818   CoeffReturnType coeff(Index index) const
00819   { 
00820     return coeff(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
00821   }
00822 
00823   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00824   Scalar& coeffRef(Index row, Index col)
00825   { 
00826     return m_argImpl.coeffRef(m_startRow.value() + row, m_startCol.value() + col); 
00827   }
00828   
00829   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00830   Scalar& coeffRef(Index index)
00831   { 
00832     return coeffRef(RowsAtCompileTime == 1 ? 0 : index, RowsAtCompileTime == 1 ? index : 0);
00833   }
00834  
00835   template<int LoadMode, typename PacketType>
00836   EIGEN_STRONG_INLINE
00837   PacketType packet(Index row, Index col) const 
00838   { 
00839     return m_argImpl.template packet<LoadMode,PacketType>(m_startRow.value() + row, m_startCol.value() + col); 
00840   }
00841 
00842   template<int LoadMode, typename PacketType>
00843   EIGEN_STRONG_INLINE
00844   PacketType packet(Index index) const 
00845   { 
00846     return packet<LoadMode,PacketType>(RowsAtCompileTime == 1 ? 0 : index,
00847                                        RowsAtCompileTime == 1 ? index : 0);
00848   }
00849   
00850   template<int StoreMode, typename PacketType>
00851   EIGEN_STRONG_INLINE
00852   void writePacket(Index row, Index col, const PacketType& x) 
00853   { 
00854     return m_argImpl.template writePacket<StoreMode,PacketType>(m_startRow.value() + row, m_startCol.value() + col, x); 
00855   }
00856   
00857   template<int StoreMode, typename PacketType>
00858   EIGEN_STRONG_INLINE
00859   void writePacket(Index index, const PacketType& x) 
00860   { 
00861     return writePacket<StoreMode,PacketType>(RowsAtCompileTime == 1 ? 0 : index,
00862                                              RowsAtCompileTime == 1 ? index : 0,
00863                                              x);
00864   }
00865  
00866 protected:
00867   evaluator<ArgType> m_argImpl;
00868   const variable_if_dynamic<Index, (ArgType::RowsAtCompileTime == 1 && BlockRows==1) ? 0 : Dynamic> m_startRow;
00869   const variable_if_dynamic<Index, (ArgType::ColsAtCompileTime == 1 && BlockCols==1) ? 0 : Dynamic> m_startCol;
00870 };
00871 
00872 // TODO: This evaluator does not actually use the child evaluator; 
00873 // all action is via the data() as returned by the Block expression.
00874 
00875 template<typename ArgType, int BlockRows, int BlockCols, bool InnerPanel> 
00876 struct block_evaluator<ArgType, BlockRows, BlockCols, InnerPanel, /* HasDirectAccess */ true>
00877   : mapbase_evaluator<Block<ArgType, BlockRows, BlockCols, InnerPanel>,
00878                       typename Block<ArgType, BlockRows, BlockCols, InnerPanel>::PlainObject>
00879 {
00880   typedef Block<ArgType, BlockRows, BlockCols, InnerPanel> XprType;
00881   typedef typename XprType::Scalar Scalar;
00882 
00883   EIGEN_DEVICE_FUNC explicit block_evaluator(const XprType& block)
00884     : mapbase_evaluator<XprType, typename XprType::PlainObject>(block) 
00885   {
00886     // 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
00887     eigen_assert(((size_t(block.data()) % EIGEN_PLAIN_ENUM_MAX(1,evaluator<XprType>::Alignment)) == 0) && "data is not aligned");
00888   }
00889 };
00890 
00891 
00892 // -------------------- Select --------------------
00893 // NOTE shall we introduce a ternary_evaluator?
00894 
00895 // TODO enable vectorization for Select
00896 template<typename ConditionMatrixType, typename ThenMatrixType, typename ElseMatrixType>
00897 struct evaluator<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
00898   : evaluator_base<Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> >
00899 {
00900   typedef Select<ConditionMatrixType, ThenMatrixType, ElseMatrixType> XprType;
00901   enum {
00902     CoeffReadCost = evaluator<ConditionMatrixType>::CoeffReadCost
00903                   + EIGEN_PLAIN_ENUM_MAX(evaluator<ThenMatrixType>::CoeffReadCost,
00904                                          evaluator<ElseMatrixType>::CoeffReadCost),
00905 
00906     Flags = (unsigned int)evaluator<ThenMatrixType>::Flags & evaluator<ElseMatrixType>::Flags & HereditaryBits,
00907     
00908     Alignment = EIGEN_PLAIN_ENUM_MIN(evaluator<ThenMatrixType>::Alignment, evaluator<ElseMatrixType>::Alignment)
00909   };
00910 
00911   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& select)
00912     : m_conditionImpl(select.conditionMatrix()),
00913       m_thenImpl(select.thenMatrix()),
00914       m_elseImpl(select.elseMatrix())
00915   {
00916     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
00917   }
00918  
00919   typedef typename XprType::CoeffReturnType CoeffReturnType;
00920 
00921   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00922   CoeffReturnType coeff(Index row, Index col) const
00923   {
00924     if (m_conditionImpl.coeff(row, col))
00925       return m_thenImpl.coeff(row, col);
00926     else
00927       return m_elseImpl.coeff(row, col);
00928   }
00929 
00930   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00931   CoeffReturnType coeff(Index index) const
00932   {
00933     if (m_conditionImpl.coeff(index))
00934       return m_thenImpl.coeff(index);
00935     else
00936       return m_elseImpl.coeff(index);
00937   }
00938  
00939 protected:
00940   evaluator<ConditionMatrixType> m_conditionImpl;
00941   evaluator<ThenMatrixType> m_thenImpl;
00942   evaluator<ElseMatrixType> m_elseImpl;
00943 };
00944 
00945 
00946 // -------------------- Replicate --------------------
00947 
00948 template<typename ArgType, int RowFactor, int ColFactor> 
00949 struct unary_evaluator<Replicate<ArgType, RowFactor, ColFactor> >
00950   : evaluator_base<Replicate<ArgType, RowFactor, ColFactor> >
00951 {
00952   typedef Replicate<ArgType, RowFactor, ColFactor> XprType;
00953   typedef typename XprType::CoeffReturnType CoeffReturnType;
00954   enum {
00955     Factor = (RowFactor==Dynamic || ColFactor==Dynamic) ? Dynamic : RowFactor*ColFactor
00956   };
00957   typedef typename internal::nested_eval<ArgType,Factor>::type ArgTypeNested;
00958   typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
00959   
00960   enum {
00961     CoeffReadCost = evaluator<ArgTypeNestedCleaned>::CoeffReadCost,
00962     LinearAccessMask = XprType::IsVectorAtCompileTime ? LinearAccessBit : 0,
00963     Flags = (evaluator<ArgTypeNestedCleaned>::Flags & (HereditaryBits|LinearAccessMask) & ~RowMajorBit) | (traits<XprType>::Flags & RowMajorBit),
00964     
00965     Alignment = evaluator<ArgTypeNestedCleaned>::Alignment
00966   };
00967 
00968   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& replicate)
00969     : m_arg(replicate.nestedExpression()),
00970       m_argImpl(m_arg),
00971       m_rows(replicate.nestedExpression().rows()),
00972       m_cols(replicate.nestedExpression().cols())
00973   {}
00974  
00975   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00976   CoeffReturnType coeff(Index row, Index col) const
00977   {
00978     // try to avoid using modulo; this is a pure optimization strategy
00979     const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0
00980                            : RowFactor==1 ? row
00981                            : row % m_rows.value();
00982     const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0
00983                            : ColFactor==1 ? col
00984                            : col % m_cols.value();
00985     
00986     return m_argImpl.coeff(actual_row, actual_col);
00987   }
00988   
00989   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00990   CoeffReturnType coeff(Index index) const
00991   {
00992     // try to avoid using modulo; this is a pure optimization strategy
00993     const Index actual_index = internal::traits<XprType>::RowsAtCompileTime==1
00994                                   ? (ColFactor==1 ?  index : index%m_cols.value())
00995                                   : (RowFactor==1 ?  index : index%m_rows.value());
00996     
00997     return m_argImpl.coeff(actual_index);
00998   }
00999 
01000   template<int LoadMode, typename PacketType>
01001   EIGEN_STRONG_INLINE
01002   PacketType packet(Index row, Index col) const
01003   {
01004     const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0
01005                            : RowFactor==1 ? row
01006                            : row % m_rows.value();
01007     const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0
01008                            : ColFactor==1 ? col
01009                            : col % m_cols.value();
01010 
01011     return m_argImpl.template packet<LoadMode,PacketType>(actual_row, actual_col);
01012   }
01013   
01014   template<int LoadMode, typename PacketType>
01015   EIGEN_STRONG_INLINE
01016   PacketType packet(Index index) const
01017   {
01018     const Index actual_index = internal::traits<XprType>::RowsAtCompileTime==1
01019                                   ? (ColFactor==1 ?  index : index%m_cols.value())
01020                                   : (RowFactor==1 ?  index : index%m_rows.value());
01021 
01022     return m_argImpl.template packet<LoadMode,PacketType>(actual_index);
01023   }
01024  
01025 protected:
01026   const ArgTypeNested m_arg;
01027   evaluator<ArgTypeNestedCleaned> m_argImpl;
01028   const variable_if_dynamic<Index, ArgType::RowsAtCompileTime> m_rows;
01029   const variable_if_dynamic<Index, ArgType::ColsAtCompileTime> m_cols;
01030 };
01031 
01032 
01033 // -------------------- PartialReduxExpr --------------------
01034 
01035 template< typename ArgType, typename MemberOp, int Direction>
01036 struct evaluator<PartialReduxExpr<ArgType, MemberOp, Direction> >
01037   : evaluator_base<PartialReduxExpr<ArgType, MemberOp, Direction> >
01038 {
01039   typedef PartialReduxExpr<ArgType, MemberOp, Direction> XprType;
01040   typedef typename internal::nested_eval<ArgType,1>::type ArgTypeNested;
01041   typedef typename internal::remove_all<ArgTypeNested>::type ArgTypeNestedCleaned;
01042   typedef typename ArgType::Scalar InputScalar;
01043   typedef typename XprType::Scalar Scalar;
01044   enum {
01045     TraversalSize = Direction==int(Vertical) ? int(ArgType::RowsAtCompileTime) :  int(ArgType::ColsAtCompileTime)
01046   };
01047   typedef typename MemberOp::template Cost<InputScalar,int(TraversalSize)> CostOpType;
01048   enum {
01049     CoeffReadCost = TraversalSize==Dynamic ? HugeCost
01050                   : TraversalSize * evaluator<ArgType>::CoeffReadCost + int(CostOpType::value),
01051     
01052     Flags = (traits<XprType>::Flags&RowMajorBit) | (evaluator<ArgType>::Flags&(HereditaryBits&(~RowMajorBit))) | LinearAccessBit,
01053     
01054     Alignment = 0 // FIXME this will need to be improved once PartialReduxExpr is vectorized
01055   };
01056 
01057   EIGEN_DEVICE_FUNC explicit evaluator(const XprType xpr)
01058     : m_arg(xpr.nestedExpression()), m_functor(xpr.functor())
01059   {
01060     EIGEN_INTERNAL_CHECK_COST_VALUE(TraversalSize==Dynamic ? HugeCost : int(CostOpType::value));
01061     EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
01062   }
01063 
01064   typedef typename XprType::CoeffReturnType CoeffReturnType;
01065 
01066   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01067   const Scalar coeff(Index i, Index j) const
01068   {
01069     if (Direction==Vertical)
01070       return m_functor(m_arg.col(j));
01071     else
01072       return m_functor(m_arg.row(i));
01073   }
01074 
01075   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01076   const Scalar coeff(Index index) const
01077   {
01078     if (Direction==Vertical)
01079       return m_functor(m_arg.col(index));
01080     else
01081       return m_functor(m_arg.row(index));
01082   }
01083 
01084 protected:
01085   const ArgTypeNested m_arg;
01086   const MemberOp m_functor;
01087 };
01088 
01089 
01090 // -------------------- MatrixWrapper and ArrayWrapper --------------------
01091 //
01092 // evaluator_wrapper_base<T> is a common base class for the
01093 // MatrixWrapper and ArrayWrapper evaluators.
01094 
01095 template<typename XprType>
01096 struct evaluator_wrapper_base
01097   : evaluator_base<XprType>
01098 {
01099   typedef typename remove_all<typename XprType::NestedExpressionType>::type ArgType;
01100   enum {
01101     CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
01102     Flags = evaluator<ArgType>::Flags,
01103     Alignment = evaluator<ArgType>::Alignment
01104   };
01105 
01106   EIGEN_DEVICE_FUNC explicit evaluator_wrapper_base(const ArgType& arg) : m_argImpl(arg) {}
01107 
01108   typedef typename ArgType::Scalar Scalar;
01109   typedef typename ArgType::CoeffReturnType CoeffReturnType;
01110 
01111   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01112   CoeffReturnType coeff(Index row, Index col) const
01113   {
01114     return m_argImpl.coeff(row, col);
01115   }
01116 
01117   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01118   CoeffReturnType coeff(Index index) const
01119   {
01120     return m_argImpl.coeff(index);
01121   }
01122 
01123   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01124   Scalar& coeffRef(Index row, Index col)
01125   {
01126     return m_argImpl.coeffRef(row, col);
01127   }
01128 
01129   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01130   Scalar& coeffRef(Index index)
01131   {
01132     return m_argImpl.coeffRef(index);
01133   }
01134 
01135   template<int LoadMode, typename PacketType>
01136   EIGEN_STRONG_INLINE
01137   PacketType packet(Index row, Index col) const
01138   {
01139     return m_argImpl.template packet<LoadMode,PacketType>(row, col);
01140   }
01141 
01142   template<int LoadMode, typename PacketType>
01143   EIGEN_STRONG_INLINE
01144   PacketType packet(Index index) const
01145   {
01146     return m_argImpl.template packet<LoadMode,PacketType>(index);
01147   }
01148 
01149   template<int StoreMode, typename PacketType>
01150   EIGEN_STRONG_INLINE
01151   void writePacket(Index row, Index col, const PacketType& x)
01152   {
01153     m_argImpl.template writePacket<StoreMode>(row, col, x);
01154   }
01155 
01156   template<int StoreMode, typename PacketType>
01157   EIGEN_STRONG_INLINE
01158   void writePacket(Index index, const PacketType& x)
01159   {
01160     m_argImpl.template writePacket<StoreMode>(index, x);
01161   }
01162 
01163 protected:
01164   evaluator<ArgType> m_argImpl;
01165 };
01166 
01167 template<typename TArgType>
01168 struct unary_evaluator<MatrixWrapper<TArgType> >
01169   : evaluator_wrapper_base<MatrixWrapper<TArgType> >
01170 {
01171   typedef MatrixWrapper<TArgType> XprType;
01172 
01173   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& wrapper)
01174     : evaluator_wrapper_base<MatrixWrapper<TArgType> >(wrapper.nestedExpression())
01175   { }
01176 };
01177 
01178 template<typename TArgType>
01179 struct unary_evaluator<ArrayWrapper<TArgType> >
01180   : evaluator_wrapper_base<ArrayWrapper<TArgType> >
01181 {
01182   typedef ArrayWrapper<TArgType> XprType;
01183 
01184   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& wrapper)
01185     : evaluator_wrapper_base<ArrayWrapper<TArgType> >(wrapper.nestedExpression())
01186   { }
01187 };
01188 
01189 
01190 // -------------------- Reverse --------------------
01191 
01192 // defined in Reverse.h:
01193 template<typename PacketType, bool ReversePacket> struct reverse_packet_cond;
01194 
01195 template<typename ArgType, int Direction>
01196 struct unary_evaluator<Reverse<ArgType, Direction> >
01197   : evaluator_base<Reverse<ArgType, Direction> >
01198 {
01199   typedef Reverse<ArgType, Direction> XprType;
01200   typedef typename XprType::Scalar Scalar;
01201   typedef typename XprType::CoeffReturnType CoeffReturnType;
01202 
01203   enum {
01204     IsRowMajor = XprType::IsRowMajor,
01205     IsColMajor = !IsRowMajor,
01206     ReverseRow = (Direction == Vertical)   || (Direction == BothDirections),
01207     ReverseCol = (Direction == Horizontal) || (Direction == BothDirections),
01208     ReversePacket = (Direction == BothDirections)
01209                     || ((Direction == Vertical)   && IsColMajor)
01210                     || ((Direction == Horizontal) && IsRowMajor),
01211                     
01212     CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
01213     
01214     // let's enable LinearAccess only with vectorization because of the product overhead
01215     // FIXME enable DirectAccess with negative strides?
01216     Flags0 = evaluator<ArgType>::Flags,
01217     LinearAccess = ( (Direction==BothDirections) && (int(Flags0)&PacketAccessBit) )
01218                   || ((ReverseRow && XprType::ColsAtCompileTime==1) || (ReverseCol && XprType::RowsAtCompileTime==1))
01219                  ? LinearAccessBit : 0,
01220 
01221     Flags = int(Flags0) & (HereditaryBits | PacketAccessBit | LinearAccess),
01222     
01223     Alignment = 0 // FIXME in some rare cases, Alignment could be preserved, like a Vector4f.
01224   };
01225 
01226   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& reverse)
01227     : m_argImpl(reverse.nestedExpression()),
01228       m_rows(ReverseRow ? reverse.nestedExpression().rows() : 1),
01229       m_cols(ReverseCol ? reverse.nestedExpression().cols() : 1)
01230   { }
01231  
01232   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01233   CoeffReturnType coeff(Index row, Index col) const
01234   {
01235     return m_argImpl.coeff(ReverseRow ? m_rows.value() - row - 1 : row,
01236                            ReverseCol ? m_cols.value() - col - 1 : col);
01237   }
01238 
01239   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01240   CoeffReturnType coeff(Index index) const
01241   {
01242     return m_argImpl.coeff(m_rows.value() * m_cols.value() - index - 1);
01243   }
01244 
01245   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01246   Scalar& coeffRef(Index row, Index col)
01247   {
01248     return m_argImpl.coeffRef(ReverseRow ? m_rows.value() - row - 1 : row,
01249                               ReverseCol ? m_cols.value() - col - 1 : col);
01250   }
01251 
01252   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01253   Scalar& coeffRef(Index index)
01254   {
01255     return m_argImpl.coeffRef(m_rows.value() * m_cols.value() - index - 1);
01256   }
01257 
01258   template<int LoadMode, typename PacketType>
01259   EIGEN_STRONG_INLINE
01260   PacketType packet(Index row, Index col) const
01261   {
01262     enum {
01263       PacketSize = unpacket_traits<PacketType>::size,
01264       OffsetRow  = ReverseRow && IsColMajor ? PacketSize : 1,
01265       OffsetCol  = ReverseCol && IsRowMajor ? PacketSize : 1
01266     };
01267     typedef internal::reverse_packet_cond<PacketType,ReversePacket> reverse_packet;
01268     return reverse_packet::run(m_argImpl.template packet<LoadMode,PacketType>(
01269                                   ReverseRow ? m_rows.value() - row - OffsetRow : row,
01270                                   ReverseCol ? m_cols.value() - col - OffsetCol : col));
01271   }
01272 
01273   template<int LoadMode, typename PacketType>
01274   EIGEN_STRONG_INLINE
01275   PacketType packet(Index index) const
01276   {
01277     enum { PacketSize = unpacket_traits<PacketType>::size };
01278     return preverse(m_argImpl.template packet<LoadMode,PacketType>(m_rows.value() * m_cols.value() - index - PacketSize));
01279   }
01280 
01281   template<int LoadMode, typename PacketType>
01282   EIGEN_STRONG_INLINE
01283   void writePacket(Index row, Index col, const PacketType& x)
01284   {
01285     // FIXME we could factorize some code with packet(i,j)
01286     enum {
01287       PacketSize = unpacket_traits<PacketType>::size,
01288       OffsetRow  = ReverseRow && IsColMajor ? PacketSize : 1,
01289       OffsetCol  = ReverseCol && IsRowMajor ? PacketSize : 1
01290     };
01291     typedef internal::reverse_packet_cond<PacketType,ReversePacket> reverse_packet;
01292     m_argImpl.template writePacket<LoadMode>(
01293                                   ReverseRow ? m_rows.value() - row - OffsetRow : row,
01294                                   ReverseCol ? m_cols.value() - col - OffsetCol : col,
01295                                   reverse_packet::run(x));
01296   }
01297 
01298   template<int LoadMode, typename PacketType>
01299   EIGEN_STRONG_INLINE
01300   void writePacket(Index index, const PacketType& x)
01301   {
01302     enum { PacketSize = unpacket_traits<PacketType>::size };
01303     m_argImpl.template writePacket<LoadMode>
01304       (m_rows.value() * m_cols.value() - index - PacketSize, preverse(x));
01305   }
01306  
01307 protected:
01308   evaluator<ArgType> m_argImpl;
01309 
01310   // If we do not reverse rows, then we do not need to know the number of rows; same for columns
01311   // Nonetheless, in this case it is important to set to 1 such that the coeff(index) method works fine for vectors.
01312   const variable_if_dynamic<Index, ReverseRow ? ArgType::RowsAtCompileTime : 1> m_rows;
01313   const variable_if_dynamic<Index, ReverseCol ? ArgType::ColsAtCompileTime : 1> m_cols;
01314 };
01315 
01316 
01317 // -------------------- Diagonal --------------------
01318 
01319 template<typename ArgType, int DiagIndex>
01320 struct evaluator<Diagonal<ArgType, DiagIndex> >
01321   : evaluator_base<Diagonal<ArgType, DiagIndex> >
01322 {
01323   typedef Diagonal<ArgType, DiagIndex> XprType;
01324   
01325   enum {
01326     CoeffReadCost = evaluator<ArgType>::CoeffReadCost,
01327     
01328     Flags = (unsigned int)evaluator<ArgType>::Flags & (HereditaryBits | LinearAccessBit | DirectAccessBit) & ~RowMajorBit,
01329     
01330     Alignment = 0
01331   };
01332 
01333   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& diagonal)
01334     : m_argImpl(diagonal.nestedExpression()),
01335       m_index(diagonal.index())
01336   { }
01337  
01338   typedef typename XprType::Scalar Scalar;
01339   // FIXME having to check whether ArgType is sparse here i not very nice.
01340   typedef typename internal::conditional<!internal::is_same<typename ArgType::StorageKind,Sparse>::value,
01341                                          typename XprType::CoeffReturnType,Scalar>::type CoeffReturnType;
01342 
01343   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01344   CoeffReturnType coeff(Index row, Index) const
01345   {
01346     return m_argImpl.coeff(row + rowOffset(), row + colOffset());
01347   }
01348 
01349   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01350   CoeffReturnType coeff(Index index) const
01351   {
01352     return m_argImpl.coeff(index + rowOffset(), index + colOffset());
01353   }
01354 
01355   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01356   Scalar& coeffRef(Index row, Index)
01357   {
01358     return m_argImpl.coeffRef(row + rowOffset(), row + colOffset());
01359   }
01360 
01361   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
01362   Scalar& coeffRef(Index index)
01363   {
01364     return m_argImpl.coeffRef(index + rowOffset(), index + colOffset());
01365   }
01366 
01367 protected:
01368   evaluator<ArgType> m_argImpl;
01369   const internal::variable_if_dynamicindex<Index, XprType::DiagIndex> m_index;
01370 
01371 private:
01372   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index rowOffset() const { return m_index.value() > 0 ? 0 : -m_index.value(); }
01373   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index colOffset() const { return m_index.value() > 0 ? m_index.value() : 0; }
01374 };
01375 
01376 
01377 //----------------------------------------------------------------------
01378 // deprecated code
01379 //----------------------------------------------------------------------
01380 
01381 // -------------------- EvalToTemp --------------------
01382 
01383 // expression class for evaluating nested expression to a temporary
01384 
01385 template<typename ArgType> class EvalToTemp;
01386 
01387 template<typename ArgType>
01388 struct traits<EvalToTemp<ArgType> >
01389   : public traits<ArgType>
01390 { };
01391 
01392 template<typename ArgType>
01393 class EvalToTemp
01394   : public dense_xpr_base<EvalToTemp<ArgType> >::type
01395 {
01396  public:
01397  
01398   typedef typename dense_xpr_base<EvalToTemp>::type Base;
01399   EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp)
01400  
01401   explicit EvalToTemp(const ArgType& arg)
01402     : m_arg(arg)
01403   { }
01404  
01405   const ArgType& arg() const
01406   {
01407     return m_arg;
01408   }
01409 
01410   Index rows() const 
01411   {
01412     return m_arg.rows();
01413   }
01414 
01415   Index cols() const 
01416   {
01417     return m_arg.cols();
01418   }
01419 
01420  private:
01421   const ArgType& m_arg;
01422 };
01423  
01424 template<typename ArgType>
01425 struct evaluator<EvalToTemp<ArgType> >
01426   : public evaluator<typename ArgType::PlainObject>
01427 {
01428   typedef EvalToTemp<ArgType>                   XprType;
01429   typedef typename ArgType::PlainObject         PlainObject;
01430   typedef evaluator<PlainObject> Base;
01431   
01432   EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
01433     : m_result(xpr.arg())
01434   {
01435     ::new (static_cast<Base*>(this)) Base(m_result);
01436   }
01437 
01438   // This constructor is used when nesting an EvalTo evaluator in another evaluator
01439   EIGEN_DEVICE_FUNC evaluator(const ArgType& arg)
01440     : m_result(arg)
01441   {
01442     ::new (static_cast<Base*>(this)) Base(m_result);
01443   }
01444 
01445 protected:
01446   PlainObject m_result;
01447 };
01448 
01449 } // namespace internal
01450 
01451 } // end namespace Eigen
01452 
01453 #endif // EIGEN_COREEVALUATORS_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines