LCOV - code coverage report
Current view: top level - Core - AssignEvaluator.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 124 132 93.9 %
Date: 1980-01-01 00:00:00 Functions: 1014 1061 95.6 %
Branches: 0 0 -

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

Generated by: LCOV version 1.0