// File: Kingsford-Group[P]ghost2/include/Eigen/src/Core/products/GeneralBlockPanelKernel.h
// Function: Eigen::internal::gemm_pack_lhs<double, long, 4, 2, 0, false, false>::operator()(double*, double const*, long, long, long, long, long)
EIGEN_DONT_INLINE void gemm_pack_lhs<Scalar, Index, Pack1, Pack2, StorageOrder, Conjugate, PanelMode>
  ::operator()(Scalar* blockA, const Scalar* EIGEN_RESTRICT _lhs, Index lhsStride, Index depth, Index rows, Index stride, Index offset)
{
  typedef typename packet_traits<Scalar>::type Packet;
  enum { PacketSize = packet_traits<Scalar>::size };

  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( (StorageOrder==RowMajor) || ((Pack1%PacketSize)==0 && Pack1<=4*PacketSize) );
  conj_if<NumTraits<Scalar>::IsComplex && Conjugate> cj;
  const_blas_data_mapper<Scalar, Index, StorageOrder> lhs(_lhs,lhsStride);
  Index count = 0;
  Index peeled_mc = (rows/Pack1)*Pack1;
  for(Index i=0; i<peeled_mc; i+=Pack1)
  {
    if(PanelMode) count += Pack1 * offset;

    if(StorageOrder==ColMajor)
    {
      for(Index k=0; k<depth; k++)
      {
        Packet A, B, C, D;
        if(Pack1>=1*PacketSize) A = ploadu<Packet>(&lhs(i+0*PacketSize, k));
        if(Pack1>=2*PacketSize) B = ploadu<Packet>(&lhs(i+1*PacketSize, k));
        if(Pack1>=3*PacketSize) C = ploadu<Packet>(&lhs(i+2*PacketSize, k));
        if(Pack1>=4*PacketSize) D = ploadu<Packet>(&lhs(i+3*PacketSize, k));
        if(Pack1>=1*PacketSize) { pstore(blockA+count, cj.pconj(A)); count+=PacketSize; }
        if(Pack1>=2*PacketSize) { pstore(blockA+count, cj.pconj(B)); count+=PacketSize; }
        if(Pack1>=3*PacketSize) { pstore(blockA+count, cj.pconj(C)); count+=PacketSize; }
        if(Pack1>=4*PacketSize) { pstore(blockA+count, cj.pconj(D)); count+=PacketSize; }
      }
    }
    else
    {
      for(Index k=0; k<depth; k++)
      {
        // TODO add a vectorized transpose here
        Index w=0;
        for(; w<Pack1-3; w+=4)
        {
          Scalar a(cj(lhs(i+w+0, k))),
                  b(cj(lhs(i+w+1, k))),
                  c(cj(lhs(i+w+2, k))),
                  d(cj(lhs(i+w+3, k)));
          blockA[count++] = a;
          blockA[count++] = b;
          blockA[count++] = c;
          blockA[count++] = d;
        }
        if(Pack1%4)
          for(;w<Pack1;++w)
            blockA[count++] = cj(lhs(i+w, k));
      }
    }
    if(PanelMode) count += Pack1 * (stride-offset-depth);
  }
  if(rows-peeled_mc>=Pack2)
  {
    if(PanelMode) count += Pack2*offset;
    for(Index k=0; k<depth; k++)
      for(Index w=0; w<Pack2; w++)
        blockA[count++] = cj(lhs(peeled_mc+w, k));
    if(PanelMode) count += Pack2 * (stride-offset-depth);
    peeled_mc += Pack2;
  }
  for(Index i=peeled_mc; 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 $0xf0, %rsp
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
leaq 0x10(%rbp), %rdi
callq 0x56c70
leaq 0x18(%rbp), %rdi
callq 0x56c70
cmpq $0x0, 0x10(%rbp)
jne 0xa8ef3
movb $0x1, %al
cmpq $0x0, 0x18(%rbp)
movb %al, -0xd1(%rbp)
je 0xa8efd
xorl %eax, %eax
movb %al, -0xd1(%rbp)
jmp 0xa8efd
movb -0xd1(%rbp), %al
testb $0x1, %al
jne 0xa8f09
jmp 0xa8f0b
jmp 0xa8f2a
leaq 0x2cced(%rip), %rdi     # 0xd5bff
leaq 0x2cd41(%rip), %rsi     # 0xd5c5a
movl $0x46d, %edx            # imm = 0x46D
leaq 0x2ce50(%rip), %rcx     # 0xd5d75
callq 0x104a0
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
leaq -0x48(%rbp), %rdi
callq 0xa8ab0
movq $0x0, -0x50(%rbp)
movq -0x30(%rbp), %rax
movl $0x4, %ecx
cqto
idivq %rcx
shlq $0x2, %rax
movq %rax, -0x58(%rbp)
movq $0x0, -0x60(%rbp)
movq -0x60(%rbp), %rax
cmpq -0x58(%rbp), %rax
jge 0xa906f
movq $0x0, -0x68(%rbp)
movq -0x68(%rbp), %rax
cmpq -0x28(%rbp), %rax
jge 0xa905c
movq -0x60(%rbp), %rsi
addq $0x0, %rsi
movq -0x68(%rbp), %rdx
leaq -0x48(%rbp), %rdi
callq 0xa8e70
movq %rax, %rdi
callq 0x517b0
movapd %xmm0, -0x80(%rbp)
movq -0x60(%rbp), %rsi
addq $0x2, %rsi
movq -0x68(%rbp), %rdx
leaq -0x48(%rbp), %rdi
callq 0xa8e70
movq %rax, %rdi
callq 0x517b0
movapd %xmm0, -0x90(%rbp)
movq -0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0xe8(%rbp)
leaq -0x31(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0xab0f0
movq -0xe8(%rbp), %rdi
movq %rax, %rsi
callq 0x4bbd0
movq -0x50(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0xe0(%rbp)
leaq -0x31(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0xab0f0
movq -0xe0(%rbp), %rdi
movq %rax, %rsi
callq 0x4bbd0
movq -0x50(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x50(%rbp)
movq -0x68(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x68(%rbp)
jmp 0xa8f77
jmp 0xa905e
movq -0x60(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x60(%rbp)
jmp 0xa8f61
movq -0x30(%rbp), %rax
subq -0x58(%rbp), %rax
cmpq $0x2, %rax
jl 0xa912e
movq $0x0, -0xb8(%rbp)
movq -0xb8(%rbp), %rax
cmpq -0x28(%rbp), %rax
jge 0xa9122
movq $0x0, -0xc0(%rbp)
cmpq $0x2, -0xc0(%rbp)
jge 0xa9109
movq -0x58(%rbp), %rsi
addq -0xc0(%rbp), %rsi
movq -0xb8(%rbp), %rdx
leaq -0x48(%rbp), %rdi
callq 0xa8e70
movq %rax, %rsi
leaq -0x31(%rbp), %rdi
callq 0xab0d0
movsd (%rax), %xmm0
movq -0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x50(%rbp)
movsd %xmm0, (%rax,%rcx,8)
movq -0xc0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xc0(%rbp)
jmp 0xa90a8
jmp 0xa910b
movq -0xb8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb8(%rbp)
jmp 0xa908c
movq -0x58(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
cmpq -0x30(%rbp), %rax
jge 0xa91ce
movq $0x0, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
cmpq -0x28(%rbp), %rax
jge 0xa91b5
movq -0xc8(%rbp), %rsi
movq -0xd0(%rbp), %rdx
leaq -0x48(%rbp), %rdi
callq 0xa8e70
movq %rax, %rsi
leaq -0x31(%rbp), %rdi
callq 0xab0d0
movsd (%rax), %xmm0
movq -0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x50(%rbp)
movsd %xmm0, (%rax,%rcx,8)
movq -0xd0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xd0(%rbp)
jmp 0xa9155
jmp 0xa91b7
movq -0xc8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xc8(%rbp)
jmp 0xa9139
addq $0xf0, %rsp
popq %rbp
retq
nopw (%rax,%rax)