// File: j-faria[P]kima/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h
// Function: Eigen::internal::gemm_pack_lhs<double, long, Eigen::internal::blas_data_mapper<double, long, 0, 0, 1>, 4, 2, double vector[2], 0, false, true>::operator()(double*, Eigen::internal::blas_data_mapper<double, long, 0, 0, 1> const&, long, long, long, long)
EIGEN_DONT_INLINE void gemm_pack_lhs<Scalar, Index, DataMapper, Pack1, Pack2, Packet, ColMajor, Conjugate, PanelMode>
  ::operator()(Scalar* blockA, const DataMapper& lhs, Index depth, Index rows, Index stride, Index offset)
{
  typedef typename unpacket_traits<Packet>::half HalfPacket;
  typedef typename unpacket_traits<typename unpacket_traits<Packet>::half>::half QuarterPacket;
  enum { PacketSize = unpacket_traits<Packet>::size,
         HalfPacketSize = unpacket_traits<HalfPacket>::size,
         QuarterPacketSize = unpacket_traits<QuarterPacket>::size,
         HasHalf = (int)HalfPacketSize < (int)PacketSize,
         HasQuarter = (int)QuarterPacketSize < (int)HalfPacketSize};

  EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK LHS");
  EIGEN_UNUSED_VARIABLE(stride);
  EIGEN_UNUSED_VARIABLE(offset);
  eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride));
  eigen_assert( ((Pack1%PacketSize)==0 && Pack1<=4*PacketSize) || (Pack1<=4) );
  conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
  Index count = 0;

  const Index peeled_mc3 = Pack1>=3*PacketSize ? (rows/(3*PacketSize))*(3*PacketSize) : 0;
  const Index peeled_mc2 = Pack1>=2*PacketSize ? peeled_mc3+((rows-peeled_mc3)/(2*PacketSize))*(2*PacketSize) : 0;
  const Index peeled_mc1 = Pack1>=1*PacketSize ? peeled_mc2+((rows-peeled_mc2)/(1*PacketSize))*(1*PacketSize) : 0;
  const Index peeled_mc_half = Pack1>=HalfPacketSize ? peeled_mc1+((rows-peeled_mc1)/(HalfPacketSize))*(HalfPacketSize) : 0;
  const Index peeled_mc_quarter = Pack1>=QuarterPacketSize ? (rows/(QuarterPacketSize))*(QuarterPacketSize) : 0;
  const Index last_lhs_progress = rows > peeled_mc_quarter ? (rows - peeled_mc_quarter) & ~1 : 0;
  const Index peeled_mc0 = Pack2>=PacketSize ? peeled_mc_quarter
                         : Pack2>1 && last_lhs_progress ? (rows/last_lhs_progress)*last_lhs_progress : 0;

  Index i=0;

  // Pack 3 packets
  if(Pack1>=3*PacketSize)
  {
    for(; i<peeled_mc3; i+=3*PacketSize)
    {
      if(PanelMode) count += (3*PacketSize) * offset;

      for(Index k=0; k<depth; k++)
      {
        Packet A, B, C;
        A = lhs.template loadPacket<Packet>(i+0*PacketSize, k);
        B = lhs.template loadPacket<Packet>(i+1*PacketSize, k);
        C = lhs.template loadPacket<Packet>(i+2*PacketSize, k);
        pstore(blockA+count, cj.pconj(A)); count+=PacketSize;
        pstore(blockA+count, cj.pconj(B)); count+=PacketSize;
        pstore(blockA+count, cj.pconj(C)); count+=PacketSize;
      }
      if(PanelMode) count += (3*PacketSize) * (stride-offset-depth);
    }
  }
  // Pack 2 packets
  if(Pack1>=2*PacketSize)
  {
    for(; i<peeled_mc2; i+=2*PacketSize)
    {
      if(PanelMode) count += (2*PacketSize) * offset;

      for(Index k=0; k<depth; k++)
      {
        Packet A, B;
        A = lhs.template loadPacket<Packet>(i+0*PacketSize, k);
        B = lhs.template loadPacket<Packet>(i+1*PacketSize, k);
        pstore(blockA+count, cj.pconj(A)); count+=PacketSize;
        pstore(blockA+count, cj.pconj(B)); count+=PacketSize;
      }
      if(PanelMode) count += (2*PacketSize) * (stride-offset-depth);
    }
  }
  // Pack 1 packets
  if(Pack1>=1*PacketSize)
  {
    for(; i<peeled_mc1; i+=1*PacketSize)
    {
      if(PanelMode) count += (1*PacketSize) * offset;

      for(Index k=0; k<depth; k++)
      {
        Packet A;
        A = lhs.template loadPacket<Packet>(i+0*PacketSize, k);
        pstore(blockA+count, cj.pconj(A));
        count+=PacketSize;
      }
      if(PanelMode) count += (1*PacketSize) * (stride-offset-depth);
    }
  }
  // Pack half packets
  if(HasHalf && Pack1>=HalfPacketSize)
  {
    for(; i<peeled_mc_half; i+=HalfPacketSize)
    {
      if(PanelMode) count += (HalfPacketSize) * offset;

      for(Index k=0; k<depth; k++)
      {
        HalfPacket A;
        A = lhs.template loadPacket<HalfPacket>(i+0*(HalfPacketSize), k);
        pstoreu(blockA+count, cj.pconj(A));
        count+=HalfPacketSize;
      }
      if(PanelMode) count += (HalfPacketSize) * (stride-offset-depth);
    }
  }
  // Pack quarter packets
  if(HasQuarter && Pack1>=QuarterPacketSize)
  {
    for(; i<peeled_mc_quarter; i+=QuarterPacketSize)
    {
      if(PanelMode) count += (QuarterPacketSize) * offset;

      for(Index k=0; k<depth; k++)
      {
        QuarterPacket A;
        A = lhs.template loadPacket<QuarterPacket>(i+0*(QuarterPacketSize), k);
        pstoreu(blockA+count, cj.pconj(A));
        count+=QuarterPacketSize;
      }
      if(PanelMode) count += (QuarterPacketSize) * (stride-offset-depth);
    }
  }
  // Pack2 may be *smaller* than PacketSize—that happens for
  // products like real * complex, where we have to go half the
  // progress on the lhs in order to duplicate those operands to
  // address both real & imaginary parts on the rhs. This portion will
  // pack those half ones until they match the number expected on the
  // last peeling loop at this point (for the rhs).
  if(Pack2<PacketSize && Pack2>1)
  {
    for(; i<peeled_mc0; i+=last_lhs_progress)
    {
      if(PanelMode) count += last_lhs_progress * offset;

      for(Index k=0; k<depth; k++)
        for(Index w=0; w<last_lhs_progress; w++)
          blockA[count++] = cj(lhs(i+w, k));

      if(PanelMode) count += last_lhs_progress * (stride-offset-depth);
    }
  }
  // Pack scalars
  for(; i<rows; i++)
  {
    if(PanelMode) count += offset;
    for(Index k=0; k<depth; k++)
      blockA[count++] = cj(lhs(i, k));
    if(PanelMode) count += (stride-offset-depth);
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1d0, %rsp            # imm = 0x1D0
movq 0x10(%rbp), %rax
movq %rdi, -0xc8(%rbp)
movq %rsi, -0xd0(%rbp)
movq %rdx, -0xd8(%rbp)
movq %rcx, -0xe0(%rbp)
movq %r8, -0xe8(%rbp)
movq %r9, -0xf0(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x2fc00
leaq 0x10(%rbp), %rdi
callq 0x2fc00
movq -0xf0(%rbp), %rcx
xorl %eax, %eax
cmpq -0xe0(%rbp), %rcx
movb %al, -0x199(%rbp)
jl 0x461da
movq 0x10(%rbp), %rax
cmpq -0xf0(%rbp), %rax
setle %al
movb %al, -0x199(%rbp)
movb -0x199(%rbp), %al
testb $0x1, %al
jne 0x461e6
jmp 0x461e8
jmp 0x46207
leaq 0x76571(%rip), %rdi     # 0xbc760
leaq 0x765c5(%rip), %rsi     # 0xbc7bb
movl $0x8d2, %edx            # imm = 0x8D2
leaq 0x769ed(%rip), %rcx     # 0xbcbef
callq 0x6340
movq $0x0, -0x100(%rbp)
movq $0x0, -0x108(%rbp)
movq -0xe8(%rbp), %rax
subq $0x0, %rax
movl $0x4, %ecx
cqto
idivq %rcx
shlq $0x2, %rax
addq $0x0, %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rax
movq %rax, -0x1b0(%rbp)
movq -0xe8(%rbp), %rax
subq -0x110(%rbp), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x1b0(%rbp), %rax
shlq %rcx
addq %rcx, %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rax
movq %rax, -0x1a8(%rbp)
movq -0xe8(%rbp), %rax
subq -0x118(%rbp), %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, %rcx
movq -0x1a8(%rbp), %rax
shlq %rcx
addq %rcx, %rax
movq %rax, -0x120(%rbp)
movq -0xe8(%rbp), %rax
movl $0x2, %ecx
cqto
idivq %rcx
shlq %rax
movq %rax, -0x128(%rbp)
movq -0xe8(%rbp), %rax
cmpq -0x128(%rbp), %rax
jle 0x46301
movq -0xe8(%rbp), %rax
subq -0x128(%rbp), %rax
andq $-0x2, %rax
movq %rax, -0x1b8(%rbp)
jmp 0x4630c
xorl %eax, %eax
movq %rax, -0x1b8(%rbp)
jmp 0x4630c
movq -0x1b8(%rbp), %rax
movq %rax, -0x130(%rbp)
movq -0x128(%rbp), %rax
movq %rax, -0x138(%rbp)
movq $0x0, -0x140(%rbp)
movq -0x140(%rbp), %rax
cmpq -0x110(%rbp), %rax
jge 0x4654e
movq 0x10(%rbp), %rax
shlq $0x2, %rax
addq -0x100(%rbp), %rax
movq %rax, -0x100(%rbp)
movq $0x0, -0x148(%rbp)
movq -0x148(%rbp), %rax
cmpq -0xe0(%rbp), %rax
jge 0x46513
movq -0xd8(%rbp), %rdx
movq -0x140(%rbp), %rcx
addq $0x0, %rcx
movq -0x148(%rbp), %rax
movq %rdx, -0x28(%rbp)
movq %rcx, -0x30(%rbp)
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
movq -0x38(%rbp), %rax
movq %rdx, -0x8(%rbp)
movq %rcx, -0x10(%rbp)
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rsi
movq (%rsi), %rax
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rdx
imulq 0x8(%rsi), %rdx
addq %rdx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rdi
callq 0x35b10
movapd %xmm0, -0x160(%rbp)
movq -0xd8(%rbp), %rdx
movq -0x140(%rbp), %rcx
addq $0x2, %rcx
movq -0x148(%rbp), %rax
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, -0x40(%rbp)
movq %rcx, -0x48(%rbp)
movq %rax, -0x50(%rbp)
movq -0x40(%rbp), %rsi
movq (%rsi), %rax
movq -0x48(%rbp), %rcx
movq -0x50(%rbp), %rdx
imulq 0x8(%rsi), %rdx
addq %rdx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rdi
callq 0x35b10
movapd %xmm0, -0x170(%rbp)
movq -0xd0(%rbp), %rax
movq -0x100(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x1c8(%rbp)
leaq -0xf1(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x48620
movq -0x1c8(%rbp), %rdi
movq %rax, %rsi
callq 0x306e0
movq -0x100(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x100(%rbp)
movq -0xd0(%rbp), %rax
movq -0x100(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x1c0(%rbp)
leaq -0xf1(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x48620
movq -0x1c0(%rbp), %rdi
movq %rax, %rsi
callq 0x306e0
movq -0x100(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x100(%rbp)
movq -0x148(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x148(%rbp)
jmp 0x46368
movq -0xf0(%rbp), %rax
subq 0x10(%rbp), %rax
subq -0xe0(%rbp), %rax
shlq $0x2, %rax
addq -0x100(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x140(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x140(%rbp)
jmp 0x46333
jmp 0x46550
movq -0x140(%rbp), %rax
cmpq -0x118(%rbp), %rax
jge 0x466c7
movq 0x10(%rbp), %rax
shlq %rax
addq -0x100(%rbp), %rax
movq %rax, -0x100(%rbp)
movq $0x0, -0x178(%rbp)
movq -0x178(%rbp), %rax
cmpq -0xe0(%rbp), %rax
jge 0x4668d
movq -0xd8(%rbp), %rdx
movq -0x140(%rbp), %rcx
addq $0x0, %rcx
movq -0x178(%rbp), %rax
movq %rdx, -0x98(%rbp)
movq %rcx, -0xa0(%rbp)
movq %rax, -0xa8(%rbp)
movq -0x98(%rbp), %rdx
movq -0xa0(%rbp), %rcx
movq -0xa8(%rbp), %rax
movq %rdx, -0x78(%rbp)
movq %rcx, -0x80(%rbp)
movq %rax, -0x88(%rbp)
movq -0x78(%rbp), %rsi
movq (%rsi), %rax
movq -0x80(%rbp), %rcx
movq -0x88(%rbp), %rdx
imulq 0x8(%rsi), %rdx
addq %rdx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rdi
callq 0x35b10
movapd %xmm0, -0x190(%rbp)
movq -0xd0(%rbp), %rax
movq -0x100(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x1d0(%rbp)
leaq -0xf1(%rbp), %rdi
leaq -0x190(%rbp), %rsi
callq 0x48620
movq -0x1d0(%rbp), %rdi
movq %rax, %rsi
callq 0x306e0
movq -0x100(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x100(%rbp)
movq -0x178(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x178(%rbp)
jmp 0x46584
movq -0xf0(%rbp), %rax
subq 0x10(%rbp), %rax
subq -0xe0(%rbp), %rax
shlq %rax
addq -0x100(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x140(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x140(%rbp)
jmp 0x46550
jmp 0x466c9
movq -0x140(%rbp), %rax
cmpq -0xe8(%rbp), %rax
jge 0x467de
movq 0x10(%rbp), %rax
addq -0x100(%rbp), %rax
movq %rax, -0x100(%rbp)
movq $0x0, -0x198(%rbp)
movq -0x198(%rbp), %rax
cmpq -0xe0(%rbp), %rax
jge 0x467a7
movq -0xd8(%rbp), %rdx
movq -0x140(%rbp), %rcx
movq -0x198(%rbp), %rax
movq %rdx, -0xb0(%rbp)
movq %rcx, -0xb8(%rbp)
movq %rax, -0xc0(%rbp)
movq -0xb0(%rbp), %rdx
movq (%rdx), %rsi
movq -0xb8(%rbp), %rax
movq -0xc0(%rbp), %rcx
imulq 0x8(%rdx), %rcx
addq %rcx, %rax
shlq $0x3, %rax
addq %rax, %rsi
leaq -0xf1(%rbp), %rdi
callq 0x46140
movsd (%rax), %xmm0
movq -0xd0(%rbp), %rax
movq -0x100(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x100(%rbp)
movsd %xmm0, (%rax,%rcx,8)
movq -0x198(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x198(%rbp)
jmp 0x466fa
movq -0xf0(%rbp), %rax
subq 0x10(%rbp), %rax
subq -0xe0(%rbp), %rax
addq -0x100(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x140(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x140(%rbp)
jmp 0x466c9
addq $0x1d0, %rsp            # imm = 0x1D0
popq %rbp
retq
nopw (%rax,%rax)