// File: j-faria[P]kima/eigen/Eigen/src/Core/GeneralProduct.h
// Function: void Eigen::internal::gemv_dense_selector<2, 0, true>::run<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, -1, false>, Eigen::Transpose<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> const>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, 1, false>>(Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, -1, false> const&, Eigen::Transpose<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> const> const&, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, 1, false>&, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, -1, 1, false>::Scalar const&)
static inline void run(const Lhs &lhs, const Rhs &rhs, Dest& dest, const typename Dest::Scalar& alpha)
  {
    typedef typename Lhs::Scalar   LhsScalar;
    typedef typename Rhs::Scalar   RhsScalar;
    typedef typename Dest::Scalar  ResScalar;
    typedef typename Dest::RealScalar  RealScalar;
    
    typedef internal::blas_traits<Lhs> LhsBlasTraits;
    typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhsType;
    typedef internal::blas_traits<Rhs> RhsBlasTraits;
    typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
  
    typedef Map<Matrix<ResScalar,Dynamic,1>, EIGEN_PLAIN_ENUM_MIN(AlignedMax,internal::packet_traits<ResScalar>::size)> MappedDest;

    ActualLhsType actualLhs = LhsBlasTraits::extract(lhs);
    ActualRhsType actualRhs = RhsBlasTraits::extract(rhs);

    ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(lhs)
                                  * RhsBlasTraits::extractScalarFactor(rhs);

    // make sure Dest is a compile-time vector type (bug 1166)
    typedef typename conditional<Dest::IsVectorAtCompileTime, Dest, typename Dest::ColXpr>::type ActualDest;

    enum {
      // FIXME find a way to allow an inner stride on the result if packet_traits<Scalar>::size==1
      // on, the other hand it is good for the cache to pack the vector anyways...
      EvalToDestAtCompileTime = (ActualDest::InnerStrideAtCompileTime==1),
      ComplexByReal = (NumTraits<LhsScalar>::IsComplex) && (!NumTraits<RhsScalar>::IsComplex),
      MightCannotUseDest = ((!EvalToDestAtCompileTime) || ComplexByReal) && (ActualDest::MaxSizeAtCompileTime!=0)
    };

    typedef const_blas_data_mapper<LhsScalar,Index,ColMajor> LhsMapper;
    typedef const_blas_data_mapper<RhsScalar,Index,RowMajor> RhsMapper;
    RhsScalar compatibleAlpha = get_factor<ResScalar,RhsScalar>::run(actualAlpha);

    if(!MightCannotUseDest)
    {
      // shortcut if we are sure to be able to use dest directly,
      // this ease the compiler to generate cleaner and more optimzized code for most common cases
      general_matrix_vector_product
          <Index,LhsScalar,LhsMapper,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsMapper,RhsBlasTraits::NeedToConjugate>::run(
          actualLhs.rows(), actualLhs.cols(),
          LhsMapper(actualLhs.data(), actualLhs.outerStride()),
          RhsMapper(actualRhs.data(), actualRhs.innerStride()),
          dest.data(), 1,
          compatibleAlpha);
    }
    else
    {
      gemv_static_vector_if<ResScalar,ActualDest::SizeAtCompileTime,ActualDest::MaxSizeAtCompileTime,MightCannotUseDest> static_dest;

      const bool alphaIsCompatible = (!ComplexByReal) || (numext::imag(actualAlpha)==RealScalar(0));
      const bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible;

      ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(),
                                                    evalToDest ? dest.data() : static_dest.data());

      if(!evalToDest)
      {
        #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN
        Index size = dest.size();
        EIGEN_DENSE_STORAGE_CTOR_PLUGIN
        #endif
        if(!alphaIsCompatible)
        {
          MappedDest(actualDestPtr, dest.size()).setZero();
          compatibleAlpha = RhsScalar(1);
        }
        else
          MappedDest(actualDestPtr, dest.size()) = dest;
      }

      general_matrix_vector_product
          <Index,LhsScalar,LhsMapper,ColMajor,LhsBlasTraits::NeedToConjugate,RhsScalar,RhsMapper,RhsBlasTraits::NeedToConjugate>::run(
          actualLhs.rows(), actualLhs.cols(),
          LhsMapper(actualLhs.data(), actualLhs.outerStride()),
          RhsMapper(actualRhs.data(), actualRhs.innerStride()),
          actualDestPtr, 1,
          compatibleAlpha);

      if (!evalToDest)
      {
        if(!alphaIsCompatible)
          dest.matrix() += actualAlpha * MappedDest(actualDestPtr, dest.size());
        else
          dest = MappedDest(actualDestPtr, dest.size());
      }
    }
  }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x78(%rbp)
movq %rsi, -0x80(%rbp)
movq %rdx, -0x88(%rbp)
movq %rcx, -0x90(%rbp)
movq -0x78(%rbp), %rdi
callq 0x398c0
movq %rax, -0x98(%rbp)
movq -0x80(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
callq 0x398d0
movq -0x90(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x128(%rbp)
movq -0x78(%rbp), %rdi
callq 0x39920
movaps %xmm0, %xmm1
movsd -0x128(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x120(%rbp)
movq -0x80(%rbp), %rdi
callq 0x39940
movaps %xmm0, %xmm1
movsd -0x120(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0xd8(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x39970
movsd %xmm0, -0xe0(%rbp)
movq -0x98(%rbp), %rdi
callq 0x395a0
movq %rax, -0x118(%rbp)
movq -0x98(%rbp), %rdi
callq 0x39210
movq %rax, -0x110(%rbp)
movq -0x98(%rbp), %rdi
callq 0x3b8e0
movq %rax, -0x108(%rbp)
movq -0x98(%rbp), %rdi
callq 0x3b900
movq -0x108(%rbp), %rcx
leaq -0xf0(%rbp), %rdx
movq %rdx, -0x60(%rbp)
movq %rcx, -0x68(%rbp)
movq %rax, -0x70(%rbp)
movq -0x60(%rbp), %rdx
movq -0x68(%rbp), %rcx
movq -0x70(%rbp), %rax
movq %rdx, -0x28(%rbp)
movq %rcx, -0x30(%rbp)
movq %rax, -0x38(%rbp)
movq $0x1, -0x40(%rbp)
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, (%rax)
movq -0x38(%rbp), %rcx
movq %rcx, 0x8(%rax)
cmpq $0x1, -0x40(%rbp)
je 0x397e0
leaq 0x8147b(%rip), %rdi     # 0xbac43
leaq 0x8147c(%rip), %rsi     # 0xbac4b
movl $0xd1, %edx
leaq 0x81495(%rip), %rcx     # 0xbac70
callq 0x6340
leaq -0xd0(%rbp), %rdi
callq 0x3b920
movq %rax, -0x130(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0x3b950
movq -0x130(%rbp), %rcx
leaq -0x100(%rbp), %rdx
movq %rdx, -0x48(%rbp)
movq %rcx, -0x50(%rbp)
movq %rax, -0x58(%rbp)
movq -0x48(%rbp), %rdx
movq -0x50(%rbp), %rcx
movq -0x58(%rbp), %rax
movq %rdx, -0x8(%rbp)
movq %rcx, -0x10(%rbp)
movq %rax, -0x18(%rbp)
movq $0x1, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq -0x10(%rbp), %rcx
movq %rcx, (%rax)
movq -0x18(%rbp), %rcx
movq %rcx, 0x8(%rax)
cmpq $0x1, -0x20(%rbp)
je 0x39872
leaq 0x813e9(%rip), %rdi     # 0xbac43
leaq 0x813ea(%rip), %rsi     # 0xbac4b
movl $0xd1, %edx
leaq 0x814bb(%rip), %rcx     # 0xbad28
callq 0x6340
movq -0x88(%rbp), %rdi
callq 0x3b980
movq -0x118(%rbp), %rdi
movq -0x110(%rbp), %rsi
movq %rax, %r8
movsd -0xe0(%rbp), %xmm0
leaq -0xf0(%rbp), %rdx
leaq -0x100(%rbp), %rcx
movl $0x1, %r9d
callq 0x39990
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
nopl (%rax)