27 #ifndef EIGEN_ASSIGN_H
28 #define EIGEN_ASSIGN_H
38 template <
typename Derived,
typename OtherDerived>
45 SrcIsAligned = OtherDerived::Flags &
AlignedBit,
51 InnerSize =
int(Derived::IsVectorAtCompileTime) ?
int(Derived::SizeAtCompileTime)
53 :
int(Derived::RowsAtCompileTime),
54 InnerMaxSize =
int(Derived::IsVectorAtCompileTime) ?
int(Derived::MaxSizeAtCompileTime)
56 :
int(Derived::MaxRowsAtCompileTime),
57 MaxSizeAtCompileTime = Derived::SizeAtCompileTime,
58 PacketSize = packet_traits<typename Derived::Scalar>::size
62 StorageOrdersAgree = (
int(Derived::IsRowMajor) ==
int(OtherDerived::IsRowMajor)),
63 MightVectorize = StorageOrdersAgree
65 MayInnerVectorize = MightVectorize &&
int(InnerSize)!=
Dynamic &&
int(InnerSize)%
int(PacketSize)==0
66 &&
int(DstIsAligned) &&
int(SrcIsAligned),
67 MayLinearize = StorageOrdersAgree && (
int(Derived::Flags) &
int(OtherDerived::Flags) &
LinearAccessBit),
68 MayLinearVectorize = MightVectorize && MayLinearize && DstHasDirectAccess
69 && (DstIsAligned || MaxSizeAtCompileTime ==
Dynamic),
72 MaySliceVectorize = MightVectorize && DstHasDirectAccess
73 && (
int(InnerMaxSize)==
Dynamic ||
int(InnerMaxSize)>=3*PacketSize)
94 MayUnrollCompletely = int(Derived::SizeAtCompileTime) !=
Dynamic
95 && int(OtherDerived::CoeffReadCost) !=
Dynamic
96 && int(Derived::SizeAtCompileTime) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit),
97 MayUnrollInner = int(InnerSize) !=
Dynamic
98 && int(OtherDerived::CoeffReadCost) !=
Dynamic
99 && int(InnerSize) * int(OtherDerived::CoeffReadCost) <= int(UnrollingLimit)
117 #ifdef EIGEN_DEBUG_ASSIGN
149 template<
typename Derived1,
typename Derived2,
int Index,
int Stop>
150 struct assign_DefaultTraversal_CompleteUnrolling
153 outer = Index / Derived1::InnerSizeAtCompileTime,
154 inner = Index % Derived1::InnerSizeAtCompileTime
159 dst.copyCoeffByOuterInner(outer, inner, src);
160 assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
164 template<
typename Derived1,
typename Derived2,
int Stop>
165 struct assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
170 template<
typename Derived1,
typename Derived2,
int Index,
int Stop>
171 struct assign_DefaultTraversal_InnerUnrolling
175 dst.copyCoeffByOuterInner(outer, Index, src);
176 assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src, outer);
180 template<
typename Derived1,
typename Derived2,
int Stop>
181 struct assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, Stop, Stop>
190 template<
typename Derived1,
typename Derived2,
int Index,
int Stop>
191 struct assign_LinearTraversal_CompleteUnrolling
195 dst.copyCoeff(Index, src);
196 assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Index+1, Stop>::run(dst, src);
200 template<
typename Derived1,
typename Derived2,
int Stop>
201 struct assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
210 template<
typename Derived1,
typename Derived2,
int Index,
int Stop>
211 struct assign_innervec_CompleteUnrolling
214 outer = Index / Derived1::InnerSizeAtCompileTime,
215 inner = Index % Derived1::InnerSizeAtCompileTime,
216 JointAlignment = assign_traits<Derived1,Derived2>::JointAlignment
221 dst.template copyPacketByOuterInner<Derived2, Aligned, JointAlignment>(outer, inner, src);
222 assign_innervec_CompleteUnrolling<Derived1, Derived2,
223 Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src);
227 template<
typename Derived1,
typename Derived2,
int Stop>
228 struct assign_innervec_CompleteUnrolling<Derived1, Derived2, Stop, Stop>
233 template<
typename Derived1,
typename Derived2,
int Index,
int Stop>
234 struct assign_innervec_InnerUnrolling
238 dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, Index, src);
239 assign_innervec_InnerUnrolling<Derived1, Derived2,
240 Index+packet_traits<typename Derived1::Scalar>::size, Stop>::run(dst, src, outer);
244 template<
typename Derived1,
typename Derived2,
int Stop>
245 struct assign_innervec_InnerUnrolling<Derived1, Derived2, Stop, Stop>
254 template<
typename Derived1,
typename Derived2,
255 int Traversal = assign_traits<Derived1, Derived2>::Traversal,
256 int Unrolling = assign_traits<Derived1, Derived2>::Unrolling,
264 template<
typename Derived1,
typename Derived2,
int Unrolling,
int Version>
267 static inline void run(Derived1 &,
const Derived2 &) { }
270 template<
typename Derived1,
typename Derived2,
int Version>
273 typedef typename Derived1::Index Index;
274 static inline void run(Derived1 &dst,
const Derived2 &src)
276 const Index innerSize = dst.innerSize();
277 const Index outerSize = dst.outerSize();
278 for(Index outer = 0; outer < outerSize; ++outer)
279 for(Index inner = 0; inner < innerSize; ++inner)
280 dst.copyCoeffByOuterInner(outer, inner, src);
284 template<
typename Derived1,
typename Derived2,
int Version>
289 assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
294 template<
typename Derived1,
typename Derived2,
int Version>
297 typedef typename Derived1::Index Index;
300 const Index outerSize = dst.outerSize();
301 for(Index outer = 0; outer < outerSize; ++outer)
302 assign_DefaultTraversal_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime>
303 ::run(dst, src, outer);
311 template<
typename Derived1,
typename Derived2,
int Version>
314 typedef typename Derived1::Index Index;
315 static inline void run(Derived1 &dst,
const Derived2 &src)
317 const Index size = dst.size();
318 for(Index i = 0; i < size; ++i)
319 dst.copyCoeff(i, src);
323 template<
typename Derived1,
typename Derived2,
int Version>
328 assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
337 template<
typename Derived1,
typename Derived2,
int Version>
340 typedef typename Derived1::Index Index;
341 static inline void run(Derived1 &dst,
const Derived2 &src)
343 const Index innerSize = dst.innerSize();
344 const Index outerSize = dst.outerSize();
345 const Index packetSize = packet_traits<typename Derived1::Scalar>::size;
346 for(Index outer = 0; outer < outerSize; ++outer)
347 for(Index inner = 0; inner < innerSize; inner+=packetSize)
348 dst.template copyPacketByOuterInner<Derived2, Aligned, Aligned>(outer, inner, src);
352 template<
typename Derived1,
typename Derived2,
int Version>
357 assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, Derived1::SizeAtCompileTime>
362 template<
typename Derived1,
typename Derived2,
int Version>
365 typedef typename Derived1::Index Index;
368 const Index outerSize = dst.outerSize();
369 for(Index outer = 0; outer < outerSize; ++outer)
370 assign_innervec_InnerUnrolling<Derived1, Derived2, 0, Derived1::InnerSizeAtCompileTime>
371 ::run(dst, src, outer);
379 template <
bool IsAligned = false>
380 struct unaligned_assign_impl
382 template <
typename Derived,
typename OtherDerived>
383 static EIGEN_STRONG_INLINE void run(
const Derived&, OtherDerived&,
typename Derived::Index,
typename Derived::Index) {}
387 struct unaligned_assign_impl<false>
392 template <
typename Derived,
typename OtherDerived>
393 static EIGEN_DONT_INLINE void run(
const Derived& src, OtherDerived& dst,
typename Derived::Index start,
typename Derived::Index end)
395 template <
typename Derived,
typename OtherDerived>
396 static EIGEN_STRONG_INLINE void run(
const Derived& src, OtherDerived& dst,
typename Derived::Index start,
typename Derived::Index end)
399 for (
typename Derived::Index index = start; index < end; ++index)
400 dst.copyCoeff(index, src);
404 template<
typename Derived1,
typename Derived2,
int Version>
407 typedef typename Derived1::Index Index;
410 const Index size = dst.size();
411 typedef packet_traits<typename Derived1::Scalar> PacketTraits;
413 packetSize = PacketTraits::size,
414 dstAlignment = PacketTraits::AlignedOnScalar ?
Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
415 srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
417 const Index alignedStart = assign_traits<Derived1,Derived2>::DstIsAligned ? 0
418 : internal::first_aligned(&dst.coeffRef(0), size);
419 const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
421 unaligned_assign_impl<assign_traits<Derived1,Derived2>::DstIsAligned!=0>::run(src,dst,0,alignedStart);
423 for(Index index = alignedStart; index < alignedEnd; index += packetSize)
425 dst.template copyPacket<Derived2, dstAlignment, srcAlignment>(index, src);
428 unaligned_assign_impl<>::run(src,dst,alignedEnd,size);
432 template<
typename Derived1,
typename Derived2,
int Version>
435 typedef typename Derived1::Index Index;
438 enum { size = Derived1::SizeAtCompileTime,
439 packetSize = packet_traits<typename Derived1::Scalar>::size,
440 alignedSize = (size/packetSize)*packetSize };
442 assign_innervec_CompleteUnrolling<Derived1, Derived2, 0, alignedSize>::run(dst, src);
443 assign_DefaultTraversal_CompleteUnrolling<Derived1, Derived2, alignedSize, size>::run(dst, src);
451 template<
typename Derived1,
typename Derived2,
int Version>
454 typedef typename Derived1::Index Index;
455 static inline void run(Derived1 &dst,
const Derived2 &src)
457 typedef packet_traits<typename Derived1::Scalar> PacketTraits;
459 packetSize = PacketTraits::size,
460 alignable = PacketTraits::AlignedOnScalar,
461 dstAlignment = alignable ?
Aligned : int(assign_traits<Derived1,Derived2>::DstIsAligned) ,
462 srcAlignment = assign_traits<Derived1,Derived2>::JointAlignment
464 const Index packetAlignedMask = packetSize - 1;
465 const Index innerSize = dst.innerSize();
466 const Index outerSize = dst.outerSize();
467 const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0;
468 Index alignedStart = ((!alignable) || assign_traits<Derived1,Derived2>::DstIsAligned) ? 0
469 : internal::first_aligned(&dst.coeffRef(0,0), innerSize);
471 for(Index outer = 0; outer < outerSize; ++outer)
473 const Index alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
475 for(Index inner = 0; inner<alignedStart ; ++inner)
476 dst.copyCoeffByOuterInner(outer, inner, src);
479 for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize)
480 dst.template copyPacketByOuterInner<Derived2, dstAlignment, Unaligned>(outer, inner, src);
483 for(Index inner = alignedEnd; inner<innerSize ; ++inner)
484 dst.copyCoeffByOuterInner(outer, inner, src);
486 alignedStart = std::min<Index>((alignedStart+alignedStep)%packetSize, innerSize);
497 template<
typename Derived>
498 template<
typename OtherDerived>
500 ::lazyAssign(
const DenseBase<OtherDerived>& other)
503 SameType = internal::is_same<typename Derived::Scalar,typename OtherDerived::Scalar>::value
508 EIGEN_STATIC_ASSERT(SameType,YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
510 #ifdef EIGEN_DEBUG_ASSIGN
511 internal::assign_traits<Derived, OtherDerived>::debug();
513 eigen_assert(rows() == other.rows() && cols() == other.cols());
514 internal::assign_impl<Derived, OtherDerived, int(SameType) ? int(internal::assign_traits<Derived, OtherDerived>::Traversal)
516 #ifndef EIGEN_NO_DEBUG
517 checkTransposeAliasing(other.derived());
524 template<
typename Derived,
typename OtherDerived,
526 bool NeedToTranspose = Derived::IsVectorAtCompileTime
527 && OtherDerived::IsVectorAtCompileTime
528 && ((
int(Derived::RowsAtCompileTime) == 1 &&
int(OtherDerived::ColsAtCompileTime) == 1)
531 (int(Derived::ColsAtCompileTime) == 1 && int(OtherDerived::RowsAtCompileTime) == 1))
532 && int(Derived::SizeAtCompileTime) != 1>
533 struct assign_selector;
535 template<
typename Derived,
typename OtherDerived>
536 struct assign_selector<Derived,OtherDerived,false,false> {
537 static EIGEN_STRONG_INLINE Derived& run(Derived& dst,
const OtherDerived& other) {
return dst.lazyAssign(other.derived()); }
539 template<
typename Derived,
typename OtherDerived>
540 struct assign_selector<Derived,OtherDerived,true,false> {
541 static EIGEN_STRONG_INLINE Derived& run(Derived& dst,
const OtherDerived& other) {
return dst.lazyAssign(other.eval()); }
543 template<
typename Derived,
typename OtherDerived>
544 struct assign_selector<Derived,OtherDerived,false,true> {
545 static EIGEN_STRONG_INLINE Derived& run(Derived& dst,
const OtherDerived& other) {
return dst.lazyAssign(other.transpose()); }
547 template<
typename Derived,
typename OtherDerived>
548 struct assign_selector<Derived,OtherDerived,true,true> {
549 static EIGEN_STRONG_INLINE Derived& run(Derived& dst,
const OtherDerived& other) {
return dst.lazyAssign(other.transpose().eval()); }
554 template<
typename Derived>
555 template<
typename OtherDerived>
558 return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
561 template<
typename Derived>
564 return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
567 template<
typename Derived>
570 return internal::assign_selector<Derived,Derived>::run(derived(), other.derived());
573 template<
typename Derived>
574 template <
typename OtherDerived>
577 return internal::assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
580 template<
typename Derived>
581 template <
typename OtherDerived>
584 other.
derived().evalTo(derived());
588 template<
typename Derived>
589 template<
typename OtherDerived>
598 #endif // EIGEN_ASSIGN_H