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