// File: /workspace/github_cpp_makefile_star2_O3/DavidLBruce[P]sim3dof/Matrix/build/../../Matrix/src/Matrix.cpp
// Function: Matrix::Det()
double Matrix::Det()
{
  if (rows != cols)
  {
    throw(DIMERR());
  }

  double cofactor;
  int    col(0);
  bool   done(false);
  int    maxZeroRow(0);
  double minor(0.0);
  int    prevZeroCnt(0);
  double result(0.0);
  int    row(0);
  double sign(0.0);
  int    zeroCnt(0);

  //
  // Handle trivial cases.
  //
  if (rows == 1)
  {
    result = *pData;
    done = true;
  }

  if (!done)
  {
    if (rows == 2)
    {
      result = (*this)[0][0] * (*this)[1][1] - (*this)[0][1] * (*this)[1][0];
      done = true;
    }
  }

  if (!done)
  {
    //
    // Find the row with the most zero elements.
    //
    for (row = 0; row < rows; ++row)
    {
      zeroCnt = 0.0;
      for (col = 0; col < cols; ++col)
      {
        if (WithinTolerance((*this)[row][col],  0.0))
        {
          ++zeroCnt;
        }
      }
      if (zeroCnt == cols)
      {
        result = 0.0;
        done = true;
        break;  // exit loop for (row = 0; row < rows; ++row)
      }
      else if (zeroCnt > prevZeroCnt)
      {
        maxZeroRow = row;
        prevZeroCnt = zeroCnt;
      }
    }
    
    row = maxZeroRow;

  } // end if (!done)

  //
  // Sum the products of the selected row elements and their cofactors.
  //
  if (!done)
  {  
    for (col = 0; col < cols; ++col)
    {
      if (!WithinTolerance(pData[row*cols+col], 0.0))
      { 
        //
        // Odd powers of -1 are negative 1, even powers are positive 1.
        //
        sign = (row + col) % 2 == 0 ? 1.0 : -1.0;

        minor = Minor(row, col);
    
        cofactor = sign * pData[row*cols+col] * minor;
    
        result += cofactor;
      }
    }
  }  // end if (!done)

  return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl 0x8(%rdi), %eax
cmpl (%rdi), %eax
jne 0x14cd9
movq %rdi, %rbx
cmpl $0x1, %eax
je 0x14b6c
cmpl $0x2, %eax
jne 0x14b7e
movq %rbx, %rdi
xorl %esi, %esi
callq 0x139a6
movsd (%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x139a6
movsd -0x38(%rbp), %xmm0
mulsd 0x8(%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x139a6
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x30(%rbp)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x139a6
movsd -0x30(%rbp), %xmm1
mulsd (%rax), %xmm1
movsd -0x38(%rbp), %xmm0
subsd %xmm1, %xmm0
jmp 0x14cca
movq 0x10(%rbx), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x30(%rbp)
jmp 0x14cc5
xorpd %xmm0, %xmm0
movsd %xmm0, -0x30(%rbp)
testl %eax, %eax
jle 0x14cc5
xorl %r14d, %r14d
movapd 0x1a06(%rip), %xmm1     # 0x165a0
movsd 0x3a06(%rip), %xmm2     # 0x185a8
xorl %r12d, %r12d
xorl %esi, %esi
movl $0x0, %r13d
testl %eax, %eax
jle 0x14bf5
movl %esi, -0x38(%rbp)
xorl %r15d, %r15d
xorl %r13d, %r13d
movq %rbx, %rdi
movl %r14d, %esi
callq 0x139a6
movsd 0x39db(%rip), %xmm2     # 0x185a8
movapd 0x19cb(%rip), %xmm1     # 0x165a0
movsd (%rax,%r15,8), %xmm0
andpd %xmm1, %xmm0
ucomisd %xmm0, %xmm2
sbbl $-0x1, %r13d
incq %r15
movslq (%rbx), %rax
cmpq %rax, %r15
jl 0x14bba
movl -0x38(%rbp), %esi
cmpl %eax, %r13d
je 0x14cc5
cmpl %r12d, %r13d
cmovgl %r14d, %esi
cmovgl %r13d, %r12d
incl %r14d
cmpl 0x8(%rbx), %r14d
jl 0x14ba7
testl %eax, %eax
jle 0x14cc5
xorps %xmm0, %xmm0
cvtsi2sd %esi, %xmm0
movsd %xmm0, -0x38(%rbp)
movq 0x10(%rbx), %rcx
movl %esi, %r14d
xorpd %xmm0, %xmm0
movsd %xmm0, -0x30(%rbp)
xorl %r12d, %r12d
movl %eax, %edx
imull %esi, %edx
movslq %edx, %rdx
addq %r12, %rdx
movsd (%rcx,%rdx,8), %xmm0
andpd %xmm1, %xmm0
ucomisd %xmm0, %xmm2
jae 0x14cb9
leal (%r14,%r12), %r15d
xorps %xmm1, %xmm1
cvtsi2sd %r12d, %xmm1
movq %rbx, %rdi
movsd -0x38(%rbp), %xmm0
movl %esi, %r13d
callq 0x14d04
movl %r13d, %esi
movl (%rbx), %eax
movl %eax, %ecx
imull %r13d, %ecx
movslq %ecx, %rdx
addq %r12, %rdx
movq 0x10(%rbx), %rcx
movsd (%rcx,%rdx,8), %xmm1
testb $0x1, %r15b
je 0x14c97
xorpd 0x1379(%rip), %xmm1     # 0x16010
mulsd %xmm1, %xmm0
movsd -0x30(%rbp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, -0x30(%rbp)
movapd 0x18ef(%rip), %xmm1     # 0x165a0
movsd 0x38ef(%rip), %xmm2     # 0x185a8
incq %r12
cmpl %eax, %r12d
jl 0x14c39
movsd -0x30(%rbp), %xmm0
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x8, %edi
callq 0x30b0
leaq 0x905e(%rip), %rcx      # 0x1dd48
movq %rcx, (%rax)
leaq 0x8ffc(%rip), %rsi      # 0x1dcf0
movq 0x92e5(%rip), %rdx      # 0x1dfe0
movq %rax, %rdi
callq 0x32b0
nop