Assign.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2007 Michael Olbrich <michael.olbrich@gmx.net>
00005 // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
00006 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00007 //
00008 // Eigen is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Lesser General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 3 of the License, or (at your option) any later version.
00012 //
00013 // Alternatively, you can redistribute it and/or
00014 // modify it under the terms of the GNU General Public License as
00015 // published by the Free Software Foundation; either version 2 of
00016 // the License, or (at your option) any later version.
00017 //
00018 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00019 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00020 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00021 // GNU General Public License for more details.
00022 //
00023 // You should have received a copy of the GNU Lesser General Public
00024 // License and a copy of the GNU General Public License along with
00025 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 #ifndef EIGEN_ASSIGN_H
00028 #define EIGEN_ASSIGN_H
00029 
00030 namespace Eigen {
00031 
00032 namespace internal {
00033 
00034 /***************************************************************************
00035 * Part 1 : the logic deciding a strategy for traversal and unrolling       *
00036 ***************************************************************************/
00037 
00038 template <typename Derived, typename OtherDerived>
00039 struct assign_traits
00040 {
00041 public:
00042   enum {
00043     DstIsAligned = Derived::Flags & AlignedBit,
00044     DstHasDirectAccess = Derived::Flags & DirectAccessBit,
00045     SrcIsAligned = OtherDerived::Flags & AlignedBit,
00046     JointAlignment = bool(DstIsAligned) && bool(SrcIsAligned) ? Aligned : Unaligned
00047   };
00048 
00049 private:
00050   enum {
00051     InnerSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::SizeAtCompileTime)
00052               : int(Derived::Flags)&RowMajorBit ? int(Derived::ColsAtCompileTime)
00053               : int(Derived::RowsAtCompileTime),
00054     InnerMaxSize = int(Derived::IsVectorAtCompileTime) ? int(Derived::MaxSizeAtCompileTime)
00055               : int(Derived::Flags)&RowMajorBit ? int(Derived::MaxColsAtCompileTime)
00056               : int(Derived::MaxRowsAtCompileTime),
00057     MaxSizeAtCompileTime = Derived::SizeAtCompileTime,
00058     PacketSize = packet_traits<typename Derived::Scalar>::size
00059   };
00060 
00061   enum {
00062     StorageOrdersAgree = (int(Derived::IsRowMajor) == int(OtherDerived::IsRowMajor)),
00063     MightVectorize = StorageOrdersAgree
00064                   && (int(Derived::Flags) & int(OtherDerived::Flags) & ActualPacketAccessBit),
00065     MayInnerVectorize  = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0
00066                        && int(DstIsAligned) && int(SrcIsAligned),
00067     MayLinearize = StorageOrdersAgree && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit),
00068     MayLinearVectorize = MightVectorize && MayLinearize && DstHasDirectAccess
00069                        && (DstIsAligned || MaxSizeAtCompileTime == Dynamic),
00070       /* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
00071          so it's only good for large enough sizes. */
00072     MaySliceVectorize  = MightVectorize && DstHasDirectAccess
00073                        && (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=3*PacketSize)
00074       /* slice vectorization can be slow, so we only want it if the slices are big, which is
00075          indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block
00076          in a fixed-size matrix */
00077   };
00078 
00079 public:
00080   enum {
00081     Traversal = int(MayInnerVectorize)  ? int(InnerVectorizedTraversal)
00082               : int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
00083               : int(MaySliceVectorize)  ? int(SliceVectorizedTraversal)
00084               : int(MayLinearize)       ? int(LinearTraversal)
00085                                         : int(DefaultTraversal),
00086     Vectorized = int(Traversal) == InnerVectorizedTraversal
00087               || int(Traversal) == LinearVectorizedTraversal
00088               || int(Traversal) == SliceVectorizedTraversal
00089   };
00090 
00091 private:
00092   enum {
00093     UnrollingLimit      = EIGEN_UNROLLING_LIMIT * (Vectorized ? int(PacketSize) : 1),
00094     MayUnrollCompletely = int(Derived::SizeAtCompileTime) != Dynamic
00095                        && int(OtherDerived::CoeffReadCost) != Dynamic
00096                        && int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit),
00097     MayUnrollInner      = int(InnerSize) != Dynamic
00098                        && int(OtherDerived::CoeffReadCost) != Dynamic
00099                        && int(InnerSize) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit)
00100   };
00101 
00102 public:
00103   enum {
00104     Unrolling = (int(Traversal) == int(InnerVectorizedTraversal) || int(Traversal) == int(DefaultTraversal))
00105                 ? (
00106                     int(MayUnrollCompletely) ? int(CompleteUnrolling)
00107                   : int(MayUnrollInner)      ? int(InnerUnrolling)
00108                                              : int(NoUnrolling)
00109                   )
00110               : int(Traversal) == int(LinearVectorizedTraversal)
00111                 ? ( bool(MayUnrollCompletely) && bool(DstIsAligned) ? int(CompleteUnrolling) : int(NoUnrolling) )
00112               : int(Traversal) == int(LinearTraversal)
00113                 ? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling) : int(NoUnrolling) )
00114               : int(NoUnrolling)
00115   };
00116 
00117 #ifdef EIGEN_DEBUG_ASSIGN
00118   static void debug()
00119   {
00120     EIGEN_DEBUG_VAR(DstIsAligned)
00121     EIGEN_DEBUG_VAR(SrcIsAligned)
00122     EIGEN_DEBUG_VAR(JointAlignment)
00123     EIGEN_DEBUG_VAR(InnerSize)
00124     EIGEN_DEBUG_VAR(InnerMaxSize)
00125     EIGEN_DEBUG_VAR(PacketSize)
00126     EIGEN_DEBUG_VAR(StorageOrdersAgree)
00127     EIGEN_DEBUG_VAR(MightVectorize)
00128     EIGEN_DEBUG_VAR(MayLinearize)
00129     EIGEN_DEBUG_VAR(MayInnerVectorize)
00130     EIGEN_DEBUG_VAR(MayLinearVectorize)
00131     EIGEN_DEBUG_VAR(MaySliceVectorize)
00132     EIGEN_DEBUG_VAR(Traversal)
00133     EIGEN_DEBUG_VAR(UnrollingLimit)
00134     EIGEN_DEBUG_VAR(MayUnrollCompletely)
00135     EIGEN_DEBUG_VAR(MayUnrollInner)
00136     EIGEN_DEBUG_VAR(Unrolling)
00137   }
00138 #endif
00139 };
00140 
00141 /***************************************************************************
00142 * Part 2 : meta-unrollers
00143 ***************************************************************************/
00144 
00145 /************************
00146 *** Default traversal ***
00147 ************************/
00148 
00149 template<typename Derived1, typename Derived2, int Index, int Stop>
00150 struct assign_DefaultTraversal_CompleteUnrolling
00151 {
00152   enum {
00153     outer = Index / Derived1::InnerSizeAtCompileTime,
00154     inner = Index % Derived1::InnerSizeAtCompileTime
00155   };
00156 
00157   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00158   {
00159     dst.copyCoeffByOuterInner(outer, inner, src);
00160     assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
00161   }
00162 };
00163 
00164 template<typename Derived1, typename Derived2, int Stop>
00165 struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
00166 {
00167   static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {}
00168 };
00169 
00170 template<typename Derived1, typename Derived2, int Index, int Stop>
00171 struct assign_DefaultTraversal_InnerUnrolling
00172 {
00173   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer)
00174   {
00175     dst.copyCoeffByOuterInner(outer, Index, src);
00176     assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, outer);
00177   }
00178 };
00179 
00180 template<typename Derived1, typename Derived2, int Stop>
00181 struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop>
00182 {
00183   static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
00184 };
00185 
00186 /***********************
00187 *** Linear traversal ***
00188 ***********************/
00189 
00190 template<typename Derived1, typename Derived2, int Index, int Stop>
00191 struct assign_LinearTraversal_CompleteUnrolling
00192 {
00193   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00194   {
00195     dst.copyCoeff(Index, src);
00196     assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
00197   }
00198 };
00199 
00200 template<typename Derived1, typename Derived2, int Stop>
00201 struct assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
00202 {
00203   static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {}
00204 };
00205 
00206 /**************************
00207 *** Inner vectorization ***
00208 **************************/
00209 
00210 template<typename Derived1, typename Derived2, int Index, int Stop>
00211 struct assign_innervec_CompleteUnrolling
00212 {
00213   enum {
00214     outer = Index / Derived1::InnerSizeAtCompileTime,
00215     inner = Index % Derived1::InnerSizeAtCompileTime,
00216     JointAlignment = assign_traits<Derived1,Derived2>::JointAlignment
00217   };
00218 
00219   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00220   {
00221     dst.template copyPacketByOuterInner<Derived2, Aligned, JointAlignment>(outer, inner, src);
00222     assign_innervec_CompleteUnrolling<Derived1, Derived2,
00223       Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src);
00224   }
00225 };
00226 
00227 template<typename Derived1, typename Derived2, int Stop>
00228 struct assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
00229 {
00230   static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {}
00231 };
00232 
00233 template<typename Derived1, typename Derived2, int Index, int Stop>
00234 struct assign_innervec_InnerUnrolling
00235 {
00236   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer)
00237   {
00238     dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, Index, src);
00239     assign_innervec_InnerUnrolling<Derived1, Derived2,
00240       Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src, outer);
00241   }
00242 };
00243 
00244 template<typename Derived1, typename Derived2, int Stop>
00245 struct assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
00246 {
00247   static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {}
00248 };
00249 
00250 /***************************************************************************
00251 * Part 3 : implementation of all cases
00252 ***************************************************************************/
00253 
00254 template<typename Derived1, typename Derived2,
00255          int Traversal = assign_traits<Derived1, Derived2>::Traversal,
00256          int Unrolling = assign_traits<Derived1, Derived2>::Unrolling,
00257          int Version = Specialized>
00258 struct assign_impl;
00259 
00260 /************************
00261 *** Default traversal ***
00262 ************************/
00263 
00264 template<typename Derived1, typename Derived2, int Unrolling, int Version>
00265 struct assign_impl<Derived1, Derived2, InvalidTraversal, Unrolling, Version>
00266 {
00267   static inline void run(Derived1 &, const Derived2 &) { }
00268 };
00269 
00270 template<typename Derived1, typename Derived2, int Version>
00271 struct assign_impl<Derived1, Derived2, DefaultTraversal, NoUnrolling, Version>
00272 {
00273   typedef typename Derived1::Index Index;
00274   static inline void run(Derived1 &dst, const Derived2 &src)
00275   {
00276     const Index innerSize = dst.innerSize();
00277     const Index outerSize = dst.outerSize();
00278     for(Index outer = 0; outer < outerSize; ++outer)
00279       for(Index inner = 0; inner < innerSize; ++inner)
00280         dst.copyCoeffByOuterInner(outer, inner, src);
00281   }
00282 };
00283 
00284 template<typename Derived1, typename Derived2, int Version>
00285 struct assign_impl<Derived1, Derived2, DefaultTraversal, CompleteUnrolling, Version>
00286 {
00287   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00288   {
00289     assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
00290       ::run(dst, src);
00291   }
00292 };
00293 
00294 template<typename Derived1, typename Derived2, int Version>
00295 struct assign_impl<Derived1, Derived2, DefaultTraversal, InnerUnrolling, Version>
00296 {
00297   typedef typename Derived1::Index Index;
00298   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00299   {
00300     const Index outerSize = dst.outerSize();
00301     for(Index outer = 0; outer < outerSize; ++outer)
00302       assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime>
00303         ::run(dst, src, outer);
00304   }
00305 };
00306 
00307 /***********************
00308 *** Linear traversal ***
00309 ***********************/
00310 
00311 template<typename Derived1, typename Derived2, int Version>
00312 struct assign_impl<Derived1, Derived2, LinearTraversal, NoUnrolling, Version>
00313 {
00314   typedef typename Derived1::Index Index;
00315   static inline void run(Derived1 &dst, const Derived2 &src)
00316   {
00317     const Index size = dst.size();
00318     for(Index i = 0; i < size; ++i)
00319       dst.copyCoeff(i, src);
00320   }
00321 };
00322 
00323 template<typename Derived1, typename Derived2, int Version>
00324 struct assign_impl<Derived1, Derived2, LinearTraversal, CompleteUnrolling, Version>
00325 {
00326   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00327   {
00328     assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
00329       ::run(dst, src);
00330   }
00331 };
00332 
00333 /**************************
00334 *** Inner vectorization ***
00335 **************************/
00336 
00337 template<typename Derived1, typename Derived2, int Version>
00338 struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, NoUnrolling, Version>
00339 {
00340   typedef typename Derived1::Index Index;
00341   static inline void run(Derived1 &dst, const Derived2 &src)
00342   {
00343     const Index innerSize = dst.innerSize();
00344     const Index outerSize = dst.outerSize();
00345     const Index packetSize = packet_traits<typename Derived1::Scalar>::size;
00346     for(Index outer = 0; outer < outerSize; ++outer)
00347       for(Index inner = 0; inner < innerSize; inner+=packetSize)
00348         dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, inner, src);
00349   }
00350 };
00351 
00352 template<typename Derived1, typename Derived2, int Version>
00353 struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, CompleteUnrolling, Version>
00354 {
00355   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00356   {
00357     assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
00358       ::run(dst, src);
00359   }
00360 };
00361 
00362 template<typename Derived1, typename Derived2, int Version>
00363 struct assign_impl<Derived1, Derived2, InnerVectorizedTraversal, InnerUnrolling, Version>
00364 {
00365   typedef typename Derived1::Index Index;
00366   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00367   {
00368     const Index outerSize = dst.outerSize();
00369     for(Index outer = 0; outer < outerSize; ++outer)
00370       assign_innervec_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime>
00371         ::run(dst, src, outer);
00372   }
00373 };
00374 
00375 /***************************
00376 *** Linear vectorization ***
00377 ***************************/
00378 
00379 template <bool IsAligned = false>
00380 struct unaligned_assign_impl
00381 {
00382   template <typename Derived, typename OtherDerived>
00383   static EIGEN_STRONG_INLINE void run(const Derived&, OtherDerived&, typename Derived::Index, typename Derived::Index) {}
00384 };
00385 
00386 template <>
00387 struct unaligned_assign_impl<false>
00388 {
00389   // MSVC must not inline this functions. If it does, it fails to optimize the
00390   // packet access path.
00391 #ifdef _MSC_VER
00392   template <typename Derived, typename OtherDerived>
00393   static EIGEN_DONT_INLINE void run(const Derived& src, OtherDerived& dst, typename Derived::Index start, typename Derived::Index end)
00394 #else
00395   template <typename Derived, typename OtherDerived>
00396   static EIGEN_STRONG_INLINE void run(const Derived& src, OtherDerived& dst, typename Derived::Index start, typename Derived::Index end)
00397 #endif
00398   {
00399     for (typename Derived::Index index = start; index < end; ++index)
00400       dst.copyCoeff(index, src);
00401   }
00402 };
00403 
00404 template<typename Derived1, typename Derived2, int Version>
00405 struct assign_impl<Derived1, Derived2, LinearVectorizedTraversal, NoUnrolling, Version>
00406 {
00407   typedef typename Derived1::Index Index;
00408   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00409   {
00410     const Index size = dst.size();
00411     typedef packet_traits<typename Derived1::Scalar> PacketTraits;
00412     enum {
00413       packetSize = PacketTraits::size,
00414       dstAlignment = PacketTraits::AlignedOnScalar ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
00415       srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
00416     };
00417     const Index alignedStart = assign_traits<Derived1,Derived2>::DstIsAligned ? 0
00418                              : internal::first_aligned(&dst.coeffRef(0), size);
00419     const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
00420 
00421     unaligned_assign_impl<assign_traits<Derived1,Derived2>::DstIsAligned!=0>::run(src,dst,0,alignedStart);
00422 
00423     for(Index index = alignedStart; index < alignedEnd; index += packetSize)
00424     {
00425       dst.template copyPacket<Derived2, dstAlignment, srcAlignment>(index, src);
00426     }
00427 
00428     unaligned_assign_impl<>::run(src,dst,alignedEnd,size);
00429   }
00430 };
00431 
00432 template<typename Derived1, typename Derived2, int Version>
00433 struct assign_impl<Derived1, Derived2, LinearVectorizedTraversal, CompleteUnrolling, Version>
00434 {
00435   typedef typename Derived1::Index Index;
00436   static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src)
00437   {
00438     enum { size = Derived1::SizeAtCompileTime,
00439            packetSize = packet_traits<typename Derived1::Scalar>::size,
00440            alignedSize = (size/packetSize)*packetSize };
00441 
00442     assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, alignedSize>::run(dst, src);
00443     assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, alignedSize, size>::run(dst, src);
00444   }
00445 };
00446 
00447 /**************************
00448 *** Slice vectorization ***
00449 ***************************/
00450 
00451 template<typename Derived1, typename Derived2, int Version>
00452 struct assign_impl<Derived1, Derived2, SliceVectorizedTraversal, NoUnrolling, Version>
00453 {
00454   typedef typename Derived1::Index Index;
00455   static inline void run(Derived1 &dst, const Derived2 &src)
00456   {
00457     typedef packet_traits<typename Derived1::Scalar> PacketTraits;
00458     enum {
00459       packetSize = PacketTraits::size,
00460       alignable = PacketTraits::AlignedOnScalar,
00461       dstAlignment = alignable ? Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
00462       srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
00463     };
00464     const Index packetAlignedMask = packetSize - 1;
00465     const Index innerSize = dst.innerSize();
00466     const Index outerSize = dst.outerSize();
00467     const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0;
00468     Index alignedStart = ((!alignable) || assign_traits<Derived1,Derived2>::DstIsAligned) ? 0
00469                        : internal::first_aligned(&dst.coeffRef(0,0), innerSize);
00470 
00471     for(Index outer = 0; outer < outerSize; ++outer)
00472     {
00473       const Index alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
00474       // do the non-vectorizable part of the assignment
00475       for(Index inner = 0; inner<alignedStart ; ++inner)
00476         dst.copyCoeffByOuterInner(outer, inner, src);
00477 
00478       // do the vectorizable part of the assignment
00479       for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize)
00480         dst.template copyPacketByOuterInner<Derived2, dstAlignment, Unaligned>(outer, inner, src);
00481 
00482       // do the non-vectorizable part of the assignment
00483       for(Index inner = alignedEnd; inner<innerSize ; ++inner)
00484         dst.copyCoeffByOuterInner(outer, inner, src);
00485 
00486       alignedStart = std::min<Index>((alignedStart+alignedStep)%packetSize, innerSize);
00487     }
00488   }
00489 };
00490 
00491 } // end namespace internal
00492 
00493 /***************************************************************************
00494 * Part 4 : implementation of DenseBase methods
00495 ***************************************************************************/
00496 
00497 template<typename Derived>
00498 template<typename OtherDerived>
00499 EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
00500   ::lazyAssign(const DenseBase<OtherDerived>& other)
00501 {
00502   enum{
00503     SameType = internal::is_same<typename Derived::Scalar,typename OtherDerived::Scalar>::value
00504   };
00505 
00506   EIGEN_STATIC_ASSERT_LVALUE(Derived)
00507   EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
00508   EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00509 
00510 #ifdef EIGEN_DEBUG_ASSIGN
00511   internal::assign_traits<Derived, OtherDerived>::debug();
00512 #endif
00513   eigen_assert(rows() == other.rows() && cols() == other.cols());
00514   internal::assign_impl<Derived, OtherDerived, int(SameType) ? int(internal::assign_traits<Derived, OtherDerived>::Traversal)
00515                                                        : int(InvalidTraversal)>::run(derived(),other.derived());
00516 #ifndef EIGEN_NO_DEBUG
00517   checkTransposeAliasing(other.derived());
00518 #endif
00519   return derived();
00520 }
00521 
00522 namespace internal {
00523 
00524 template<typename Derived, typename OtherDerived,
00525          bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
00526          bool NeedToTranspose = Derived::IsVectorAtCompileTime
00527                 && OtherDerived::IsVectorAtCompileTime
00528                 && ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
00529                       |  // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
00530                          // revert to || as soon as not needed anymore.
00531                     (int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
00532                 && int(Derived::SizeAtCompileTime) != 1>
00533 struct assign_selector;
00534 
00535 template<typename Derived, typename OtherDerived>
00536 struct assign_selector<Derived,OtherDerived,false,false> {
00537   static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
00538 };
00539 template<typename Derived, typename OtherDerived>
00540 struct assign_selector<Derived,OtherDerived,true,false> {
00541   static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
00542 };
00543 template<typename Derived, typename OtherDerived>
00544 struct assign_selector<Derived,OtherDerived,false,true> {
00545   static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
00546 };
00547 template<typename Derived, typename OtherDerived>
00548 struct assign_selector<Derived,OtherDerived,true,true> {
00549   static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
00550 };
00551 
00552 } // end namespace internal
00553 
00554 template<typename Derived>
00555 template<typename OtherDerived>
00556 EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
00557 {
00558   return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
00559 }
00560 
00561 template<typename Derived>
00562 EIGEN_STRONG_INLINE Derived& DenseBase<Derived>::operator=(const DenseBase& other)
00563 {
00564   return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
00565 }
00566 
00567 template<typename Derived>
00568 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const MatrixBase& other)
00569 {
00570   return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
00571 }
00572 
00573 template<typename Derived>
00574 template <typename OtherDerived>
00575 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const DenseBase<OtherDerived>& other)
00576 {
00577   return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
00578 }
00579 
00580 template<typename Derived>
00581 template <typename OtherDerived>
00582 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
00583 {
00584   other.derived().evalTo(derived());
00585   return derived();
00586 }
00587 
00588 template<typename Derived>
00589 template<typename OtherDerived>
00590 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
00591 {
00592   other.evalTo(derived());
00593   return derived();
00594 }
00595 
00596 } // end namespace Eigen
00597 
00598 #endif // EIGEN_ASSIGN_H