MOAB
4.9.3pre
|
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