00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef EIGEN_ASSIGN_H
00028 #define EIGEN_ASSIGN_H
00029
00030
00031
00032
00033
00034 template <typename Derived, typename OtherDerived>
00035 struct ei_assign_traits
00036 {
00037 public:
00038 enum {
00039 DstIsAligned = Derived::Flags & AlignedBit,
00040 SrcIsAligned = OtherDerived::Flags & AlignedBit,
00041 SrcAlignment = DstIsAligned && SrcIsAligned ? Aligned : Unaligned
00042 };
00043
00044 private:
00045 enum {
00046 InnerSize = int(Derived::Flags)&RowMajorBit
00047 ? Derived::ColsAtCompileTime
00048 : Derived::RowsAtCompileTime,
00049 InnerMaxSize = int(Derived::Flags)&RowMajorBit
00050 ? Derived::MaxColsAtCompileTime
00051 : Derived::MaxRowsAtCompileTime,
00052 PacketSize = ei_packet_traits<typename Derived::Scalar>::size
00053 };
00054
00055 enum {
00056 MightVectorize = (int(Derived::Flags) & int(OtherDerived::Flags) & ActualPacketAccessBit)
00057 && ((int(Derived::Flags)&RowMajorBit)==(int(OtherDerived::Flags)&RowMajorBit)),
00058 MayInnerVectorize = MightVectorize && int(InnerSize)!=Dynamic && int(InnerSize)%int(PacketSize)==0
00059 && int(DstIsAligned) && int(SrcIsAligned),
00060 MayLinearVectorize = MightVectorize && (int(Derived::Flags) & int(OtherDerived::Flags) & LinearAccessBit),
00061 MaySliceVectorize = MightVectorize && int(InnerMaxSize)>=3*PacketSize
00062
00063
00064 };
00065
00066 public:
00067 enum {
00068 Vectorization = int(MayInnerVectorize) ? int(InnerVectorization)
00069 : int(MayLinearVectorize) ? int(LinearVectorization)
00070 : int(MaySliceVectorize) ? int(SliceVectorization)
00071 : int(NoVectorization)
00072 };
00073
00074 private:
00075 enum {
00076 UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Vectorization) == int(NoVectorization) ? 1 : int(PacketSize)),
00077 MayUnrollCompletely = int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit),
00078 MayUnrollInner = int(InnerSize * OtherDerived::CoeffReadCost) <= int(UnrollingLimit)
00079 };
00080
00081 public:
00082 enum {
00083 Unrolling = (int(Vectorization) == int(InnerVectorization) || int(Vectorization) == int(NoVectorization))
00084 ? (
00085 int(MayUnrollCompletely) ? int(CompleteUnrolling)
00086 : int(MayUnrollInner) ? int(InnerUnrolling)
00087 : int(NoUnrolling)
00088 )
00089 : int(Vectorization) == int(LinearVectorization)
00090 ? ( int(MayUnrollCompletely) && int(DstIsAligned) ? int(CompleteUnrolling) : int(NoUnrolling) )
00091 : int(NoUnrolling)
00092 };
00093
00094 #ifdef EIGEN_DEBUG_ASSIGN
00095 #define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
00096 static void debug()
00097 {
00098 EIGEN_DEBUG_VAR(DstIsAligned)
00099 EIGEN_DEBUG_VAR(SrcIsAligned)
00100 EIGEN_DEBUG_VAR(SrcAlignment)
00101 EIGEN_DEBUG_VAR(InnerSize)
00102 EIGEN_DEBUG_VAR(InnerMaxSize)
00103 EIGEN_DEBUG_VAR(PacketSize)
00104 EIGEN_DEBUG_VAR(MightVectorize)
00105 EIGEN_DEBUG_VAR(MayInnerVectorize)
00106 EIGEN_DEBUG_VAR(MayLinearVectorize)
00107 EIGEN_DEBUG_VAR(MaySliceVectorize)
00108 EIGEN_DEBUG_VAR(Vectorization)
00109 EIGEN_DEBUG_VAR(UnrollingLimit)
00110 EIGEN_DEBUG_VAR(MayUnrollCompletely)
00111 EIGEN_DEBUG_VAR(MayUnrollInner)
00112 EIGEN_DEBUG_VAR(Unrolling)
00113 }
00114 #endif
00115 };
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 template<typename Derived1, typename Derived2, int Index, int Stop>
00126 struct ei_assign_novec_CompleteUnrolling
00127 {
00128 enum {
00129 row = int(Derived1::Flags)&RowMajorBit
00130 ? Index / int(Derived1::ColsAtCompileTime)
00131 : Index % Derived1::RowsAtCompileTime,
00132 col = int(Derived1::Flags)&RowMajorBit
00133 ? Index % int(Derived1::ColsAtCompileTime)
00134 : Index / Derived1::RowsAtCompileTime
00135 };
00136
00137 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
00138 {
00139 dst.copyCoeff(row, col, src);
00140 ei_assign_novec_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
00141 }
00142 };
00143
00144 template<typename Derived1, typename Derived2, int Stop>
00145 struct ei_assign_novec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
00146 {
00147 EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
00148 };
00149
00150 template<typename Derived1, typename Derived2, int Index, int Stop>
00151 struct ei_assign_novec_InnerUnrolling
00152 {
00153 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
00154 {
00155 const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
00156 const int row = rowMajor ? row_or_col : Index;
00157 const int col = rowMajor ? Index : row_or_col;
00158 dst.copyCoeff(row, col, src);
00159 ei_assign_novec_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, row_or_col);
00160 }
00161 };
00162
00163 template<typename Derived1, typename Derived2, int Stop>
00164 struct ei_assign_novec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
00165 {
00166 EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
00167 };
00168
00169
00170
00171
00172
00173 template<typename Derived1, typename Derived2, int Index, int Stop>
00174 struct ei_assign_innervec_CompleteUnrolling
00175 {
00176 enum {
00177 row = int(Derived1::Flags)&RowMajorBit
00178 ? Index / int(Derived1::ColsAtCompileTime)
00179 : Index % Derived1::RowsAtCompileTime,
00180 col = int(Derived1::Flags)&RowMajorBit
00181 ? Index % int(Derived1::ColsAtCompileTime)
00182 : Index / Derived1::RowsAtCompileTime,
00183 SrcAlignment = ei_assign_traits<Derived1,Derived2>::SrcAlignment
00184 };
00185
00186 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
00187 {
00188 dst.template copyPacket<Derived2, Aligned, SrcAlignment>(row, col, src);
00189 ei_assign_innervec_CompleteUnrolling<Derived1, Derived2,
00190 Index+ei_packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src);
00191 }
00192 };
00193
00194 template<typename Derived1, typename Derived2, int Stop>
00195 struct ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
00196 {
00197 EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {}
00198 };
00199
00200 template<typename Derived1, typename Derived2, int Index, int Stop>
00201 struct ei_assign_innervec_InnerUnrolling
00202 {
00203 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int row_or_col)
00204 {
00205 const int row = int(Derived1::Flags)&RowMajorBit ? row_or_col : Index;
00206 const int col = int(Derived1::Flags)&RowMajorBit ? Index : row_or_col;
00207 dst.template copyPacket<Derived2, Aligned, Aligned>(row, col, src);
00208 ei_assign_innervec_InnerUnrolling<Derived1, Derived2,
00209 Index+ei_packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src, row_or_col);
00210 }
00211 };
00212
00213 template<typename Derived1, typename Derived2, int Stop>
00214 struct ei_assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
00215 {
00216 EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {}
00217 };
00218
00219
00220
00221
00222
00223 template<typename Derived1, typename Derived2,
00224 int Vectorization = ei_assign_traits<Derived1, Derived2>::Vectorization,
00225 int Unrolling = ei_assign_traits<Derived1, Derived2>::Unrolling>
00226 struct ei_assign_impl;
00227
00228
00229
00230
00231
00232 template<typename Derived1, typename Derived2>
00233 struct ei_assign_impl<Derived1, Derived2, NoVectorization, NoUnrolling>
00234 {
00235 inline static void run(Derived1 &dst, const Derived2 &src)
00236 {
00237 const int innerSize = dst.innerSize();
00238 const int outerSize = dst.outerSize();
00239 for(int j = 0; j < outerSize; ++j)
00240 for(int i = 0; i < innerSize; ++i)
00241 {
00242 if(int(Derived1::Flags)&RowMajorBit)
00243 dst.copyCoeff(j, i, src);
00244 else
00245 dst.copyCoeff(i, j, src);
00246 }
00247 }
00248 };
00249
00250 template<typename Derived1, typename Derived2>
00251 struct ei_assign_impl<Derived1, Derived2, NoVectorization, CompleteUnrolling>
00252 {
00253 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
00254 {
00255 ei_assign_novec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
00256 ::run(dst, src);
00257 }
00258 };
00259
00260 template<typename Derived1, typename Derived2>
00261 struct ei_assign_impl<Derived1, Derived2, NoVectorization, InnerUnrolling>
00262 {
00263 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
00264 {
00265 const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
00266 const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
00267 const int outerSize = dst.outerSize();
00268 for(int j = 0; j < outerSize; ++j)
00269 ei_assign_novec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
00270 ::run(dst, src, j);
00271 }
00272 };
00273
00274
00275
00276
00277
00278 template<typename Derived1, typename Derived2>
00279 struct ei_assign_impl<Derived1, Derived2, InnerVectorization, NoUnrolling>
00280 {
00281 inline static void run(Derived1 &dst, const Derived2 &src)
00282 {
00283 const int innerSize = dst.innerSize();
00284 const int outerSize = dst.outerSize();
00285 const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
00286 for(int j = 0; j < outerSize; ++j)
00287 for(int i = 0; i < innerSize; i+=packetSize)
00288 {
00289 if(int(Derived1::Flags)&RowMajorBit)
00290 dst.template copyPacket<Derived2, Aligned, Aligned>(j, i, src);
00291 else
00292 dst.template copyPacket<Derived2, Aligned, Aligned>(i, j, src);
00293 }
00294 }
00295 };
00296
00297 template<typename Derived1, typename Derived2>
00298 struct ei_assign_impl<Derived1, Derived2, InnerVectorization, CompleteUnrolling>
00299 {
00300 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
00301 {
00302 ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
00303 ::run(dst, src);
00304 }
00305 };
00306
00307 template<typename Derived1, typename Derived2>
00308 struct ei_assign_impl<Derived1, Derived2, InnerVectorization, InnerUnrolling>
00309 {
00310 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
00311 {
00312 const bool rowMajor = int(Derived1::Flags)&RowMajorBit;
00313 const int innerSize = rowMajor ? Derived1::ColsAtCompileTime : Derived1::RowsAtCompileTime;
00314 const int outerSize = dst.outerSize();
00315 for(int j = 0; j < outerSize; ++j)
00316 ei_assign_innervec_InnerUnrolling<Derived1, Derived2, 0, innerSize>
00317 ::run(dst, src, j);
00318 }
00319 };
00320
00321
00322
00323
00324
00325 template<typename Derived1, typename Derived2>
00326 struct ei_assign_impl<Derived1, Derived2, LinearVectorization, NoUnrolling>
00327 {
00328 inline static void run(Derived1 &dst, const Derived2 &src)
00329 {
00330 const int size = dst.size();
00331 const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
00332 const int alignedStart = ei_assign_traits<Derived1,Derived2>::DstIsAligned ? 0
00333 : ei_alignmentOffset(&dst.coeffRef(0), size);
00334 const int alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
00335
00336 for(int index = 0; index < alignedStart; ++index)
00337 dst.copyCoeff(index, src);
00338
00339 for(int index = alignedStart; index < alignedEnd; index += packetSize)
00340 {
00341 dst.template copyPacket<Derived2, Aligned, ei_assign_traits<Derived1,Derived2>::SrcAlignment>(index, src);
00342 }
00343
00344 for(int index = alignedEnd; index < size; ++index)
00345 dst.copyCoeff(index, src);
00346 }
00347 };
00348
00349 template<typename Derived1, typename Derived2>
00350 struct ei_assign_impl<Derived1, Derived2, LinearVectorization, CompleteUnrolling>
00351 {
00352 EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src)
00353 {
00354 const int size = Derived1::SizeAtCompileTime;
00355 const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
00356 const int alignedSize = (size/packetSize)*packetSize;
00357
00358 ei_assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, alignedSize>::run(dst, src);
00359 ei_assign_novec_CompleteUnrolling<Derived1, Derived2, alignedSize, size>::run(dst, src);
00360 }
00361 };
00362
00363
00364
00365
00366
00367 template<typename Derived1, typename Derived2>
00368 struct ei_assign_impl<Derived1, Derived2, SliceVectorization, NoUnrolling>
00369 {
00370 inline static void run(Derived1 &dst, const Derived2 &src)
00371 {
00372 const int packetSize = ei_packet_traits<typename Derived1::Scalar>::size;
00373 const int packetAlignedMask = packetSize - 1;
00374 const int innerSize = dst.innerSize();
00375 const int outerSize = dst.outerSize();
00376 const int alignedStep = (packetSize - dst.stride() % packetSize) & packetAlignedMask;
00377 int alignedStart = ei_assign_traits<Derived1,Derived2>::DstIsAligned ? 0
00378 : ei_alignmentOffset(&dst.coeffRef(0,0), innerSize);
00379
00380 for(int i = 0; i < outerSize; ++i)
00381 {
00382 const int alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
00383
00384
00385 for (int index = 0; index<alignedStart ; ++index)
00386 {
00387 if(Derived1::Flags&RowMajorBit)
00388 dst.copyCoeff(i, index, src);
00389 else
00390 dst.copyCoeff(index, i, src);
00391 }
00392
00393
00394 for (int index = alignedStart; index<alignedEnd; index+=packetSize)
00395 {
00396 if(Derived1::Flags&RowMajorBit)
00397 dst.template copyPacket<Derived2, Aligned, Unaligned>(i, index, src);
00398 else
00399 dst.template copyPacket<Derived2, Aligned, Unaligned>(index, i, src);
00400 }
00401
00402
00403 for (int index = alignedEnd; index<innerSize ; ++index)
00404 {
00405 if(Derived1::Flags&RowMajorBit)
00406 dst.copyCoeff(i, index, src);
00407 else
00408 dst.copyCoeff(index, i, src);
00409 }
00410
00411 alignedStart = std::min<int>((alignedStart+alignedStep)%packetSize, innerSize);
00412 }
00413 }
00414 };
00415
00416
00417
00418
00419
00420 template<typename Derived>
00421 template<typename OtherDerived>
00422 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
00423 ::lazyAssign(const MatrixBase<OtherDerived>& other)
00424 {
00425 #ifdef EIGEN_DEBUG_ASSIGN
00426 ei_assign_traits<Derived, OtherDerived>::debug();
00427 #endif
00428 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Derived,OtherDerived)
00429 EIGEN_STATIC_ASSERT((ei_is_same_type<typename Derived::Scalar, typename OtherDerived::Scalar>::ret),
00430 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00431 ei_assert(rows() == other.rows() && cols() == other.cols());
00432 ei_assign_impl<Derived, OtherDerived>::run(derived(),other.derived());
00433 return derived();
00434 }
00435
00436 template<typename Derived, typename OtherDerived,
00437 bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0,
00438 bool NeedToTranspose = Derived::IsVectorAtCompileTime
00439 && OtherDerived::IsVectorAtCompileTime
00440 && int(Derived::RowsAtCompileTime) == int(OtherDerived::ColsAtCompileTime)
00441 && int(Derived::ColsAtCompileTime) == int(OtherDerived::RowsAtCompileTime)
00442 && int(Derived::SizeAtCompileTime) != 1>
00443 struct ei_assign_selector;
00444
00445 template<typename Derived, typename OtherDerived>
00446 struct ei_assign_selector<Derived,OtherDerived,false,false> {
00447 EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); }
00448 };
00449 template<typename Derived, typename OtherDerived>
00450 struct ei_assign_selector<Derived,OtherDerived,true,false> {
00451 EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); }
00452 };
00453 template<typename Derived, typename OtherDerived>
00454 struct ei_assign_selector<Derived,OtherDerived,false,true> {
00455 EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); }
00456 };
00457 template<typename Derived, typename OtherDerived>
00458 struct ei_assign_selector<Derived,OtherDerived,true,true> {
00459 EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
00460 };
00461
00462 template<typename Derived>
00463 template<typename OtherDerived>
00464 EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
00465 ::operator=(const MatrixBase<OtherDerived>& other)
00466 {
00467 return ei_assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
00468 }
00469
00470 #endif // EIGEN_ASSIGN_H