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@gmx.net> 5// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> 6// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@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 15namespace Eigen { 16 17namespace internal { 18 19/*************************************************************************** 20* Part 1 : the logic deciding a strategy for traversal and unrolling * 21***************************************************************************/ 22 23template <typename Derived, typename OtherDerived> 24struct assign_traits 25{ 26public: 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 34private: 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 64public: 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 76private: 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 87public: 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 134template<typename Derived1, typename Derived2, int Index, int Stop> 135struct 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 149template<typename Derived1, typename Derived2, int Stop> 150struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop> 151{ 152 static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} 153}; 154 155template<typename Derived1, typename Derived2, int Index, int Stop> 156struct 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 165template<typename Derived1, typename Derived2, int Stop> 166struct 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 175template<typename Derived1, typename Derived2, int Index, int Stop> 176struct 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 185template<typename Derived1, typename Derived2, int Stop> 186struct 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 195template<typename Derived1, typename Derived2, int Index, int Stop> 196struct 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 212template<typename Derived1, typename Derived2, int Stop> 213struct assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop> 214{ 215 static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} 216}; 217 218template<typename Derived1, typename Derived2, int Index, int Stop> 219struct 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 229template<typename Derived1, typename Derived2, int Stop> 230struct 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 239template<typename Derived1, typename Derived2, 240 int Traversal = assign_traits<Derived1, Derived2>::Traversal, 241 int Unrolling = assign_traits<Derived1, Derived2>::Unrolling, 242 int Version = Specialized> 243struct assign_impl; 244 245/************************ 246*** Default traversal *** 247************************/ 248 249template<typename Derived1, typename Derived2, int Unrolling, int Version> 250struct assign_impl<Derived1, Derived2, InvalidTraversal, Unrolling, Version> 251{ 252 static inline void run(Derived1 &, const Derived2 &) { } 253}; 254 255template<typename Derived1, typename Derived2, int Version> 256struct 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 269template<typename Derived1, typename Derived2, int Version> 270struct 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 279template<typename Derived1, typename Derived2, int Version> 280struct 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 296template<typename Derived1, typename Derived2, int Version> 297struct 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 308template<typename Derived1, typename Derived2, int Version> 309struct 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 322template<typename Derived1, typename Derived2, int Version> 323struct 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 337template<typename Derived1, typename Derived2, int Version> 338struct 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 347template<typename Derived1, typename Derived2, int Version> 348struct 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 364template <bool IsAligned = false> 365struct 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 371template <> 372struct 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 389template<typename Derived1, typename Derived2, int Version> 390struct 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 417template<typename Derived1, typename Derived2, int Version> 418struct 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 436template<typename Derived1, typename Derived2, int Version> 437struct 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 482template<typename Derived> 483template<typename OtherDerived> 484EIGEN_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 507namespace internal { 508 509template<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> 518struct assign_selector; 519 520template<typename Derived, typename OtherDerived> 521struct assign_selector<Derived,OtherDerived,false,false> { 522 static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); } 523}; 524template<typename Derived, typename OtherDerived> 525struct assign_selector<Derived,OtherDerived,true,false> { 526 static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); } 527}; 528template<typename Derived, typename OtherDerived> 529struct assign_selector<Derived,OtherDerived,false,true> { 530 static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); } 531}; 532template<typename Derived, typename OtherDerived> 533struct 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 539template<typename Derived> 540template<typename OtherDerived> 541EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase<OtherDerived>& other) 542{ 543 return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived()); 544} 545 546template<typename Derived> 547EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase& other) 548{ 549 return internal::assign_selector<Derived,Derived>::run(derived(), other.derived()); 550} 551 552template<typename Derived> 553EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& other) 554{ 555 return internal::assign_selector<Derived,Derived>::run(derived(), other.derived()); 556} 557 558template<typename Derived> 559template <typename OtherDerived> 560EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<OtherDerived>& other) 561{ 562 return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived()); 563} 564 565template<typename Derived> 566template <typename OtherDerived> 567EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other) 568{ 569 other.derived().evalTo(derived()); 570 return derived(); 571} 572 573template<typename Derived> 574template<typename OtherDerived> 575EIGEN_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