// File: /workspace/github_cpp_makefile_star2_O2/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 0x14436
movq %rdi, %rbx
cmpl $0x1, %eax
je 0x142fe
cmpl $0x2, %eax
jne 0x1430b
movq %rbx, %rdi
xorl %esi, %esi
callq 0x1324e
movsd (%rax), %xmm0
movsd %xmm0, -0x30(%rbp)
pushq $0x1
popq %r14
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1324e
movsd -0x30(%rbp), %xmm0
mulsd 0x8(%rax), %xmm0
movsd %xmm0, -0x30(%rbp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x1324e
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1324e
movsd -0x38(%rbp), %xmm1
mulsd (%rax), %xmm1
movsd -0x30(%rbp), %xmm0
subsd %xmm1, %xmm0
jmp 0x14427
movq 0x10(%rbx), %rax
movsd (%rax), %xmm2
jmp 0x14423
movl $0x0, -0x30(%rbp)
movl %eax, %ecx
xorl %r12d, %r12d
xorl %r14d, %r14d
cmpl %ecx, %r14d
jge 0x1437f
xorl %r15d, %r15d
xorl %r13d, %r13d
movslq %eax, %rcx
cmpq %rcx, %r15
jge 0x1435d
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1324e
movsd (%rax,%r15,8), %xmm0
andpd 0x125a(%rip), %xmm0     # 0x155a0
movsd 0x325a(%rip), %xmm1     # 0x175a8
ucomisd %xmm0, %xmm1
sbbl $-0x1, %r13d
incq %r15
movl (%rbx), %eax
jmp 0x14325
cmpl %eax, %r13d
je 0x14420
cmpl %r12d, %r13d
movl -0x30(%rbp), %ecx
cmoval %r14d, %ecx
movl %ecx, -0x30(%rbp)
cmovgl %r13d, %r12d
incl %r14d
movl 0x8(%rbx), %ecx
jmp 0x1431a
movl -0x30(%rbp), %r13d
cvtsi2sd %r13d, %xmm0
movsd %xmm0, -0x40(%rbp)
movl %r13d, %r14d
xorpd %xmm2, %xmm2
xorl %r12d, %r12d
cmpl %eax, %r12d
jge 0x14423
movq 0x10(%rbx), %rcx
movl %eax, %edx
imull %r13d, %edx
addl %r12d, %edx
movslq %edx, %rdx
movsd (%rcx,%rdx,8), %xmm0
andpd 0x11e3(%rip), %xmm0     # 0x155a0
movsd 0x31e3(%rip), %xmm1     # 0x175a8
ucomisd %xmm0, %xmm1
jae 0x14418
movsd %xmm2, -0x38(%rbp)
leal (%r14,%r12), %r15d
cvtsi2sd %r12d, %xmm1
movq %rbx, %rdi
movsd -0x40(%rbp), %xmm0
callq 0x1445e
movl (%rbx), %eax
movl %eax, %ecx
imull %r13d, %ecx
movslq %ecx, %rcx
addq %r12, %rcx
movq 0x10(%rbx), %rdx
movsd (%rdx,%rcx,8), %xmm1
testb $0x1, %r15b
je 0x1440b
xorpd 0xc05(%rip), %xmm1      # 0x15010
movsd -0x38(%rbp), %xmm2
mulsd %xmm1, %xmm0
addsd %xmm0, %xmm2
incq %r12
jmp 0x14397
xorps %xmm2, %xmm2
movapd %xmm2, %xmm0
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x8
popq %rdi
callq 0x30e0
leaq 0x8903(%rip), %rcx      # 0x1cd48
movq %rcx, (%rax)
leaq 0x88a1(%rip), %rsi      # 0x1ccf0
movq 0x8b8a(%rip), %rdx      # 0x1cfe0
movq %rax, %rdi
callq 0x3300