1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2007 Michael Olbrich <michael.olbrich (at) gmx.net> 5 // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1 (at) gmail.com> 6 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud (at) inria.fr> 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 #ifndef EIGEN_ASSIGN_H 13 #define EIGEN_ASSIGN_H 14 15 namespace Eigen { 16 17 namespace internal { 18 19 /*************************************************************************** 20 * Part 1 : the logic deciding a strategy for traversal and unrolling * 21 ***************************************************************************/ 22 23 template <typename Derived, typename OtherDerived> 24 struct assign_traits 25 { 26 public: 27 enum { 28 DstIsAligned = Derived::Flags & AlignedBit, 29 DstHasDirectAccess = Derived::Flags & DirectAccessBit, 30 SrcIsAligned = OtherDerived::Flags & AlignedBit, 31 JointAlignment = bool(DstIsAligned) && bool(SrcIsAligned) ? Aligned : Unaligned 32 }; 33 34 private: 35 enum { 36 InnerSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::SizeAtCompileTime) 37 : int(Derived::Flags)&RowMajorBit ? int(Derived::ColsAtCompileTime) 38 : int(Derived::RowsAtCompileTime), 39 InnerMaxSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::MaxSizeAtCompileTime) 40 : int(Derived::Flags)&RowMajorBit ? int(Derived::MaxColsAtCompileTime) 41 : int(Derived::MaxRowsAtCompileTime), 42 MaxSizeAtCompileTime = Derived::SizeAtCompileTime, 43 PacketSize = packet_traits<typename Derived::Scalar>::size 44 }; 45 46 enum { 47 StorageOrdersAgree = (int(Derived::IsRowMajor) == int(OtherDerived::IsRowMajor)), 48 MightVectorize = StorageOrdersAgree 49 && (int(Derived::Flags) & int(OtherDerived::Flags) & ActualPacketAccessBit), 50 MayInnerVectorize = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0 51 && int(DstIsAligned) && int(SrcIsAligned), 52 MayLinearize = StorageOrdersAgree && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit), 53 MayLinearVectorize = MightVectorize && MayLinearize && DstHasDirectAccess 54 && (DstIsAligned || MaxSizeAtCompileTime == Dynamic), 55 /* If the destination isn't aligned, we have to do runtime checks and we don't unroll, 56 so it's only good for large enough sizes. */ 57 MaySliceVectorize = MightVectorize && DstHasDirectAccess 58 && (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=3*PacketSize) 59 /* slice vectorization can be slow, so we only want it if the slices are big, which is 60 indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block 61 in a fixed-size matrix */ 62 }; 63 64 public: 65 enum { 66 Traversal = int(MayInnerVectorize) ? int(InnerVectorizedTraversal) 67 : int(MayLinearVectorize) ? int(LinearVectorizedTraversal) 68 : int(MaySliceVectorize) ? int(SliceVectorizedTraversal) 69 : int(MayLinearize) ? int(LinearTraversal) 70 : int(DefaultTraversal), 71 Vectorized = int(Traversal) == InnerVectorizedTraversal 72 || int(Traversal) == LinearVectorizedTraversal 73 || int(Traversal) == SliceVectorizedTraversal 74 }; 75 76 private: 77 enum { 78 UnrollingLimit = EIGEN_UNROLLING_LIMIT * (Vectorized ? int(PacketSize) : 1), 79 MayUnrollCompletely = int(Derived::SizeAtCompileTime) != Dynamic 80 && int(OtherDerived::CoeffReadCost) != Dynamic 81 && int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit), 82 MayUnrollInner = int(InnerSize) != Dynamic 83 && int(OtherDerived::CoeffReadCost) != Dynamic 84 && int(InnerSize) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit) 85 }; 86 87 public: 88 enum { 89 Unrolling = (int(Traversal) == int(InnerVectorizedTraversal) || int(Traversal) == int(DefaultTraversal)) 90 ? ( 91 int(MayUnrollCompletely) ? int(CompleteUnrolling) 92 : int(MayUnrollInner) ? int(InnerUnrolling) 93 : int(NoUnrolling) 94 ) 95 : int(Traversal) == int(LinearVectorizedTraversal) 96 ? ( bool(MayUnrollCompletely) && bool(DstIsAligned) ? int(CompleteUnrolling) : int(NoUnrolling) ) 97 : int(Traversal) == int(LinearTraversal) 98 ? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling) : int(NoUnrolling) ) 99 : int(NoUnrolling) 100 }; 101 102 #ifdef EIGEN_DEBUG_ASSIGN 103 static void debug() 104 { 105 EIGEN_DEBUG_VAR(DstIsAligned) 106 EIGEN_DEBUG_VAR(SrcIsAligned) 107 EIGEN_DEBUG_VAR(JointAlignment) 108 EIGEN_DEBUG_VAR(InnerSize) 109 EIGEN_DEBUG_VAR(InnerMaxSize) 110 EIGEN_DEBUG_VAR(PacketSize) 111 EIGEN_DEBUG_VAR(StorageOrdersAgree) 112 EIGEN_DEBUG_VAR(MightVectorize) 113 EIGEN_DEBUG_VAR(MayLinearize) 114 EIGEN_DEBUG_VAR(MayInnerVectorize) 115 EIGEN_DEBUG_VAR(MayLinearVectorize) 116 EIGEN_DEBUG_VAR(MaySliceVectorize) 117 EIGEN_DEBUG_VAR(Traversal) 118 EIGEN_DEBUG_VAR(UnrollingLimit) 119 EIGEN_DEBUG_VAR(MayUnrollCompletely) 120 EIGEN_DEBUG_VAR(MayUnrollInner) 121 EIGEN_DEBUG_VAR(Unrolling) 122 } 123 #endif 124 }; 125 126 /*************************************************************************** 127 * Part 2 : meta-unrollers 128 ***************************************************************************/ 129 130 /************************ 131 *** Default traversal *** 132 ************************/ 133 134 template<typename Derived1, typename Derived2, int Index, int Stop> 135 struct assign_DefaultTraversal_CompleteUnrolling 136 { 137 enum { 138 outer = Index / Derived1::InnerSizeAtCompileTime, 139 inner = Index % Derived1::InnerSizeAtCompileTime 140 }; 141 142 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 143 { 144 dst.copyCoeffByOuterInner(outer, inner, src); 145 assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src); 146 } 147 }; 148 149 template<typename Derived1, typename Derived2, int Stop> 150 struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop> 151 { 152 static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} 153 }; 154 155 template<typename Derived1, typename Derived2, int Index, int Stop> 156 struct assign_DefaultTraversal_InnerUnrolling 157 { 158 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer) 159 { 160 dst.copyCoeffByOuterInner(outer, Index, src); 161 assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, outer); 162 } 163 }; 164 165 template<typename Derived1, typename Derived2, int Stop> 166 struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop> 167 { 168 static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {} 169 }; 170 171 /*********************** 172 *** Linear traversal *** 173 ***********************/ 174 175 template<typename Derived1, typename Derived2, int Index, int Stop> 176 struct assign_LinearTraversal_CompleteUnrolling 177 { 178 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 179 { 180 dst.copyCoeff(Index, src); 181 assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src); 182 } 183 }; 184 185 template<typename Derived1, typename Derived2, int Stop> 186 struct assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop> 187 { 188 static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} 189 }; 190 191 /************************** 192 *** Inner vectorization *** 193 **************************/ 194 195 template<typename Derived1, typename Derived2, int Index, int Stop> 196 struct assign_innervec_CompleteUnrolling 197 { 198 enum { 199 outer = Index / Derived1::InnerSizeAtCompileTime, 200 inner = Index % Derived1::InnerSizeAtCompileTime, 201 JointAlignment = assign_traits<Derived1,Derived2>::JointAlignment 202 }; 203 204 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 205 { 206 dst.template copyPacketByOuterInner<Derived2, Aligned, JointAlignment>(outer, inner, src); 207 assign_innervec_CompleteUnrolling<Derived1, Derived2, 208 Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src); 209 } 210 }; 211 212 template<typename Derived1, typename Derived2, int Stop> 213 struct assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop> 214 { 215 static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} 216 }; 217 218 template<typename Derived1, typename Derived2, int Index, int Stop> 219 struct assign_innervec_InnerUnrolling 220 { 221 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer) 222 { 223 dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, Index, src); 224 assign_innervec_InnerUnrolling<Derived1, Derived2, 225 Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src, outer); 226 } 227 }; 228 229 template<typename Derived1, typename Derived2, int Stop> 230 struct assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop> 231 { 232 static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {} 233 }; 234 235 /*************************************************************************** 236 * Part 3 : implementation of all cases 237 ***************************************************************************/ 238 239 template<typename Derived1, typename Derived2, 240 int Traversal = assign_traits<Derived1, Derived2>::Traversal, 241 int Unrolling = assign_traits<Derived1, Derived2>::Unrolling, 242 int Version = Specialized> 243 struct assign_impl; 244 245 /************************ 246 *** Default traversal *** 247 ************************/ 248 249 template<typename Derived1, typename Derived2, int Unrolling, int Version> 250 struct assign_impl<Derived1, Derived2, InvalidTraversal, Unrolling, Version> 251 { 252 static inline void run(Derived1 &, const Derived2 &) { } 253 }; 254 255 template<typename Derived1, typename Derived2, int Version> 256 struct assign_impl<Derived1, Derived2, DefaultTraversal, NoUnrolling, Version> 257 { 258 typedef typename Derived1::Index Index; 259 static inline void run(Derived1 &dst, const Derived2 &src) 260 { 261 const Index innerSize = dst.innerSize(); 262 const Index outerSize = dst.outerSize(); 263 for(Index outer = 0; outer < outerSize; ++outer) 264 for(Index inner = 0; inner < innerSize; ++inner) 265 dst.copyCoeffByOuterInner(outer, inner, src); 266 } 267 }; 268 269 template<typename Derived1, typename Derived2, int Version> 270 struct assign_impl<Derived1, Derived2, DefaultTraversal, CompleteUnrolling, Version> 271 { 272 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 273 { 274 assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime> 275 ::run(dst, src); 276 } 277 }; 278 279 template<typename Derived1, typename Derived2, int Version> 280 struct assign_impl<Derived1, Derived2, DefaultTraversal, InnerUnrolling, Version> 281 { 282 typedef typename Derived1::Index Index; 283 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 284 { 285 const Index outerSize = dst.outerSize(); 286 for(Index outer = 0; outer < outerSize; ++outer) 287 assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime> 288 ::run(dst, src, outer); 289 } 290 }; 291 292 /*********************** 293 *** Linear traversal *** 294 ***********************/ 295 296 template<typename Derived1, typename Derived2, int Version> 297 struct assign_impl<Derived1, Derived2, LinearTraversal, NoUnrolling, Version> 298 { 299 typedef typename Derived1::Index Index; 300 static inline void run(Derived1 &dst, const Derived2 &src) 301 { 302 const Index size = dst.size(); 303 for(Index i = 0; i < size; ++i) 304 dst.copyCoeff(i, src); 305 } 306 }; 307 308 template<typename Derived1, typename Derived2, int Version> 309 struct assign_impl<Derived1, Derived2, LinearTraversal, CompleteUnrolling, Version> 310 { 311 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 312 { 313 assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime> 314 ::run(dst, src); 315 } 316 }; 317 318 /************************** 319 *** Inner vectorization *** 320 **************************/ 321 322 template<typename Derived1, typename Derived2, int Version> 323 struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, NoUnrolling, Version> 324 { 325 typedef typename Derived1::Index Index; 326 static inline void run(Derived1 &dst, const Derived2 &src) 327 { 328 const Index innerSize = dst.innerSize(); 329 const Index outerSize = dst.outerSize(); 330 const Index packetSize = packet_traits<typename Derived1::Scalar>::size; 331 for(Index outer = 0; outer < outerSize; ++outer) 332 for(Index inner = 0; inner < innerSize; inner+=packetSize) 333 dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, inner, src); 334 } 335 }; 336 337 template<typename Derived1, typename Derived2, int Version> 338 struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, CompleteUnrolling, Version> 339 { 340 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 341 { 342 assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime> 343 ::run(dst, src); 344 } 345 }; 346 347 template<typename Derived1, typename Derived2, int Version> 348 struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, InnerUnrolling, Version> 349 { 350 typedef typename Derived1::Index Index; 351 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 352 { 353 const Index outerSize = dst.outerSize(); 354 for(Index outer = 0; outer < outerSize; ++outer) 355 assign_innervec_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime> 356 ::run(dst, src, outer); 357 } 358 }; 359 360 /*************************** 361 *** Linear vectorization *** 362 ***************************/ 363 364 template <bool IsAligned = false> 365 struct unaligned_assign_impl 366 { 367 template <typename Derived, typename OtherDerived> 368 static EIGEN_STRONG_INLINE void run(const Derived&, OtherDerived&, typename Derived::Index, typename Derived::Index) {} 369 }; 370 371 template <> 372 struct unaligned_assign_impl<false> 373 { 374 // MSVC must not inline this functions. If it does, it fails to optimize the 375 // packet access path. 376 #ifdef _MSC_VER 377 template <typename Derived, typename OtherDerived> 378 static EIGEN_DONT_INLINE void run(const Derived& src, OtherDerived& dst, typename Derived::Index start, typename Derived::Index end) 379 #else 380 template <typename Derived, typename OtherDerived> 381 static EIGEN_STRONG_INLINE void run(const Derived& src, OtherDerived& dst, typename Derived::Index start, typename Derived::Index end) 382 #endif 383 { 384 for (typename Derived::Index index = start; index < end; ++index) 385 dst.copyCoeff(index, src); 386 } 387 }; 388 389 template<typename Derived1, typename Derived2, int Version> 390 struct assign_impl<Derived1, Derived2, LinearVectorizedTraversal, NoUnrolling, Version> 391 { 392 typedef typename Derived1::Index Index; 393 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 394 { 395 const Index size = dst.size(); 396 typedef packet_traits<typename Derived1::Scalar> PacketTraits; 397 enum { 398 packetSize = PacketTraits::size, 399 dstAlignment = PacketTraits::AlignedOnScalar ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) , 400 srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment 401 }; 402 const Index alignedStart = assign_traits<Derived1,Derived2>::DstIsAligned ? 0 403 : internal::first_aligned(&dst.coeffRef(0), size); 404 const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize; 405 406 unaligned_assign_impl<assign_traits<Derived1,Derived2>::DstIsAligned!=0>::run(src,dst,0,alignedStart); 407 408 for(Index index = alignedStart; index < alignedEnd; index += packetSize) 409 { 410 dst.template copyPacket<Derived2, dstAlignment, srcAlignment>(index, src); 411 } 412 413 unaligned_assign_impl<>::run(src,dst,alignedEnd,size); 414 } 415 }; 416 417 template<typename Derived1, typename Derived2, int Version> 418 struct assign_impl<Derived1, Derived2, LinearVectorizedTraversal, CompleteUnrolling, Version> 419 { 420 typedef typename Derived1::Index Index; 421 static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) 422 { 423 enum { size = Derived1::SizeAtCompileTime, 424 packetSize = packet_traits<typename Derived1::Scalar>::size, 425 alignedSize = (size/packetSize)*packetSize }; 426 427 assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, alignedSize>::run(dst, src); 428 assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, alignedSize, size>::run(dst, src); 429 } 430 }; 431 432 /************************** 433 *** Slice vectorization *** 434 ***************************/ 435 436 template<typename Derived1, typename Derived2, int Version> 437 struct assign_impl<Derived1, Derived2, SliceVectorizedTraversal, NoUnrolling, Version> 438 { 439 typedef typename Derived1::Index Index; 440 static inline void run(Derived1 &dst, const Derived2 &src) 441 { 442 typedef packet_traits<typename Derived1::Scalar> PacketTraits; 443 enum { 444 packetSize = PacketTraits::size, 445 alignable = PacketTraits::AlignedOnScalar, 446 dstAlignment = alignable ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) , 447 srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment 448 }; 449 const Index packetAlignedMask = packetSize - 1; 450 const Index innerSize = dst.innerSize(); 451 const Index outerSize = dst.outerSize(); 452 const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0; 453 Index alignedStart = ((!alignable) || assign_traits<Derived1,Derived2>::DstIsAligned) ? 0 454 : internal::first_aligned(&dst.coeffRef(0,0), innerSize); 455 456 for(Index outer = 0; outer < outerSize; ++outer) 457 { 458 const Index alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask); 459 // do the non-vectorizable part of the assignment 460 for(Index inner = 0; inner<alignedStart ; ++inner) 461 dst.copyCoeffByOuterInner(outer, inner, src); 462 463 // do the vectorizable part of the assignment 464 for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize) 465 dst.template copyPacketByOuterInner<Derived2, dstAlignment, Unaligned>(outer, inner, src); 466 467 // do the non-vectorizable part of the assignment 468 for(Index inner = alignedEnd; inner<innerSize ; ++inner) 469 dst.copyCoeffByOuterInner(outer, inner, src); 470 471 alignedStart = std::min<Index>((alignedStart+alignedStep)%packetSize, innerSize); 472 } 473 } 474 }; 475 476 } // end namespace internal 477 478 /*************************************************************************** 479 * Part 4 : implementation of DenseBase methods 480 ***************************************************************************/ 481 482 template<typename Derived> 483 template<typename OtherDerived> 484 EIGEN_STRONG_INLINE Derived& DenseBase<Derived> 485 ::lazyAssign(const DenseBase<OtherDerived>& other) 486 { 487 enum{ 488 SameType = internal::is_same<typename Derived::Scalar,typename OtherDerived::Scalar>::value 489 }; 490 491 EIGEN_STATIC_ASSERT_LVALUE(Derived) 492 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived) 493 EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) 494 495 #ifdef EIGEN_DEBUG_ASSIGN 496 internal::assign_traits<Derived, OtherDerived>::debug(); 497 #endif 498 eigen_assert(rows() == other.rows() && cols() == other.cols()); 499 internal::assign_impl<Derived, OtherDerived, int(SameType) ? int(internal::assign_traits<Derived, OtherDerived>::Traversal) 500 : int(InvalidTraversal)>::run(derived(),other.derived()); 501 #ifndef EIGEN_NO_DEBUG 502 checkTransposeAliasing(other.derived()); 503 #endif 504 return derived(); 505 } 506 507 namespace internal { 508 509 template<typename Derived, typename OtherDerived, 510 bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0, 511 bool NeedToTranspose = Derived::IsVectorAtCompileTime 512 && OtherDerived::IsVectorAtCompileTime 513 && ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1) 514 | // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&". 515 // revert to || as soon as not needed anymore. 516 (int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1)) 517 && int(Derived::SizeAtCompileTime) != 1> 518 struct assign_selector; 519 520 template<typename Derived, typename OtherDerived> 521 struct assign_selector<Derived,OtherDerived,false,false> { 522 static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); } 523 }; 524 template<typename Derived, typename OtherDerived> 525 struct assign_selector<Derived,OtherDerived,true,false> { 526 static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); } 527 }; 528 template<typename Derived, typename OtherDerived> 529 struct assign_selector<Derived,OtherDerived,false,true> { 530 static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); } 531 }; 532 template<typename Derived, typename OtherDerived> 533 struct assign_selector<Derived,OtherDerived,true,true> { 534 static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); } 535 }; 536 537 } // end namespace internal 538 539 template<typename Derived> 540 template<typename OtherDerived> 541 EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase<OtherDerived>& other) 542 { 543 return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived()); 544 } 545 546 template<typename Derived> 547 EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase& other) 548 { 549 return internal::assign_selector<Derived,Derived>::run(derived(), other.derived()); 550 } 551 552 template<typename Derived> 553 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& other) 554 { 555 return internal::assign_selector<Derived,Derived>::run(derived(), other.derived()); 556 } 557 558 template<typename Derived> 559 template <typename OtherDerived> 560 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<OtherDerived>& other) 561 { 562 return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived()); 563 } 564 565 template<typename Derived> 566 template <typename OtherDerived> 567 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other) 568 { 569 other.derived().evalTo(derived()); 570 return derived(); 571 } 572 573 template<typename Derived> 574 template<typename OtherDerived> 575 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other) 576 { 577 other.evalTo(derived()); 578 return derived(); 579 } 580 581 } // end namespace Eigen 582 583 #endif // EIGEN_ASSIGN_H 584