// File: Kingsford-Group[P]ghost2/include/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h
// Function: Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, -1, -1, 0, -1, -1>>::compute(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, int)
SelfAdjointEigenSolver<MatrixType>& SelfAdjointEigenSolver<MatrixType>
::compute(const MatrixType& matrix, int options)
{
  using std::abs;
  eigen_assert(matrix.cols() == matrix.rows());
  eigen_assert((options&~(EigVecMask|GenEigMask))==0
          && (options&EigVecMask)!=EigVecMask
          && "invalid option parameter");
  bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors;
  Index n = matrix.cols();
  m_eivalues.resize(n,1);

  if(n==1)
  {
    m_eivalues.coeffRef(0,0) = numext::real(matrix.coeff(0,0));
    if(computeEigenvectors)
      m_eivec.setOnes(n,n);
    m_info = Success;
    m_isInitialized = true;
    m_eigenvectorsOk = computeEigenvectors;
    return *this;
  }

  // declare some aliases
  RealVectorType& diag = m_eivalues;
  MatrixType& mat = m_eivec;

  // map the matrix coefficients to [-1:1] to avoid over- and underflow.
  mat = matrix.template triangularView<Lower>();
  RealScalar scale = mat.cwiseAbs().maxCoeff();
  if(scale==RealScalar(0)) scale = RealScalar(1);
  mat.template triangularView<Lower>() /= scale;
  m_subdiag.resize(n-1);
  internal::tridiagonalization_inplace(mat, diag, m_subdiag, computeEigenvectors);
  
  Index end = n-1;
  Index start = 0;
  Index iter = 0; // total number of iterations

  while (end>0)
  {
    for (Index i = start; i<end; ++i)
      if (internal::isMuchSmallerThan(abs(m_subdiag[i]),(abs(diag[i])+abs(diag[i+1]))))
        m_subdiag[i] = 0;

    // find the largest unreduced block
    while (end>0 && m_subdiag[end-1]==0)
    {
      end--;
    }
    if (end<=0)
      break;

    // if we spent too many iterations, we give up
    iter++;
    if(iter > m_maxIterations * n) break;

    start = end - 1;
    while (start>0 && m_subdiag[start-1]!=0)
      start--;

    internal::tridiagonal_qr_step<MatrixType::Flags&RowMajorBit ? RowMajor : ColMajor>(diag.data(), m_subdiag.data(), start, end, computeEigenvectors ? m_eivec.data() : (Scalar*)0, n);
  }

  if (iter <= m_maxIterations * n)
    m_info = Success;
  else
    m_info = NoConvergence;

  // Sort eigenvalues and corresponding vectors.
  // TODO make the sort optional ?
  // TODO use a better sort algorithm !!
  if (m_info == Success)
  {
    for (Index i = 0; i < n-1; ++i)
    {
      Index k;
      m_eivalues.segment(i,n-i).minCoeff(&k);
      if (k > 0)
      {
        std::swap(m_eivalues[i], m_eivalues[k+i]);
        if(computeEigenvectors)
          m_eivec.col(i).swap(m_eivec.col(k+i));
      }
    }
  }
  
  // scale back the eigen values
  m_eivalues *= scale;

  m_isInitialized = true;
  m_eigenvectorsOk = computeEigenvectors;
  return *this;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x128(%rbp)
movq -0x18(%rbp), %rdi
callq 0x286d0
movq %rax, -0x120(%rbp)
movq -0x18(%rbp), %rdi
callq 0x24690
movq %rax, %rcx
movq -0x120(%rbp), %rax
cmpq %rcx, %rax
jne 0x6830b
jmp 0x6832a
leaq 0x60db4(%rip), %rdi     # 0xc90c6
leaq 0x60dcc(%rip), %rsi     # 0xc90e5
movl $0x184, %edx            # imm = 0x184
leaq 0x60df7(%rip), %rcx     # 0xc911c
callq 0x104a0
movl -0x1c(%rbp), %ecx
andl $0xfffff83f, %ecx       # imm = 0xFFFFF83F
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x129(%rbp)
jne 0x68363
movl -0x1c(%rbp), %ecx
andl $0xc0, %ecx
xorl %eax, %eax
cmpl $0xc0, %ecx
movb %al, -0x129(%rbp)
je 0x68363
movb $0x1, %al
movb %al, -0x129(%rbp)
jmp 0x68363
movb -0x129(%rbp), %al
testb $0x1, %al
jne 0x6836f
jmp 0x68371
jmp 0x68390
leaq 0x60e6e(%rip), %rdi     # 0xc91e6
leaq 0x60d66(%rip), %rsi     # 0xc90e5
movl $0x187, %edx            # imm = 0x187
leaq 0x60d91(%rip), %rcx     # 0xc911c
callq 0x104a0
movl -0x1c(%rbp), %eax
andl $0x80, %eax
cmpl $0x80, %eax
sete %al
andb $0x1, %al
movb %al, -0x1d(%rbp)
movq -0x18(%rbp), %rdi
callq 0x286d0
movq -0x128(%rbp), %rdi
movq %rax, -0x28(%rbp)
addq $0x18, %rdi
movq -0x28(%rbp), %rsi
movl $0x1, %edx
callq 0x4abe0
cmpq $0x1, -0x28(%rbp)
jne 0x68457
movq -0x18(%rbp), %rdi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x4db60
movq %rax, %rdi
callq 0x4c2a0
movq -0x128(%rbp), %rdi
movsd %xmm0, -0x138(%rbp)
addq $0x18, %rdi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x522d0
movsd -0x138(%rbp), %xmm0
movsd %xmm0, (%rax)
testb $0x1, -0x1d(%rbp)
je 0x68433
movq -0x128(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x28(%rbp), %rdx
callq 0x68930
movq -0x128(%rbp), %rax
movl $0x0, 0x38(%rax)
movb $0x1, 0x3c(%rax)
movb -0x1d(%rbp), %cl
andb $0x1, %cl
movb %cl, 0x3d(%rax)
movq %rax, -0x8(%rbp)
jmp 0x68923
movq -0x128(%rbp), %rax
movq %rax, %rcx
addq $0x18, %rcx
movq %rcx, -0x30(%rbp)
movq %rax, -0x38(%rbp)
movq -0x18(%rbp), %rdi
callq 0x68980
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x689b0
movq -0x38(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x689e0
leaq -0x58(%rbp), %rdi
callq 0x68a30
movsd %xmm0, -0x48(%rbp)
movsd -0x48(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x684bf
jp 0x684bf
movsd 0x53bb6(%rip), %xmm0    # 0xbc070
movsd %xmm0, -0x48(%rbp)
movq -0x38(%rbp), %rdi
callq 0x68a60
movq %rax, -0x60(%rbp)
leaq -0x60(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x68a90
movq -0x128(%rbp), %rdi
addq $0x28, %rdi
movq -0x28(%rbp), %rsi
subq $0x1, %rsi
callq 0x4d1e0
movq -0x128(%rbp), %rdx
movq -0x38(%rbp), %rdi
movq -0x30(%rbp), %rsi
addq $0x28, %rdx
movb -0x1d(%rbp), %al
andb $0x1, %al
movzbl %al, %ecx
callq 0x68ad0
movq -0x28(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
movq $0x0, -0x78(%rbp)
cmpq $0x0, -0x68(%rbp)
jle 0x6878f
movq -0x70(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
cmpq -0x68(%rbp), %rax
jge 0x6860e
movq -0x128(%rbp), %rdi
addq $0x28, %rdi
movq -0x80(%rbp), %rsi
callq 0x24bc0
movsd (%rax), %xmm0
callq 0x4dd00
movsd %xmm0, -0x88(%rbp)
movq -0x30(%rbp), %rdi
movq -0x80(%rbp), %rsi
callq 0x24bc0
movsd (%rax), %xmm0
callq 0x4dd00
movsd %xmm0, -0x140(%rbp)
movq -0x30(%rbp), %rdi
movq -0x80(%rbp), %rsi
addq $0x1, %rsi
callq 0x24bc0
movsd (%rax), %xmm0
callq 0x4dd00
movaps %xmm0, %xmm1
movsd -0x140(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x90(%rbp)
callq 0x68be0
leaq -0x88(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x68bb0
testb $0x1, %al
jne 0x685e0
jmp 0x685fb
movq -0x128(%rbp), %rdi
addq $0x28, %rdi
movq -0x80(%rbp), %rsi
callq 0x24bc0
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
jmp 0x685fd
movq -0x80(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
jmp 0x68540
jmp 0x68610
xorl %eax, %eax
cmpq $0x0, -0x68(%rbp)
movb %al, -0x141(%rbp)
jle 0x68650
movq -0x128(%rbp), %rdi
addq $0x28, %rdi
movq -0x68(%rbp), %rsi
subq $0x1, %rsi
callq 0x24bc0
movsd (%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
sete %al
setnp %cl
andb %cl, %al
movb %al, -0x141(%rbp)
movb -0x141(%rbp), %al
testb $0x1, %al
jne 0x6865c
jmp 0x6866a
movq -0x68(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x68(%rbp)
jmp 0x68610
cmpq $0x0, -0x68(%rbp)
jg 0x68676
jmp 0x6878f
movq -0x78(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
imulq $0x1e, -0x28(%rbp), %rcx
cmpq %rcx, %rax
jle 0x68695
jmp 0x6878f
movq -0x68(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x70(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x70(%rbp)
movb %al, -0x142(%rbp)
jle 0x686e1
movq -0x128(%rbp), %rdi
addq $0x28, %rdi
movq -0x70(%rbp), %rsi
subq $0x1, %rsi
callq 0x24bc0
movsd (%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
setne %al
setp %cl
orb %cl, %al
movb %al, -0x142(%rbp)
movb -0x142(%rbp), %al
testb $0x1, %al
jne 0x686ed
jmp 0x686fb
movq -0x70(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x70(%rbp)
jmp 0x686a1
movq -0x30(%rbp), %rdi
callq 0x5a090
movq -0x128(%rbp), %rdi
movq %rax, -0x168(%rbp)
addq $0x28, %rdi
callq 0x5a090
movq %rax, -0x160(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x158(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x150(%rbp)
testb $0x1, -0x1d(%rbp)
je 0x68753
movq -0x128(%rbp), %rdi
callq 0x61ec0
movq %rax, -0x170(%rbp)
jmp 0x6875e
xorl %eax, %eax
movq %rax, -0x170(%rbp)
jmp 0x6875e
movq -0x150(%rbp), %rcx
movq -0x158(%rbp), %rdx
movq -0x160(%rbp), %rsi
movq -0x168(%rbp), %rdi
movq -0x170(%rbp), %r8
movq -0x28(%rbp), %r9
callq 0x22c20
jmp 0x6852d
movq -0x78(%rbp), %rax
imulq $0x1e, -0x28(%rbp), %rcx
cmpq %rcx, %rax
jg 0x687ad
movq -0x128(%rbp), %rax
movl $0x0, 0x38(%rax)
jmp 0x687bb
movq -0x128(%rbp), %rax
movl $0x2, 0x38(%rax)
movq -0x128(%rbp), %rax
cmpl $0x0, 0x38(%rax)
jne 0x688f7
movq $0x0, -0x98(%rbp)
movq -0x98(%rbp), %rax
movq -0x28(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jge 0x688f5
movq -0x128(%rbp), %rsi
addq $0x18, %rsi
movq -0x98(%rbp), %rdx
movq -0x28(%rbp), %rcx
subq -0x98(%rbp), %rcx
leaq -0xc8(%rbp), %rdi
callq 0x68bf0
leaq -0xc8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x68c40
cmpq $0x0, -0xa0(%rbp)
jle 0x688dc
movq -0x128(%rbp), %rdi
addq $0x18, %rdi
movq -0x98(%rbp), %rsi
callq 0x24bc0
movq -0x128(%rbp), %rdi
movq %rax, -0x178(%rbp)
addq $0x18, %rdi
movq -0xa0(%rbp), %rsi
addq -0x98(%rbp), %rsi
callq 0x24bc0
movq -0x178(%rbp), %rdi
movq %rax, %rsi
callq 0x4df50
testb $0x1, -0x1d(%rbp)
je 0x688da
movq -0x128(%rbp), %rsi
movq -0x98(%rbp), %rdx
leaq -0xf0(%rbp), %rdi
callq 0x4de50
movq -0x128(%rbp), %rsi
movq -0xa0(%rbp), %rdx
addq -0x98(%rbp), %rdx
leaq -0x118(%rbp), %rdi
callq 0x4de50
leaq -0xf0(%rbp), %rdi
leaq -0x118(%rbp), %rsi
xorl %edx, %edx
callq 0x68c80
jmp 0x688dc
jmp 0x688de
movq -0x98(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x98(%rbp)
jmp 0x687d7
jmp 0x688f7
movq -0x128(%rbp), %rdi
addq $0x18, %rdi
leaq -0x48(%rbp), %rsi
callq 0x68cd0
movq -0x128(%rbp), %rax
movb $0x1, 0x3c(%rax)
movb -0x1d(%rbp), %cl
andb $0x1, %cl
movb %cl, 0x3d(%rax)
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq