AssignEvaluator.h
Go to the documentation of this file.
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 
15 #include "./InternalHeaderCheck.h"
16 
17 namespace Eigen {
18 
19 // This implementation is based on Assign.h
20 
21 namespace internal {
22 
23 
27 // copy_using_evaluator_traits is based on assign_traits
28 
29 template <typename DstEvaluator, typename SrcEvaluator, typename AssignFunc, int MaxPacketSize = -1>
30 struct copy_using_evaluator_traits
31 {
32  typedef typename DstEvaluator::XprType Dst;
33  typedef typename Dst::Scalar DstScalar;
34 
35  enum {
36  DstFlags = DstEvaluator::Flags,
37  SrcFlags = SrcEvaluator::Flags
38  };
39 
40 public:
41  enum {
42  DstAlignment = DstEvaluator::Alignment,
43  SrcAlignment = SrcEvaluator::Alignment,
44  DstHasDirectAccess = (DstFlags & DirectAccessBit) == DirectAccessBit,
45  JointAlignment = plain_enum_min(DstAlignment, SrcAlignment)
46  };
47 
48 private:
49  enum {
50  InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime)
51  : int(DstFlags)&RowMajorBit ? int(Dst::ColsAtCompileTime)
52  : int(Dst::RowsAtCompileTime),
53  InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime)
54  : int(DstFlags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime)
55  : int(Dst::MaxRowsAtCompileTime),
56  RestrictedInnerSize = min_size_prefer_fixed(InnerSize, MaxPacketSize),
57  RestrictedLinearSize = min_size_prefer_fixed(Dst::SizeAtCompileTime, MaxPacketSize),
58  OuterStride = int(outer_stride_at_compile_time<Dst>::ret),
59  MaxSizeAtCompileTime = Dst::SizeAtCompileTime
60  };
61 
62  // TODO distinguish between linear traversal and inner-traversals
63  typedef typename find_best_packet<DstScalar,RestrictedLinearSize>::type LinearPacketType;
64  typedef typename find_best_packet<DstScalar,RestrictedInnerSize>::type InnerPacketType;
65 
66  enum {
67  LinearPacketSize = unpacket_traits<LinearPacketType>::size,
69  };
70 
71 public:
72  enum {
73  LinearRequiredAlignment = unpacket_traits<LinearPacketType>::alignment,
74  InnerRequiredAlignment = unpacket_traits<InnerPacketType>::alignment
75  };
76 
77 private:
78  enum {
79  DstIsRowMajor = DstFlags&RowMajorBit,
80  SrcIsRowMajor = SrcFlags&RowMajorBit,
81  StorageOrdersAgree = (int(DstIsRowMajor) == int(SrcIsRowMajor)),
82  MightVectorize = bool(StorageOrdersAgree)
83  && (int(DstFlags) & int(SrcFlags) & ActualPacketAccessBit)
84  && bool(functor_traits<AssignFunc>::PacketAccess),
85  MayInnerVectorize = MightVectorize
86  && int(InnerSize)!=Dynamic && int(InnerSize)%int(InnerPacketSize)==0
87  && int(OuterStride)!=Dynamic && int(OuterStride)%int(InnerPacketSize)==0
88  && (EIGEN_UNALIGNED_VECTORIZE || int(JointAlignment)>=int(InnerRequiredAlignment)),
89  MayLinearize = bool(StorageOrdersAgree) && (int(DstFlags) & int(SrcFlags) & LinearAccessBit),
90  MayLinearVectorize = bool(MightVectorize) && bool(MayLinearize) && bool(DstHasDirectAccess)
91  && (EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)) || MaxSizeAtCompileTime == Dynamic),
92  /* If the destination isn't aligned, we have to do runtime checks and we don't unroll,
93  so it's only good for large enough sizes. */
94  MaySliceVectorize = bool(MightVectorize) && bool(DstHasDirectAccess)
95  && (int(InnerMaxSize)==Dynamic || int(InnerMaxSize)>=(EIGEN_UNALIGNED_VECTORIZE?InnerPacketSize:(3*InnerPacketSize)))
96  /* slice vectorization can be slow, so we only want it if the slices are big, which is
97  indicated by InnerMaxSize rather than InnerSize, think of the case of a dynamic block
98  in a fixed-size matrix
99  However, with EIGEN_UNALIGNED_VECTORIZE and unrolling, slice vectorization is still worth it */
100  };
101 
102 public:
103  enum {
104  Traversal = int(Dst::SizeAtCompileTime) == 0 ? int(AllAtOnceTraversal) // If compile-size is zero, traversing will fail at compile-time.
105  : (int(MayLinearVectorize) && (LinearPacketSize>InnerPacketSize)) ? int(LinearVectorizedTraversal)
106  : int(MayInnerVectorize) ? int(InnerVectorizedTraversal)
107  : int(MayLinearVectorize) ? int(LinearVectorizedTraversal)
108  : int(MaySliceVectorize) ? int(SliceVectorizedTraversal)
109  : int(MayLinearize) ? int(LinearTraversal)
110  : int(DefaultTraversal),
111  Vectorized = int(Traversal) == InnerVectorizedTraversal
112  || int(Traversal) == LinearVectorizedTraversal
113  || int(Traversal) == SliceVectorizedTraversal
114  };
115 
116  typedef std::conditional_t<int(Traversal)==LinearVectorizedTraversal, LinearPacketType, InnerPacketType> PacketType;
117 
118 private:
119  enum {
120  ActualPacketSize = int(Traversal)==LinearVectorizedTraversal ? LinearPacketSize
121  : Vectorized ? InnerPacketSize
122  : 1,
123  UnrollingLimit = EIGEN_UNROLLING_LIMIT * ActualPacketSize,
124  MayUnrollCompletely = int(Dst::SizeAtCompileTime) != Dynamic
125  && int(Dst::SizeAtCompileTime) * (int(DstEvaluator::CoeffReadCost)+int(SrcEvaluator::CoeffReadCost)) <= int(UnrollingLimit),
126  MayUnrollInner = int(InnerSize) != Dynamic
127  && int(InnerSize) * (int(DstEvaluator::CoeffReadCost)+int(SrcEvaluator::CoeffReadCost)) <= int(UnrollingLimit)
128  };
129 
130 public:
131  enum {
132  Unrolling = (int(Traversal) == int(InnerVectorizedTraversal) || int(Traversal) == int(DefaultTraversal))
133  ? (
134  int(MayUnrollCompletely) ? int(CompleteUnrolling)
135  : int(MayUnrollInner) ? int(InnerUnrolling)
136  : int(NoUnrolling)
137  )
138  : int(Traversal) == int(LinearVectorizedTraversal)
139  ? ( bool(MayUnrollCompletely) && ( EIGEN_UNALIGNED_VECTORIZE || (int(DstAlignment)>=int(LinearRequiredAlignment)))
140  ? int(CompleteUnrolling)
141  : int(NoUnrolling) )
142  : int(Traversal) == int(LinearTraversal)
143  ? ( bool(MayUnrollCompletely) ? int(CompleteUnrolling)
144  : int(NoUnrolling) )
146  : int(Traversal) == int(SliceVectorizedTraversal)
147  ? ( bool(MayUnrollInner) ? int(InnerUnrolling)
148  : int(NoUnrolling) )
149 #endif
150  : int(NoUnrolling)
151  };
152 
153 #ifdef EIGEN_DEBUG_ASSIGN
154  static void debug()
155  {
156  std::cerr << "DstXpr: " << typeid(typename DstEvaluator::XprType).name() << std::endl;
157  std::cerr << "SrcXpr: " << typeid(typename SrcEvaluator::XprType).name() << std::endl;
158  std::cerr.setf(std::ios::hex, std::ios::basefield);
159  std::cerr << "DstFlags" << " = " << DstFlags << " (" << demangle_flags(DstFlags) << " )" << std::endl;
160  std::cerr << "SrcFlags" << " = " << SrcFlags << " (" << demangle_flags(SrcFlags) << " )" << std::endl;
161  std::cerr.unsetf(std::ios::hex);
162  EIGEN_DEBUG_VAR(DstAlignment)
163  EIGEN_DEBUG_VAR(SrcAlignment)
164  EIGEN_DEBUG_VAR(LinearRequiredAlignment)
165  EIGEN_DEBUG_VAR(InnerRequiredAlignment)
166  EIGEN_DEBUG_VAR(JointAlignment)
167  EIGEN_DEBUG_VAR(InnerSize)
168  EIGEN_DEBUG_VAR(InnerMaxSize)
169  EIGEN_DEBUG_VAR(LinearPacketSize)
170  EIGEN_DEBUG_VAR(InnerPacketSize)
171  EIGEN_DEBUG_VAR(ActualPacketSize)
172  EIGEN_DEBUG_VAR(StorageOrdersAgree)
173  EIGEN_DEBUG_VAR(MightVectorize)
174  EIGEN_DEBUG_VAR(MayLinearize)
175  EIGEN_DEBUG_VAR(MayInnerVectorize)
176  EIGEN_DEBUG_VAR(MayLinearVectorize)
177  EIGEN_DEBUG_VAR(MaySliceVectorize)
178  std::cerr << "Traversal" << " = " << Traversal << " (" << demangle_traversal(Traversal) << ")" << std::endl;
179  EIGEN_DEBUG_VAR(SrcEvaluator::CoeffReadCost)
180  EIGEN_DEBUG_VAR(DstEvaluator::CoeffReadCost)
181  EIGEN_DEBUG_VAR(Dst::SizeAtCompileTime)
182  EIGEN_DEBUG_VAR(UnrollingLimit)
183  EIGEN_DEBUG_VAR(MayUnrollCompletely)
184  EIGEN_DEBUG_VAR(MayUnrollInner)
185  std::cerr << "Unrolling" << " = " << Unrolling << " (" << demangle_unrolling(Unrolling) << ")" << std::endl;
186  std::cerr << std::endl;
187  }
188 #endif
189 };
190 
191 
195 
199 template<typename Kernel, int Index, int Stop>
200 struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling
201 {
202  // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
203  typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
204  typedef typename DstEvaluatorType::XprType DstXprType;
205 
206  enum {
207  outer = Index / DstXprType::InnerSizeAtCompileTime,
208  inner = Index % DstXprType::InnerSizeAtCompileTime
209  };
210 
211  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
212  {
213  kernel.assignCoeffByOuterInner(outer, inner);
214  copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Index+1, Stop>::run(kernel);
215  }
216 };
217 
218 template<typename Kernel, int Stop>
219 struct copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, Stop, Stop>
220 {
221  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel&) { }
222 };
223 
224 template<typename Kernel, int Index_, int Stop>
225 struct copy_using_evaluator_DefaultTraversal_InnerUnrolling
226 {
227  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
228  {
229  kernel.assignCoeffByOuterInner(outer, Index_);
230  copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, Index_+1, Stop>::run(kernel, outer);
231  }
232 };
233 
234 template<typename Kernel, int Stop>
235 struct copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, Stop, Stop>
236 {
237  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&, Index) { }
238 };
239 
240 
244 template<typename Kernel, int Index, int Stop>
245 struct copy_using_evaluator_LinearTraversal_CompleteUnrolling
246 {
247  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel)
248  {
249  kernel.assignCoeff(Index);
250  copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, Index+1, Stop>::run(kernel);
251  }
252 };
253 
254 template<typename Kernel, int Stop>
255 struct copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, Stop, Stop>
256 {
257  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel&) { }
258 };
259 
260 
264 template<typename Kernel, int Index, int Stop>
265 struct copy_using_evaluator_innervec_CompleteUnrolling
266 {
267  // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
268  typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
269  typedef typename DstEvaluatorType::XprType DstXprType;
270  typedef typename Kernel::PacketType PacketType;
271 
272  enum {
273  outer = Index / DstXprType::InnerSizeAtCompileTime,
274  inner = Index % DstXprType::InnerSizeAtCompileTime,
275  SrcAlignment = Kernel::AssignmentTraits::SrcAlignment,
276  DstAlignment = Kernel::AssignmentTraits::DstAlignment
277  };
278 
279  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
280  {
281  kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, inner);
282  enum { NextIndex = Index + unpacket_traits<PacketType>::size };
283  copy_using_evaluator_innervec_CompleteUnrolling<Kernel, NextIndex, Stop>::run(kernel);
284  }
285 };
286 
287 template<typename Kernel, int Stop>
288 struct copy_using_evaluator_innervec_CompleteUnrolling<Kernel, Stop, Stop>
289 {
290  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel&) { }
291 };
292 
293 template<typename Kernel, int Index_, int Stop, int SrcAlignment, int DstAlignment>
294 struct copy_using_evaluator_innervec_InnerUnrolling
295 {
296  typedef typename Kernel::PacketType PacketType;
297  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel, Index outer)
298  {
299  kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, Index_);
300  enum { NextIndex = Index_ + unpacket_traits<PacketType>::size };
301  copy_using_evaluator_innervec_InnerUnrolling<Kernel, NextIndex, Stop, SrcAlignment, DstAlignment>::run(kernel, outer);
302  }
303 };
304 
305 template<typename Kernel, int Stop, int SrcAlignment, int DstAlignment>
306 struct copy_using_evaluator_innervec_InnerUnrolling<Kernel, Stop, Stop, SrcAlignment, DstAlignment>
307 {
308  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &, Index) { }
309 };
310 
311 
315 // dense_assignment_loop is based on assign_impl
316 
317 template<typename Kernel,
318  int Traversal = Kernel::AssignmentTraits::Traversal,
319  int Unrolling = Kernel::AssignmentTraits::Unrolling>
320 struct dense_assignment_loop;
321 
322 
326 // Zero-sized assignment is a no-op.
327 template<typename Kernel, int Unrolling>
328 struct dense_assignment_loop<Kernel, AllAtOnceTraversal, Unrolling>
329 {
330  EIGEN_DEVICE_FUNC static void EIGEN_STRONG_INLINE EIGEN_CONSTEXPR run(Kernel& /*kernel*/)
331  {
332  EIGEN_STATIC_ASSERT(int(Kernel::DstEvaluatorType::XprType::SizeAtCompileTime) == 0,
333  EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT)
334  }
335 };
336 
337 
341 template<typename Kernel>
342 struct dense_assignment_loop<Kernel, DefaultTraversal, NoUnrolling>
343 {
344  EIGEN_DEVICE_FUNC static void EIGEN_STRONG_INLINE run(Kernel &kernel)
345  {
346  for(Index outer = 0; outer < kernel.outerSize(); ++outer) {
347  for(Index inner = 0; inner < kernel.innerSize(); ++inner) {
348  kernel.assignCoeffByOuterInner(outer, inner);
349  }
350  }
351  }
352 };
353 
354 template<typename Kernel>
355 struct dense_assignment_loop<Kernel, DefaultTraversal, CompleteUnrolling>
356 {
357  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
358  {
359  typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
360  copy_using_evaluator_DefaultTraversal_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
361  }
362 };
363 
364 template<typename Kernel>
365 struct dense_assignment_loop<Kernel, DefaultTraversal, InnerUnrolling>
366 {
367  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
368  {
369  typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
370 
371  const Index outerSize = kernel.outerSize();
372  for(Index outer = 0; outer < outerSize; ++outer)
373  copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime>::run(kernel, outer);
374  }
375 };
376 
377 
382 // The goal of unaligned_dense_assignment_loop is simply to factorize the handling
383 // of the non vectorizable beginning and ending parts
384 
385 template <bool IsAligned = false>
386 struct unaligned_dense_assignment_loop
387 {
388  // if IsAligned = true, then do nothing
389  template <typename Kernel>
390  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel&, Index, Index) {}
391 };
392 
393 template <>
394 struct unaligned_dense_assignment_loop<false>
395 {
396  // MSVC must not inline this functions. If it does, it fails to optimize the
397  // packet access path.
398  // FIXME check which version exhibits this issue
399 #if EIGEN_COMP_MSVC
400  template <typename Kernel>
401  static EIGEN_DONT_INLINE void run(Kernel &kernel,
402  Index start,
403  Index end)
404 #else
405  template <typename Kernel>
406  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel,
407  Index start,
408  Index end)
409 #endif
410  {
411  for (Index index = start; index < end; ++index)
412  kernel.assignCoeff(index);
413  }
414 };
415 
416 template <typename Kernel, int Index, int Stop>
417 struct copy_using_evaluator_linearvec_CompleteUnrolling {
418  // FIXME: this is not very clean, perhaps this information should be provided by the kernel?
419  typedef typename Kernel::DstEvaluatorType DstEvaluatorType;
420  typedef typename DstEvaluatorType::XprType DstXprType;
421  typedef typename Kernel::PacketType PacketType;
422 
423  enum {
424  SrcAlignment = Kernel::AssignmentTraits::SrcAlignment,
425  DstAlignment = Kernel::AssignmentTraits::DstAlignment
426  };
427 
428  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel& kernel) {
429  kernel.template assignPacket<DstAlignment, SrcAlignment, PacketType>(Index);
430  enum { NextIndex = Index + unpacket_traits<PacketType>::size };
431  copy_using_evaluator_linearvec_CompleteUnrolling<Kernel, NextIndex, Stop>::run(kernel);
432  }
433 };
434 
435 template <typename Kernel, int Stop>
436 struct copy_using_evaluator_linearvec_CompleteUnrolling<Kernel, Stop, Stop> {
437  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel&) {}
438 };
439 
440 template<typename Kernel>
441 struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, NoUnrolling>
442 {
443  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel)
444  {
445  const Index size = kernel.size();
446  typedef typename Kernel::Scalar Scalar;
447  typedef typename Kernel::PacketType PacketType;
448  enum {
449  requestedAlignment = Kernel::AssignmentTraits::LinearRequiredAlignment,
451  dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment)>=int(requestedAlignment),
452  dstAlignment = packet_traits<Scalar>::AlignedOnScalar ? int(requestedAlignment)
453  : int(Kernel::AssignmentTraits::DstAlignment),
454  srcAlignment = Kernel::AssignmentTraits::JointAlignment
455  };
456  const Index alignedStart = dstIsAligned ? 0 : internal::first_aligned<requestedAlignment>(kernel.dstDataPtr(), size);
457  const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize;
458 
459  unaligned_dense_assignment_loop<dstIsAligned!=0>::run(kernel, 0, alignedStart);
460 
461  for(Index index = alignedStart; index < alignedEnd; index += packetSize)
462  kernel.template assignPacket<dstAlignment, srcAlignment, PacketType>(index);
463 
464  unaligned_dense_assignment_loop<>::run(kernel, alignedEnd, size);
465  }
466 };
467 
468 template<typename Kernel>
469 struct dense_assignment_loop<Kernel, LinearVectorizedTraversal, CompleteUnrolling>
470 {
471  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel)
472  {
473  typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
474  typedef typename Kernel::PacketType PacketType;
475 
476  enum { size = DstXprType::SizeAtCompileTime,
478  alignedSize = (int(size)/packetSize)*packetSize };
479 
480  copy_using_evaluator_linearvec_CompleteUnrolling<Kernel, 0, alignedSize>::run(kernel);
481  copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, alignedSize, size>::run(kernel);
482  }
483 };
484 
485 
489 template<typename Kernel>
490 struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, NoUnrolling>
491 {
492  typedef typename Kernel::PacketType PacketType;
493  enum {
494  SrcAlignment = Kernel::AssignmentTraits::SrcAlignment,
495  DstAlignment = Kernel::AssignmentTraits::DstAlignment
496  };
497  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel)
498  {
499  const Index innerSize = kernel.innerSize();
500  const Index outerSize = kernel.outerSize();
501  const Index packetSize = unpacket_traits<PacketType>::size;
502  for(Index outer = 0; outer < outerSize; ++outer)
503  for(Index inner = 0; inner < innerSize; inner+=packetSize)
504  kernel.template assignPacketByOuterInner<DstAlignment, SrcAlignment, PacketType>(outer, inner);
505  }
506 };
507 
508 template<typename Kernel>
509 struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, CompleteUnrolling>
510 {
511  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
512  {
513  typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
514  copy_using_evaluator_innervec_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
515  }
516 };
517 
518 template<typename Kernel>
519 struct dense_assignment_loop<Kernel, InnerVectorizedTraversal, InnerUnrolling>
520 {
521  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(Kernel &kernel)
522  {
523  typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
524  typedef typename Kernel::AssignmentTraits Traits;
525  const Index outerSize = kernel.outerSize();
526  for(Index outer = 0; outer < outerSize; ++outer)
527  copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, DstXprType::InnerSizeAtCompileTime,
528  Traits::SrcAlignment, Traits::DstAlignment>::run(kernel, outer);
529  }
530 };
531 
532 
536 template<typename Kernel>
537 struct dense_assignment_loop<Kernel, LinearTraversal, NoUnrolling>
538 {
539  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel)
540  {
541  const Index size = kernel.size();
542  for(Index i = 0; i < size; ++i)
543  kernel.assignCoeff(i);
544  }
545 };
546 
547 template<typename Kernel>
548 struct dense_assignment_loop<Kernel, LinearTraversal, CompleteUnrolling>
549 {
550  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel)
551  {
552  typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
553  copy_using_evaluator_LinearTraversal_CompleteUnrolling<Kernel, 0, DstXprType::SizeAtCompileTime>::run(kernel);
554  }
555 };
556 
557 
561 template<typename Kernel>
562 struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, NoUnrolling>
563 {
564  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel)
565  {
566  typedef typename Kernel::Scalar Scalar;
567  typedef typename Kernel::PacketType PacketType;
568  enum {
570  requestedAlignment = int(Kernel::AssignmentTraits::InnerRequiredAlignment),
571  alignable = packet_traits<Scalar>::AlignedOnScalar || int(Kernel::AssignmentTraits::DstAlignment)>=sizeof(Scalar),
572  dstIsAligned = int(Kernel::AssignmentTraits::DstAlignment)>=int(requestedAlignment),
573  dstAlignment = alignable ? int(requestedAlignment)
574  : int(Kernel::AssignmentTraits::DstAlignment)
575  };
576  const Scalar *dst_ptr = kernel.dstDataPtr();
577  if((!bool(dstIsAligned)) && (std::uintptr_t(dst_ptr) % sizeof(Scalar))>0)
578  {
579  // the pointer is not aligned-on scalar, so alignment is not possible
580  return dense_assignment_loop<Kernel,DefaultTraversal,NoUnrolling>::run(kernel);
581  }
582  const Index packetAlignedMask = packetSize - 1;
583  const Index innerSize = kernel.innerSize();
584  const Index outerSize = kernel.outerSize();
585  const Index alignedStep = alignable ? (packetSize - kernel.outerStride() % packetSize) & packetAlignedMask : 0;
586  Index alignedStart = ((!alignable) || bool(dstIsAligned)) ? 0 : internal::first_aligned<requestedAlignment>(dst_ptr, innerSize);
587 
588  for(Index outer = 0; outer < outerSize; ++outer)
589  {
590  const Index alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
591  // do the non-vectorizable part of the assignment
592  for(Index inner = 0; inner<alignedStart ; ++inner)
593  kernel.assignCoeffByOuterInner(outer, inner);
594 
595  // do the vectorizable part of the assignment
596  for(Index inner = alignedStart; inner<alignedEnd; inner+=packetSize)
597  kernel.template assignPacketByOuterInner<dstAlignment, Unaligned, PacketType>(outer, inner);
598 
599  // do the non-vectorizable part of the assignment
600  for(Index inner = alignedEnd; inner<innerSize ; ++inner)
601  kernel.assignCoeffByOuterInner(outer, inner);
602 
603  alignedStart = numext::mini((alignedStart+alignedStep)%packetSize, innerSize);
604  }
605  }
606 };
607 
608 #if EIGEN_UNALIGNED_VECTORIZE
609 template<typename Kernel>
610 struct dense_assignment_loop<Kernel, SliceVectorizedTraversal, InnerUnrolling>
611 {
612  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void run(Kernel &kernel)
613  {
614  typedef typename Kernel::DstEvaluatorType::XprType DstXprType;
615  typedef typename Kernel::PacketType PacketType;
616 
617  enum { innerSize = DstXprType::InnerSizeAtCompileTime,
619  vectorizableSize = (int(innerSize) / int(packetSize)) * int(packetSize),
620  size = DstXprType::SizeAtCompileTime };
621 
622  for(Index outer = 0; outer < kernel.outerSize(); ++outer)
623  {
624  copy_using_evaluator_innervec_InnerUnrolling<Kernel, 0, vectorizableSize, 0, 0>::run(kernel, outer);
625  copy_using_evaluator_DefaultTraversal_InnerUnrolling<Kernel, vectorizableSize, innerSize>::run(kernel, outer);
626  }
627  }
628 };
629 #endif
630 
631 
632 
636 // This class generalize the assignment of a coefficient (or packet) from one dense evaluator
637 // to another dense writable evaluator.
638 // It is parametrized by the two evaluators, and the actual assignment functor.
639 // This abstraction level permits to keep the evaluation loops as simple and as generic as possible.
640 // One can customize the assignment using this generic dense_assignment_kernel with different
641 // functors, or by completely overloading it, by-passing a functor.
642 template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor, int Version = Specialized>
643 class generic_dense_assignment_kernel
644 {
645 protected:
646  typedef typename DstEvaluatorTypeT::XprType DstXprType;
647  typedef typename SrcEvaluatorTypeT::XprType SrcXprType;
648 public:
649 
650  typedef DstEvaluatorTypeT DstEvaluatorType;
651  typedef SrcEvaluatorTypeT SrcEvaluatorType;
652  typedef typename DstEvaluatorType::Scalar Scalar;
653  typedef copy_using_evaluator_traits<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor> AssignmentTraits;
654  typedef typename AssignmentTraits::PacketType PacketType;
655 
656 
657  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
658  generic_dense_assignment_kernel(DstEvaluatorType &dst, const SrcEvaluatorType &src, const Functor &func, DstXprType& dstExpr)
659  : m_dst(dst), m_src(src), m_functor(func), m_dstExpr(dstExpr)
660  {
661  #ifdef EIGEN_DEBUG_ASSIGN
662  AssignmentTraits::debug();
663  #endif
664  }
665 
666  EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT { return m_dstExpr.size(); }
667  EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index innerSize() const EIGEN_NOEXCEPT { return m_dstExpr.innerSize(); }
668  EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index outerSize() const EIGEN_NOEXCEPT { return m_dstExpr.outerSize(); }
669  EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return m_dstExpr.rows(); }
670  EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_dstExpr.cols(); }
671  EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index outerStride() const EIGEN_NOEXCEPT { return m_dstExpr.outerStride(); }
672 
673  EIGEN_DEVICE_FUNC DstEvaluatorType& dstEvaluator() EIGEN_NOEXCEPT { return m_dst; }
674  EIGEN_DEVICE_FUNC const SrcEvaluatorType& srcEvaluator() const EIGEN_NOEXCEPT { return m_src; }
675 
677  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index row, Index col)
678  {
679  m_functor.assignCoeff(m_dst.coeffRef(row,col), m_src.coeff(row,col));
680  }
681 
683  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeff(Index index)
684  {
685  m_functor.assignCoeff(m_dst.coeffRef(index), m_src.coeff(index));
686  }
687 
689  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignCoeffByOuterInner(Index outer, Index inner)
690  {
691  Index row = rowIndexByOuterInner(outer, inner);
692  Index col = colIndexByOuterInner(outer, inner);
693  assignCoeff(row, col);
694  }
695 
696 
697  template<int StoreMode, int LoadMode, typename Packet>
698  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index row, Index col)
699  {
700  m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(row,col), m_src.template packet<LoadMode,Packet>(row,col));
701  }
702 
703  template<int StoreMode, int LoadMode, typename Packet>
704  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacket(Index index)
705  {
706  m_functor.template assignPacket<StoreMode>(&m_dst.coeffRef(index), m_src.template packet<LoadMode,Packet>(index));
707  }
708 
709  template<int StoreMode, int LoadMode, typename Packet>
710  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void assignPacketByOuterInner(Index outer, Index inner)
711  {
712  Index row = rowIndexByOuterInner(outer, inner);
713  Index col = colIndexByOuterInner(outer, inner);
714  assignPacket<StoreMode,LoadMode,Packet>(row, col);
715  }
716 
717  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index rowIndexByOuterInner(Index outer, Index inner)
718  {
719  typedef typename DstEvaluatorType::ExpressionTraits Traits;
720  return int(Traits::RowsAtCompileTime) == 1 ? 0
721  : int(Traits::ColsAtCompileTime) == 1 ? inner
722  : int(DstEvaluatorType::Flags)&RowMajorBit ? outer
723  : inner;
724  }
725 
726  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Index colIndexByOuterInner(Index outer, Index inner)
727  {
728  typedef typename DstEvaluatorType::ExpressionTraits Traits;
729  return int(Traits::ColsAtCompileTime) == 1 ? 0
730  : int(Traits::RowsAtCompileTime) == 1 ? inner
731  : int(DstEvaluatorType::Flags)&RowMajorBit ? inner
732  : outer;
733  }
734 
735  EIGEN_DEVICE_FUNC const Scalar* dstDataPtr() const
736  {
737  return m_dstExpr.data();
738  }
739 
740 protected:
741  DstEvaluatorType& m_dst;
742  const SrcEvaluatorType& m_src;
743  const Functor &m_functor;
744  // TODO find a way to avoid the needs of the original expression
745  DstXprType& m_dstExpr;
746 };
747 
748 // Special kernel used when computing small products whose operands have dynamic dimensions. It ensures that the
749 // PacketSize used is no larger than 4, thereby increasing the chance that vectorized instructions will be used
750 // when computing the product.
751 
752 template<typename DstEvaluatorTypeT, typename SrcEvaluatorTypeT, typename Functor>
753 class restricted_packet_dense_assignment_kernel : public generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, BuiltIn>
754 {
755 protected:
756  typedef generic_dense_assignment_kernel<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, BuiltIn> Base;
757  public:
758  typedef typename Base::Scalar Scalar;
759  typedef typename Base::DstXprType DstXprType;
760  typedef copy_using_evaluator_traits<DstEvaluatorTypeT, SrcEvaluatorTypeT, Functor, 4> AssignmentTraits;
761  typedef typename AssignmentTraits::PacketType PacketType;
762 
763  EIGEN_DEVICE_FUNC restricted_packet_dense_assignment_kernel(DstEvaluatorTypeT &dst, const SrcEvaluatorTypeT &src, const Functor &func, DstXprType& dstExpr)
764  : Base(dst, src, func, dstExpr)
765  {
766  }
767  };
768 
769 
773 template<typename DstXprType,typename SrcXprType, typename Functor>
774 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
775 void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const Functor &/*func*/)
776 {
779  eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
780 }
781 
782 template<typename DstXprType,typename SrcXprType, typename T1, typename T2>
783 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
784 void resize_if_allowed(DstXprType &dst, const SrcXprType& src, const internal::assign_op<T1,T2> &/*func*/)
785 {
786  Index dstRows = src.rows();
787  Index dstCols = src.cols();
788  if(((dst.rows()!=dstRows) || (dst.cols()!=dstCols)))
789  dst.resize(dstRows, dstCols);
790  eigen_assert(dst.rows() == dstRows && dst.cols() == dstCols);
791 }
792 
793 template<typename DstXprType, typename SrcXprType, typename Functor>
794 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src, const Functor &func)
795 {
796  typedef evaluator<DstXprType> DstEvaluatorType;
797  typedef evaluator<SrcXprType> SrcEvaluatorType;
798 
799  SrcEvaluatorType srcEvaluator(src);
800 
801  // NOTE To properly handle A = (A*A.transpose())/s with A rectangular,
802  // we need to resize the destination after the source evaluator has been created.
803  resize_if_allowed(dst, src, func);
804 
805  DstEvaluatorType dstEvaluator(dst);
806 
807  typedef generic_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Functor> Kernel;
808  Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
809 
810  dense_assignment_loop<Kernel>::run(kernel);
811 }
812 
813 // Specialization for filling the destination with a constant value.
814 #ifndef EIGEN_GPU_COMPILE_PHASE
815 template<typename DstXprType>
816 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<typename DstXprType::Scalar>, DstXprType>& src, const internal::assign_op<typename DstXprType::Scalar,typename DstXprType::Scalar>& func)
817 {
818  resize_if_allowed(dst, src, func);
819  std::fill_n(dst.data(), dst.size(), src.functor()());
820 }
821 #endif
822 
823 template<typename DstXprType, typename SrcXprType>
824 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void call_dense_assignment_loop(DstXprType& dst, const SrcXprType& src)
825 {
826  call_dense_assignment_loop(dst, src, internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar>());
827 }
828 
829 
833 // Based on the respective shapes of the destination and source,
834 // the class AssignmentKind determine the kind of assignment mechanism.
835 // AssignmentKind must define a Kind typedef.
836 template<typename DstShape, typename SrcShape> struct AssignmentKind;
837 
838 // Assignment kind defined in this file:
839 struct Dense2Dense {};
840 struct EigenBase2EigenBase {};
841 
842 template<typename,typename> struct AssignmentKind { typedef EigenBase2EigenBase Kind; };
843 template<> struct AssignmentKind<DenseShape,DenseShape> { typedef Dense2Dense Kind; };
844 
845 // This is the main assignment class
846 template< typename DstXprType, typename SrcXprType, typename Functor,
847  typename Kind = typename AssignmentKind< typename evaluator_traits<DstXprType>::Shape , typename evaluator_traits<SrcXprType>::Shape >::Kind,
848  typename EnableIf = void>
849 struct Assignment;
850 
851 
852 // The only purpose of this call_assignment() function is to deal with noalias() / "assume-aliasing" and automatic transposition.
853 // Indeed, I (Gael) think that this concept of "assume-aliasing" was a mistake, and it makes thing quite complicated.
854 // So this intermediate function removes everything related to "assume-aliasing" such that Assignment
855 // does not has to bother about these annoying details.
856 
857 template<typename Dst, typename Src>
858 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
859 void call_assignment(Dst& dst, const Src& src)
860 {
861  call_assignment(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
862 }
863 template<typename Dst, typename Src>
864 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
865 void call_assignment(const Dst& dst, const Src& src)
866 {
867  call_assignment(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
868 }
869 
870 // Deal with "assume-aliasing"
871 template<typename Dst, typename Src, typename Func>
872 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
873 void call_assignment(Dst& dst, const Src& src, const Func& func, std::enable_if_t< evaluator_assume_aliasing<Src>::value, void*> = 0)
874 {
875  typename plain_matrix_type<Src>::type tmp(src);
876  call_assignment_no_alias(dst, tmp, func);
877 }
878 
879 template<typename Dst, typename Src, typename Func>
880 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
881 void call_assignment(Dst& dst, const Src& src, const Func& func, std::enable_if_t<!evaluator_assume_aliasing<Src>::value, void*> = 0)
882 {
883  call_assignment_no_alias(dst, src, func);
884 }
885 
886 // by-pass "assume-aliasing"
887 // When there is no aliasing, we require that 'dst' has been properly resized
888 template<typename Dst, template <typename> class StorageBase, typename Src, typename Func>
889 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
890 void call_assignment(NoAlias<Dst,StorageBase>& dst, const Src& src, const Func& func)
891 {
892  call_assignment_no_alias(dst.expression(), src, func);
893 }
894 
895 
896 template<typename Dst, typename Src, typename Func>
897 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
898 void call_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
899 {
900  enum {
901  NeedToTranspose = ( (int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1)
902  || (int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1)
903  ) && int(Dst::SizeAtCompileTime) != 1
904  };
905 
906  typedef std::conditional_t<NeedToTranspose, Transpose<Dst>, Dst> ActualDstTypeCleaned;
907  typedef std::conditional_t<NeedToTranspose, Transpose<Dst>, Dst&> ActualDstType;
908  ActualDstType actualDst(dst);
909 
910  // TODO check whether this is the right place to perform these checks:
912  EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned,Src)
913  EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename ActualDstTypeCleaned::Scalar,typename Src::Scalar);
914 
915  Assignment<ActualDstTypeCleaned,Src,Func>::run(actualDst, src, func);
916 }
917 
918 template<typename Dst, typename Src, typename Func>
919 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
920 void call_restricted_packet_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
921 {
922  typedef evaluator<Dst> DstEvaluatorType;
923  typedef evaluator<Src> SrcEvaluatorType;
924  typedef restricted_packet_dense_assignment_kernel<DstEvaluatorType,SrcEvaluatorType,Func> Kernel;
925 
927  EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename Dst::Scalar,typename Src::Scalar);
928 
929  SrcEvaluatorType srcEvaluator(src);
930  resize_if_allowed(dst, src, func);
931 
932  DstEvaluatorType dstEvaluator(dst);
933  Kernel kernel(dstEvaluator, srcEvaluator, func, dst.const_cast_derived());
934 
935  dense_assignment_loop<Kernel>::run(kernel);
936 }
937 
938 template<typename Dst, typename Src>
939 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
940 void call_assignment_no_alias(Dst& dst, const Src& src)
941 {
942  call_assignment_no_alias(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
943 }
944 
945 template<typename Dst, typename Src, typename Func>
946 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
947 void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src, const Func& func)
948 {
949  // TODO check whether this is the right place to perform these checks:
952  EIGEN_CHECK_BINARY_COMPATIBILIY(Func,typename Dst::Scalar,typename Src::Scalar);
953 
954  Assignment<Dst,Src,Func>::run(dst, src, func);
955 }
956 template<typename Dst, typename Src>
957 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR
958 void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src)
959 {
960  call_assignment_no_alias_no_transpose(dst, src, internal::assign_op<typename Dst::Scalar,typename Src::Scalar>());
961 }
962 
963 // forward declaration
964 template<typename Dst, typename Src> EIGEN_DEVICE_FUNC void check_for_aliasing(const Dst &dst, const Src &src);
965 
966 // Generic Dense to Dense assignment
967 // Note that the last template argument "Weak" is needed to make it possible to perform
968 // both partial specialization+SFINAE without ambiguous specialization
969 template< typename DstXprType, typename SrcXprType, typename Functor, typename Weak>
970 struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Weak>
971 {
973  static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
974  {
975 #ifndef EIGEN_NO_DEBUG
977 #endif
978 
979  call_dense_assignment_loop(dst, src, func);
980  }
981 };
982 
983 // Generic assignment through evalTo.
984 // TODO: not sure we have to keep that one, but it helps porting current code to new evaluator mechanism.
985 // Note that the last template argument "Weak" is needed to make it possible to perform
986 // both partial specialization+SFINAE without ambiguous specialization
987 template< typename DstXprType, typename SrcXprType, typename Functor, typename Weak>
988 struct Assignment<DstXprType, SrcXprType, Functor, EigenBase2EigenBase, Weak>
989 {
991  static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &/*func*/)
992  {
993  Index dstRows = src.rows();
994  Index dstCols = src.cols();
995  if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
996  dst.resize(dstRows, dstCols);
997 
998  eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
999  src.evalTo(dst);
1000  }
1001 
1002  // NOTE The following two functions are templated to avoid their instantiation if not needed
1003  // This is needed because some expressions supports evalTo only and/or have 'void' as scalar type.
1004  template<typename SrcScalarType>
1006  static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<typename DstXprType::Scalar,SrcScalarType> &/*func*/)
1007  {
1008  Index dstRows = src.rows();
1009  Index dstCols = src.cols();
1010  if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
1011  dst.resize(dstRows, dstCols);
1012 
1013  eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
1014  src.addTo(dst);
1015  }
1016 
1017  template<typename SrcScalarType>
1019  static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<typename DstXprType::Scalar,SrcScalarType> &/*func*/)
1020  {
1021  Index dstRows = src.rows();
1022  Index dstCols = src.cols();
1023  if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
1024  dst.resize(dstRows, dstCols);
1025 
1026  eigen_assert(dst.rows() == src.rows() && dst.cols() == src.cols());
1027  src.subTo(dst);
1028  }
1029 };
1030 
1031 } // namespace internal
1032 
1033 } // end namespace Eigen
1034 
1035 #endif // EIGEN_ASSIGN_EVALUATOR_H
RowXpr row(Index i)
This is the const version of row(). *‍/.
ColXpr col(Index i)
This is the const version of col().
#define EIGEN_UNALIGNED_VECTORIZE
if((m *x).isApprox(y))
#define EIGEN_NOEXCEPT
Definition: Macros.h:1260
#define EIGEN_DEBUG_VAR(x)
Definition: Macros.h:806
#define EIGEN_CONSTEXPR
Definition: Macros.h:747
#define EIGEN_DEVICE_FUNC
Definition: Macros.h:883
#define EIGEN_DONT_INLINE
Definition: Macros.h:844
#define EIGEN_ONLY_USED_FOR_DEBUG(x)
Definition: Macros.h:914
#define eigen_assert(x)
Definition: Macros.h:902
#define EIGEN_UNROLLING_LIMIT
Definition: Settings.h:24
#define EIGEN_STATIC_ASSERT_LVALUE(Derived)
Definition: StaticAssert.h:96
#define EIGEN_STATIC_ASSERT(X, MSG)
Definition: StaticAssert.h:26
#define EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0, TYPE1)
Definition: StaticAssert.h:86
#define EIGEN_CHECK_BINARY_COMPATIBILIY(BINOP, LHS, RHS)
Definition: XprHelper.h:900
Generic expression of a matrix where all coefficients are defined by a functor.
Pseudo expression providing an operator = assuming no aliasing.
Definition: NoAlias.h:34
ExpressionType & expression() const
Definition: NoAlias.h:66
static const lastp1_t end
const unsigned int ActualPacketAccessBit
Definition: Constants.h:107
const unsigned int LinearAccessBit
Definition: Constants.h:132
const unsigned int DirectAccessBit
Definition: Constants.h:157
const unsigned int RowMajorBit
Definition: Constants.h:68
constexpr int plain_enum_min(A a, B b)
Definition: Meta.h:516
EIGEN_CONSTEXPR void call_assignment_no_alias_no_transpose(Dst &dst, const Src &src, const Func &func)
void check_for_aliasing(const Dst &dst, const Src &src)
Definition: Transpose.h:454
void resize_if_allowed(DstXprType &dst, const SrcXprType &src, const Functor &)
void call_restricted_packet_assignment_no_alias(Dst &dst, const Src &src, const Func &func)
EIGEN_CONSTEXPR void call_dense_assignment_loop(DstXprType &dst, const SrcXprType &src, const Functor &func)
constexpr int min_size_prefer_fixed(A a, B b)
Definition: Meta.h:553
void call_assignment(Dst &dst, const Src &src)
EIGEN_CONSTEXPR void call_assignment_no_alias(Dst &dst, const Src &src, const Func &func)
EIGEN_ALWAYS_INLINE T mini(const T &x, const T &y)
: InteropHeaders
Definition: Core:139
@ InnerVectorizedTraversal
Definition: Constants.h:284
@ LinearVectorizedTraversal
Definition: Constants.h:287
@ DefaultTraversal
Definition: Constants.h:279
@ SliceVectorizedTraversal
Definition: Constants.h:290
@ LinearTraversal
Definition: Constants.h:281
@ AllAtOnceTraversal
Definition: Constants.h:294
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
@ InnerUnrolling
Definition: Constants.h:303
@ CompleteUnrolling
Definition: Constants.h:306
@ NoUnrolling
Definition: Constants.h:301
const int Dynamic
Definition: Constants.h:24