Medial Code Documentation
Loading...
Searching...
No Matches
AssignEvaluator.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
5// Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
6// Copyright (C) 2011-2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
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_EVALUATOR_H
13#define EIGEN_ASSIGN_EVALUATOR_H
14
15namespace Eigen {
16
17 // This implementation is based on Assign.h
18
19 namespace internal {
20
21 /***************************************************************************
22 * Part 1 : the logic deciding a strategy for traversal and unrolling *
23 ***************************************************************************/
24
25 // copy_using_evaluator_traits is based on assign_traits
26
27 template <typename DstEvaluator, typename SrcEvaluator, typename AssignFunc>
29 {
30 typedef typename DstEvaluator::XprType Dst;
31 typedef typename Dst::Scalar DstScalar;
32 // TODO distinguish between linear traversal and inner-traversals
33 typedef typename find_best_packet<DstScalar, Dst::SizeAtCompileTime>::type PacketType;
34
35 enum {
36 DstFlags = DstEvaluator::Flags,
37 SrcFlags = SrcEvaluator::Flags,
39 };
40
41 public:
42 enum {
43 DstAlignment = DstEvaluator::Alignment,
44 SrcAlignment = SrcEvaluator::Alignment,
45 DstHasDirectAccess = DstFlags & DirectAccessBit,
46 JointAlignment = EIGEN_PLAIN_ENUM_MIN(DstAlignment, SrcAlignment)
47 };
48
49 private:
50 enum {
51 InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime)
52 : int(DstFlags)&RowMajorBit ? int(Dst::ColsAtCompileTime)
53 : int(Dst::RowsAtCompileTime),
54 InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime)
55 : int(DstFlags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime)
56 : int(Dst::MaxRowsAtCompileTime),
58 MaxSizeAtCompileTime = Dst::SizeAtCompileTime,
60 };
61
62 enum {
63 DstIsRowMajor = DstFlags & RowMajorBit,
64 SrcIsRowMajor = SrcFlags & RowMajorBit,
65 StorageOrdersAgree = (int(DstIsRowMajor) == int(SrcIsRowMajor)),
66 MightVectorize = StorageOrdersAgree
67 && (int(DstFlags) & int(SrcFlags) & ActualPacketAccessBit)
69 MayInnerVectorize = MightVectorize
70 && int(InnerSize) != Dynamic && int(InnerSize) % int(PacketSize) == 0
71 && int(OuterStride) != Dynamic && int(OuterStride) % int(PacketSize) == 0
72 && int(JointAlignment) >= int(RequiredAlignment),
73 MayLinearize = StorageOrdersAgree && (int(DstFlags) & int(SrcFlags) & LinearAccessBit),
74 MayLinearVectorize = MightVectorize != 0 && MayLinearize != 0 && DstHasDirectAccess != 0
75 && ((int(DstAlignment) >= int(RequiredAlignment)) || MaxSizeAtCompileTime == Dynamic),
76 /* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
77 so it's only good for large enough sizes. */
78 MaySliceVectorize = MightVectorize != 0 && DstHasDirectAccess != 0
79 && (int(InnerMaxSize) == Dynamic || int(InnerMaxSize) >= 3 * PacketSize)
80 /* slice vectorization can be slow, so we only want it if the slices are big, which is
81 indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block
82 in a fixed-size matrix */
83 };
84
85 public:
86 enum {
87 Traversal = int(MayInnerVectorize) ? int(InnerVectorizedTraversal)
88 : int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
89 : int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
90 : int(MayLinearize) ? int(LinearTraversal)
91 : int(DefaultTraversal),
92 Vectorized = int(Traversal) == InnerVectorizedTraversal
93 || int(Traversal) == LinearVectorizedTraversal
94 || int(Traversal) == SliceVectorizedTraversal
95 };
96
97 private:
98 enum {
99 UnrollingLimit = EIGEN_UNROLLING_LIMIT * (Vectorized ? int(PacketSize) : 1),
100 MayUnrollCompletely = int(Dst::SizeAtCompileTime) != Dynamic
101 && int(Dst::SizeAtCompileTime) * int(SrcEvaluator::CoeffReadCost) <= int(UnrollingLimit),
102 MayUnrollInner = int(InnerSize) != Dynamic
103 && int(InnerSize) * int(SrcEvaluator::CoeffReadCost) <= int(UnrollingLimit)
104 };
105
106 public:
107 enum {
108 Unrolling = (int(Traversal) == int(InnerVectorizedTraversal) || int(Traversal) == int(DefaultTraversal))
109 ? (
110 int(MayUnrollCompletely) ? int(CompleteUnrolling)
111 : int(MayUnrollInner) ? int(InnerUnrolling)
112 : int(NoUnrolling)
113 )
114 : int(Traversal) == int(LinearVectorizedTraversal)
115 ? (bool(MayUnrollCompletely) && (int(DstAlignment) >= int(RequiredAlignment)) ? int(CompleteUnrolling)
116 : int(NoUnrolling))
117 : int(Traversal) == int(LinearTraversal)
118 ? (bool(MayUnrollCompletely) ? int(CompleteUnrolling)
119 : int(NoUnrolling))
120 : int(NoUnrolling)
121 };
122
123#ifdef EIGEN_DEBUG_ASSIGN
124 static void debug()
125 {
126 std::cerr << "DstXpr: " << typeid(typename DstEvaluator::XprType).name() << std::endl;
127 std::cerr << "SrcXpr: " << typeid(typename SrcEvaluator::XprType).name() << std::endl;
128 std::cerr.setf(std::ios::hex, std::ios::basefield);
129 std::cerr << "DstFlags" << " = " << DstFlags << " (" << demangle_flags(DstFlags) << " )" << std::endl;
130 std::cerr << "SrcFlags" << " = " << SrcFlags << " (" << demangle_flags(SrcFlags) << " )" << std::endl;
131 std::cerr.unsetf(std::ios::hex);
132 EIGEN_DEBUG_VAR(DstAlignment)
133 EIGEN_DEBUG_VAR(SrcAlignment)
134 EIGEN_DEBUG_VAR(RequiredAlignment)
135 EIGEN_DEBUG_VAR(JointAlignment)
136 EIGEN_DEBUG_VAR(InnerSize)
137 EIGEN_DEBUG_VAR(InnerMaxSize)
138 EIGEN_DEBUG_VAR(PacketSize)
139 EIGEN_DEBUG_VAR(StorageOrdersAgree)
140 EIGEN_DEBUG_VAR(MightVectorize)
141 EIGEN_DEBUG_VAR(MayLinearize)
142 EIGEN_DEBUG_VAR(MayInnerVectorize)
143 EIGEN_DEBUG_VAR(MayLinearVectorize)
144 EIGEN_DEBUG_VAR(MaySliceVectorize)
145 std::cerr << "Traversal" << " = " << Traversal << " (" << demangle_traversal(Traversal) << ")" << std::endl;
146 EIGEN_DEBUG_VAR(UnrollingLimit)
147 EIGEN_DEBUG_VAR(MayUnrollCompletely)
148 EIGEN_DEBUG_VAR(MayUnrollInner)
149 std::cerr << "Unrolling" << " = " << Unrolling << " (" << demangle_unrolling(Unrolling) << ")" << std::endl;
150 std::cerr << std::endl;
151 }
152#endif
153 };
154
155 /***************************************************************************
156 * Part 2 : meta-unrollers
157 ***************************************************************************/
158
159 /************************
160 *** Default traversal ***
161 ************************/
162
163 template<typename Kernel, int Index, int Stop>
165 {
166 // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
167 typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
168 typedef typename DstEvaluatorType::XprType DstXprType;
169
170 enum {
171 outer = Index / DstXprType::InnerSizeAtCompileTime,
172 inner = Index % DstXprType::InnerSizeAtCompileTime
173 };
174
175 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
176 {
177 kernel.assignCoeffByOuterInner(outer, inner);
179 }
180 };
181
182 template<typename Kernel, int Stop>
184 {
185 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
186 };
187
188 template<typename Kernel, int Index_, int Stop>
190 {
191 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
192 {
193 kernel.assignCoeffByOuterInner(outer, Index_);
195 }
196 };
197
198 template<typename Kernel, int Stop>
200 {
201 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&, Index) { }
202 };
203
204 /***********************
205 *** Linear traversal ***
206 ***********************/
207
208 template<typename Kernel, int Index, int Stop>
210 {
211 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel)
212 {
213 kernel.assignCoeff(Index);
215 }
216 };
217
218 template<typename Kernel, int Stop>
220 {
221 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
222 };
223
224 /**************************
225 *** Inner vectorization ***
226 **************************/
227
228 template<typename Kernel, int Index, int Stop>
230 {
231 // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
232 typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
233 typedef typename DstEvaluatorType::XprType DstXprType;
234 typedef typename Kernel::PacketType PacketType;
235
236 enum {
237 outer = Index / DstXprType::InnerSizeAtCompileTime,
238 inner = Index % DstXprType::InnerSizeAtCompileTime,
239 JointAlignment = Kernel::AssignmentTraits::JointAlignment
240 };
241
242 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
243 {
247 }
248 };
249
250 template<typename Kernel, int Stop>
252 {
253 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
254 };
255
256 template<typename Kernel, int Index_, int Stop>
258 {
259 typedef typename Kernel::PacketType PacketType;
260 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
261 {
265 }
266 };
267
268 template<typename Kernel, int Stop>
270 {
271 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &, Index) { }
272 };
273
274 /***************************************************************************
275 * Part 3 : implementation of all cases
276 ***************************************************************************/
277
278 // dense_assignment_loop is based on assign_impl
279
280 template<typename Kernel,
281 int Traversal = Kernel::AssignmentTraits::Traversal,
282 int Unrolling = Kernel::AssignmentTraits::Unrolling>
284
285 /************************
286 *** Default traversal ***
287 ************************/
288
289 template<typename Kernel>
290 struct dense_assignment_loop<Kernel, DefaultTraversal, NoUnrolling>
291 {
292 EIGEN_DEVICE_FUNC static void EIGEN_STRONG_INLINE run(Kernel &kernel)
293 {
294 for (Index outer = 0; outer < kernel.outerSize(); ++outer) {
295 for (Index inner = 0; inner < kernel.innerSize(); ++inner) {
296 kernel.assignCoeffByOuterInner(outer, inner);
297 }
298 }
299 }
300 };
301
302 template<typename Kernel>
303 struct dense_assignment_loop<Kernel, DefaultTraversal, CompleteUnrolling>
304 {
305 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
306 {
307 typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
309 }
310 };
311
312 template<typename Kernel>
313 struct dense_assignment_loop<Kernel, DefaultTraversal, InnerUnrolling>
314 {
315 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
316 {
317 typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
318
319 const Index outerSize = kernel.outerSize();
320 for (Index outer = 0; outer < outerSize; ++outer)
322 }
323 };
324
325 /***************************
326 *** Linear vectorization ***
327 ***************************/
328
329
330 // The goal of unaligned_dense_assignment_loop is simply to factorize the handling
331 // of the non vectorizable beginning and ending parts
332
333 template <bool IsAligned = false>
335 {
336 // if IsAligned = true, then do nothing
337 template <typename Kernel>
338 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&, Index, Index) {}
339 };
340
341 template <>
343 {
344 // MSVC must not inline this functions. If it does, it fails to optimize the
345 // packet access path.
346 // FIXME check which version exhibits this issue
347#if EIGEN_COMP_MSVC
348 template <typename Kernel>
349 static EIGEN_DONT_INLINE void run(Kernel &kernel,
350 Index start,
351 Index end)
352#else
353 template <typename Kernel>
354 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel,
355 Index start,
356 Index end)
357#endif
358 {
359 for (Index index = start; index < end; ++index)
360 kernel.assignCoeff(index);
361 }
362 };
363
364 template<typename Kernel>
365 struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, NoUnrolling>
366 {
367 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
368 {
369 const Index size = kernel.size();
370 typedef typename Kernel::Scalar Scalar;
371 typedef typename Kernel::PacketType PacketType;
372 enum {
373 requestedAlignment = Kernel::AssignmentTraits::RequiredAlignment,
375 dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment) >= int(requestedAlignment),
377 : int(Kernel::AssignmentTraits::DstAlignment),
378 srcAlignment = Kernel::AssignmentTraits::JointAlignment
379 };
380 const Index alignedStart = dstIsAligned ? 0 : internal::first_aligned<requestedAlignment>(&kernel.dstEvaluator().coeffRef(0), size);
381 const Index alignedEnd = alignedStart + ((size - alignedStart) / packetSize)*packetSize;
382
384
385 for (Index index = alignedStart; index < alignedEnd; index += packetSize)
387
389 }
390 };
391
392 template<typename Kernel>
393 struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, CompleteUnrolling>
394 {
395 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
396 {
397 typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
398
399 enum {
400 size = DstXprType::SizeAtCompileTime,
403 };
404
407 }
408 };
409
410 /**************************
411 *** Inner vectorization ***
412 **************************/
413
414 template<typename Kernel>
415 struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, NoUnrolling>
416 {
417 typedef typename Kernel::PacketType PacketType;
418 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
419 {
420 const Index innerSize = kernel.innerSize();
421 const Index outerSize = kernel.outerSize();
423 for (Index outer = 0; outer < outerSize; ++outer)
424 for (Index inner = 0; inner < innerSize; inner += packetSize)
425 kernel.template assignPacketByOuterInner<Aligned, Aligned, PacketType>(outer, inner);
426 }
427 };
428
429 template<typename Kernel>
430 struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, CompleteUnrolling>
431 {
432 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
433 {
434 typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
436 }
437 };
438
439 template<typename Kernel>
440 struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, InnerUnrolling>
441 {
442 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
443 {
444 typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
445 const Index outerSize = kernel.outerSize();
446 for (Index outer = 0; outer < outerSize; ++outer)
448 }
449 };
450
451 /***********************
452 *** Linear traversal ***
453 ***********************/
454
455 template<typename Kernel>
456 struct dense_assignment_loop<Kernel, LinearTraversal, NoUnrolling>
457 {
458 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
459 {
460 const Index size = kernel.size();
461 for (Index i = 0; i < size; ++i)
462 kernel.assignCoeff(i);
463 }
464 };
465
466 template<typename Kernel>
467 struct dense_assignment_loop<Kernel, LinearTraversal, CompleteUnrolling>
468 {
469 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
470 {
471 typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
473 }
474 };
475
476 /**************************
477 *** Slice vectorization ***
478 ***************************/
479
480 template<typename Kernel>
481 struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
482 {
483 EIGEN_DEVICE_FUNC static inline void run(Kernel &kernel)
484 {
485 typedef typename Kernel::Scalar Scalar;
486 typedef typename Kernel::PacketType PacketType;
487 enum {
489 requestedAlignment = int(Kernel::AssignmentTraits::RequiredAlignment),
490 alignable = packet_traits<Scalar>::AlignedOnScalar || int(Kernel::AssignmentTraits::DstAlignment) >= sizeof(Scalar),
491 dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment) >= int(requestedAlignment),
493 : int(Kernel::AssignmentTraits::DstAlignment)
494 };
495 const Scalar *dst_ptr = &kernel.dstEvaluator().coeffRef(0, 0);
496 if ((!bool(dstIsAligned)) && (size_t(dst_ptr) % sizeof(Scalar)) > 0)
497 {
498 // the pointer is not aligend-on scalar, so alignment is not possible
500 }
501 const Index packetAlignedMask = packetSize - 1;
502 const Index innerSize = kernel.innerSize();
503 const Index outerSize = kernel.outerSize();
504 const Index alignedStep = alignable ? (packetSize - kernel.outerStride() % packetSize) & packetAlignedMask : 0;
505 Index alignedStart = ((!alignable) || bool(dstIsAligned)) ? 0 : internal::first_aligned<requestedAlignment>(dst_ptr, innerSize);
506
507 for (Index outer = 0; outer < outerSize; ++outer)
508 {
509 const Index alignedEnd = alignedStart + ((innerSize - alignedStart) & ~packetAlignedMask);
510 // do the non-vectorizable part of the assignment
511 for (Index inner = 0; inner < alignedStart; ++inner)
512 kernel.assignCoeffByOuterInner(outer, inner);
513
514 // do the vectorizable part of the assignment
515 for (Index inner = alignedStart; inner < alignedEnd; inner += packetSize)
517
518 // do the non-vectorizable part of the assignment
519 for (Index inner = alignedEnd; inner < innerSize; ++inner)
520 kernel.assignCoeffByOuterInner(outer, inner);
521
522 alignedStart = std::min<Index>((alignedStart + alignedStep) % packetSize, innerSize);
523 }
524 }
525 };
526
527 /***************************************************************************
528 * Part 4 : Generic dense assignment kernel
529 ***************************************************************************/
530
531 // This class generalize the assignment of a coefficient (or packet) from one dense evaluator
532 // to another dense writable evaluator.
533 // It is parametrized by the two evaluators, and the actual assignment functor.
534 // This abstraction level permits to keep the evaluation loops as simple and as generic as possible.
535 // One can customize the assignment using this generic dense_assignment_kernel with different
536 // functors, or by completely overloading it, by-passing a functor.
537 template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor, int Version = Specialized>
539 {
540 protected:
541 typedef typename DstEvaluatorTypeT::XprType DstXprType;
542 typedef typename SrcEvaluatorTypeT::XprType SrcXprType;
543 public:
544
545 typedef DstEvaluatorTypeT DstEvaluatorType;
546 typedef SrcEvaluatorTypeT SrcEvaluatorType;
547 typedef typename DstEvaluatorType::Scalar Scalar;
549 typedef typename AssignmentTraits::PacketType PacketType;
550
551
552 EIGEN_DEVICE_FUNC generic_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr)
553 : m_dst(dst), m_src(src), m_functor(func), m_dstExpr(dstExpr)
554 {
555#ifdef EIGEN_DEBUG_ASSIGN
556 AssignmentTraits::debug();
557#endif
558 }
559
560 EIGEN_DEVICE_FUNC Index size() const { return m_dstExpr.size(); }
561 EIGEN_DEVICE_FUNC Index innerSize() const { return m_dstExpr.innerSize(); }
562 EIGEN_DEVICE_FUNC Index outerSize() const { return m_dstExpr.outerSize(); }
563 EIGEN_DEVICE_FUNC Index rows() const { return m_dstExpr.rows(); }
564 EIGEN_DEVICE_FUNC Index cols() const { return m_dstExpr.cols(); }
565 EIGEN_DEVICE_FUNC Index outerStride() const { return m_dstExpr.outerStride(); }
566
567 EIGEN_DEVICE_FUNC DstEvaluatorType& dstEvaluator() { return m_dst; }
568 EIGEN_DEVICE_FUNC const SrcEvaluatorType& srcEvaluator() const { return m_src; }
569
571 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index row, Index col)
572 {
573 m_functor.assignCoeff(m_dst.coeffRef(row, col), m_src.coeff(row, col));
574 }
575
577 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index index)
578 {
579 m_functor.assignCoeff(m_dst.coeffRef(index), m_src.coeff(index));
580 }
581
583 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeffByOuterInner(Index outer, Index inner)
584 {
585 Index row = rowIndexByOuterInner(outer, inner);
586 Index col = colIndexByOuterInner(outer, inner);
587 assignCoeff(row, col);
588 }
589
590
591 template<int StoreMode, int LoadMode, typename PacketType>
592 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index row, Index col)
593 {
594 m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(row, col), m_src.template packet<LoadMode, PacketType>(row, col));
595 }
596
597 template<int StoreMode, int LoadMode, typename PacketType>
598 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index index)
599 {
600 m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(index), m_src.template packet<LoadMode, PacketType>(index));
601 }
602
603 template<int StoreMode, int LoadMode, typename PacketType>
604 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketByOuterInner(Index outer, Index inner)
605 {
606 Index row = rowIndexByOuterInner(outer, inner);
607 Index col = colIndexByOuterInner(outer, inner);
608 assignPacket<StoreMode, LoadMode, PacketType>(row, col);
609 }
610
611 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner)
612 {
613 typedef typename DstEvaluatorType::ExpressionTraits Traits;
614 return int(Traits::RowsAtCompileTime) == 1 ? 0
615 : int(Traits::ColsAtCompileTime) == 1 ? inner
616 : int(DstEvaluatorType::Flags)&RowMajorBit ? outer
617 : inner;
618 }
619
620 EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner)
621 {
622 typedef typename DstEvaluatorType::ExpressionTraits Traits;
623 return int(Traits::ColsAtCompileTime) == 1 ? 0
624 : int(Traits::RowsAtCompileTime) == 1 ? inner
625 : int(DstEvaluatorType::Flags)&RowMajorBit ? inner
626 : outer;
627 }
628
629 protected:
630 DstEvaluatorType & m_dst;
631 const SrcEvaluatorType& m_src;
632 const Functor &m_functor;
633 // TODO find a way to avoid the needs of the original expression
634 DstXprType& m_dstExpr;
635 };
636
637 /***************************************************************************
638 * Part 5 : Entry point for dense rectangular assignment
639 ***************************************************************************/
640
641 template<typename DstXprType, typename SrcXprType, typename Functor>
642 EIGEN_DEVICE_FUNC void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src, const Functor &func)
643 {
644 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
645
646 typedef evaluator<DstXprType> DstEvaluatorType;
647 typedef evaluator<SrcXprType> SrcEvaluatorType;
648
649 DstEvaluatorType dstEvaluator(dst);
650 SrcEvaluatorType srcEvaluator(src);
651
652 typedef generic_dense_assignment_kernel<DstEvaluatorType, SrcEvaluatorType, Functor> Kernel;
653 Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
654
655 dense_assignment_loop<Kernel>::run(kernel);
656 }
657
658 template<typename DstXprType, typename SrcXprType>
659 EIGEN_DEVICE_FUNC void call_dense_assignment_loop(const DstXprType& dst, const SrcXprType& src)
660 {
661 call_dense_assignment_loop(dst, src, internal::assign_op<typename DstXprType::Scalar>());
662 }
663
664 /***************************************************************************
665 * Part 6 : Generic assignment
666 ***************************************************************************/
667
668 // Based on the respective shapes of the destination and source,
669 // the class AssignmentKind determine the kind of assignment mechanism.
670 // AssignmentKind must define a Kind typedef.
671 template<typename DstShape, typename SrcShape> struct AssignmentKind;
672
673 // Assignement kind defined in this file:
674 struct Dense2Dense {};
676
677 template<typename, typename> struct AssignmentKind { typedef EigenBase2EigenBase Kind; };
678 template<> struct AssignmentKind<DenseShape, DenseShape> { typedef Dense2Dense Kind; };
679
680 // This is the main assignment class
681 template< typename DstXprType, typename SrcXprType, typename Functor,
682 typename Kind = typename AssignmentKind< typename evaluator_traits<DstXprType>::Shape, typename evaluator_traits<SrcXprType>::Shape >::Kind,
683 typename Scalar = typename DstXprType::Scalar>
685
686
687 // The only purpose of this call_assignment() function is to deal with noalias() / AssumeAliasing and automatic transposition.
688 // Indeed, I (Gael) think that this concept of AssumeAliasing was a mistake, and it makes thing quite complicated.
689 // So this intermediate function removes everything related to AssumeAliasing such that Assignment
690 // does not has to bother about these annoying details.
691
692 template<typename Dst, typename Src>
693 EIGEN_DEVICE_FUNC void call_assignment(Dst& dst, const Src& src)
694 {
696 }
697 template<typename Dst, typename Src>
698 EIGEN_DEVICE_FUNC void call_assignment(const Dst& dst, const Src& src)
699 {
701 }
702
703 // Deal with AssumeAliasing
704 template<typename Dst, typename Src, typename Func>
705 EIGEN_DEVICE_FUNC void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if<evaluator_traits<Src>::AssumeAliasing == 1, void*>::type = 0)
706 {
707 typename plain_matrix_type<Src>::type tmp(src);
708 call_assignment_no_alias(dst, tmp, func);
709 }
710
711 template<typename Dst, typename Src, typename Func>
712 EIGEN_DEVICE_FUNC void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if<evaluator_traits<Src>::AssumeAliasing == 0, void*>::type = 0)
713 {
714 call_assignment_no_alias(dst, src, func);
715 }
716
717 // by-pass AssumeAliasing
718 // When there is no aliasing, we require that 'dst' has been properly resized
719 template<typename Dst, template <typename> class StorageBase, typename Src, typename Func>
720 EIGEN_DEVICE_FUNC void call_assignment(NoAlias<Dst, StorageBase>& dst, const Src& src, const Func& func)
721 {
722 call_assignment_no_alias(dst.expression(), src, func);
723 }
724
725
726 template<typename Dst, typename Src, typename Func>
727 EIGEN_DEVICE_FUNC void call_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
728 {
729 enum {
730 NeedToTranspose = ((int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1)
731 || (int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1)
732 ) && int(Dst::SizeAtCompileTime) != 1
733 };
734
735 Index dstRows = NeedToTranspose ? src.cols() : src.rows();
736 Index dstCols = NeedToTranspose ? src.rows() : src.cols();
737 if ((dst.rows() != dstRows) || (dst.cols() != dstCols))
738 dst.resize(dstRows, dstCols);
739
740 typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst>::type ActualDstTypeCleaned;
741 typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst&>::type ActualDstType;
742 ActualDstType actualDst(dst);
743
744 // TODO check whether this is the right place to perform these checks:
745 EIGEN_STATIC_ASSERT_LVALUE(Dst)
746 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned, Src)
747 EIGEN_CHECK_BINARY_COMPATIBILIY(Func, typename ActualDstTypeCleaned::Scalar, typename Src::Scalar);
748
749 Assignment<ActualDstTypeCleaned, Src, Func>::run(actualDst, src, func);
750 }
751 template<typename Dst, typename Src>
752 EIGEN_DEVICE_FUNC void call_assignment_no_alias(Dst& dst, const Src& src)
753 {
754 call_assignment_no_alias(dst, src, internal::assign_op<typename Dst::Scalar>());
755 }
756
757 template<typename Dst, typename Src, typename Func>
758 EIGEN_DEVICE_FUNC void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src, const Func& func)
759 {
760 Index dstRows = src.rows();
761 Index dstCols = src.cols();
762 if ((dst.rows() != dstRows) || (dst.cols() != dstCols))
763 dst.resize(dstRows, dstCols);
764
765 // TODO check whether this is the right place to perform these checks:
766 EIGEN_STATIC_ASSERT_LVALUE(Dst)
767 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(Dst, Src)
768
769 Assignment<Dst, Src, Func>::run(dst, src, func);
770 }
771 template<typename Dst, typename Src>
772 EIGEN_DEVICE_FUNC void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src)
773 {
774 call_assignment_no_alias_no_transpose(dst, src, internal::assign_op<typename Dst::Scalar>());
775 }
776
777 // forward declaration
778 template<typename Dst, typename Src> void check_for_aliasing(const Dst &dst, const Src &src);
779
780 // Generic Dense to Dense assignment
781 template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar>
782 struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Scalar>
783 {
784 EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
785 {
786 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
787
788#ifndef EIGEN_NO_DEBUG
789 internal::check_for_aliasing(dst, src);
790#endif
791
792 call_dense_assignment_loop(dst, src, func);
793 }
794 };
795
796 // Generic assignment through evalTo.
797 // TODO: not sure we have to keep that one, but it helps porting current code to new evaluator mechanism.
798 template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar>
799 struct Assignment<DstXprType, SrcXprType, Functor, EigenBase2EigenBase, Scalar>
800 {
801 EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar> &/*func*/)
802 {
803 eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
804 src.evalTo(dst);
805 }
806 };
807
808 } // namespace internal
809
810} // end namespace Eigen
811
812#endif // EIGEN_ASSIGN_EVALUATOR_H
Convenience specialization of Stride to specify only an outer stride See class Map for some examples.
Definition Stride.h:102
Pseudo expression representing a solving operation.
Definition Solve.h:63
Definition AssignEvaluator.h:539
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index row, Index col)
Assign src(row,col) to dst(row,col) through the assignment functor.
Definition AssignEvaluator.h:571
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index index)
Definition AssignEvaluator.h:577
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeffByOuterInner(Index outer, Index inner)
Definition AssignEvaluator.h:583
Definition svm.cpp:205
const unsigned int LinearAccessBit
Short version: means the expression can be seen as 1D vector.
Definition Constants.h:124
const unsigned int DirectAccessBit
Means that the underlying array of coefficients can be directly accessed as a plain strided array.
Definition Constants.h:149
const unsigned int RowMajorBit
for a matrix, this means that the storage order is row-major.
Definition Constants.h:61
Definition Constants.h:511
Definition AssignEvaluator.h:677
Definition AssignEvaluator.h:684
Definition AssignEvaluator.h:674
Definition AssignEvaluator.h:675
Definition AssignmentFunctors.h:21
Definition AssignEvaluator.h:29
Definition AssignEvaluator.h:283
Definition XprHelper.h:107
Definition DenseCoeffsBase.h:643
Definition GenericPacketMath.h:90
Definition AssignEvaluator.h:335
Definition XprHelper.h:119