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