// File: srajangarg[P]raytracer/src/core/Algebra3.hpp
// Function: Mat4::inverse() const
inline Mat4 Mat4::inverse() const    // Gauss-Jordan elimination with partial pivoting
{
  Mat4 a(*this),          // As a evolves from original mat into identity
       b(identity3D());   // b evolves from identity into inverse(a)
  int i, j, i1;

  // Loop over cols of a from left to right, eliminating above and below diag
  for (j=0; j<4; j++)   // Find largest pivot in column j among rows j..3
  {
    i1 = j;         // Row with largest pivot candidate
    for (i=j+1; i<4; i++)
      if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
        i1 = i;

    // Swap rows i1 and j in a and b to put pivot on diagonal
    swap(a.v[i1], a.v[j]);
    swap(b.v[i1], b.v[j]);

    // Scale row j to have a unit diagonal
    if (a.v[j].n[j]==0.)
      ALG3_ERROR("Mat4::inverse: singular matrix; can't invert\n");

    b.v[j] /= a.v[j].n[j];
    a.v[j] /= a.v[j].n[j];

    // Eliminate off-diagonal elems in col j of a, doing identical ops to b
    for (i=0; i<4; i++)
      if (i!=j)
      {
        b.v[i] -= a.v[i].n[j]*b.v[j];
        a.v[i] -= a.v[i].n[j]*a.v[j];
      }
  }

  return b;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0xe8(%rbp)
movq %rdi, %rax
movq %rax, -0xf0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x3eb50
movq -0xe8(%rbp), %rdi
callq 0x9f60
movl $0x0, -0x98(%rbp)
cmpl $0x4, -0x98(%rbp)
jge 0x3e185
movl -0x98(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
cmpl $0x4, -0x94(%rbp)
jge 0x3df4f
leaq -0x90(%rbp), %rax
movslq -0x94(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movaps 0x9c19(%rip), %xmm1     # 0x47b10
pand %xmm1, %xmm0
leaq -0x90(%rbp), %rax
movslq -0x9c(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movaps 0x9bed(%rip), %xmm2     # 0x47b10
pand %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x3df39
movl -0x94(%rbp), %eax
movl %eax, -0x9c(%rbp)
jmp 0x3df3b
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x3dec2
leaq -0x90(%rbp), %rdi
movslq -0x9c(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
leaq -0x90(%rbp), %rsi
movslq -0x98(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rsi
callq 0x3ebf0
movq -0xe8(%rbp), %rsi
movslq -0x9c(%rbp), %rax
shlq $0x5, %rax
movq %rsi, %rdi
addq %rax, %rdi
movslq -0x98(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rsi
callq 0x3ebf0
leaq -0x90(%rbp), %rax
movslq -0x98(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x3dff4
jp 0x3dff4
leaq 0xad59(%rip), %rdi      # 0x48d35
leaq 0x90d0(%rip), %rsi      # 0x470b3
movl $0x4fc, %edx            # imm = 0x4FC
leaq 0xad4c(%rip), %rcx      # 0x48d3b
callq 0x52c0
movq -0xe8(%rbp), %rdi
leaq -0x90(%rbp), %rax
movslq -0x98(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movslq -0x98(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x3ec30
leaq -0x90(%rbp), %rax
movslq -0x98(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
leaq -0x90(%rbp), %rdi
movslq -0x98(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x3ec30
movl $0x0, -0x94(%rbp)
cmpl $0x4, -0x94(%rbp)
jge 0x3e16f
movl -0x94(%rbp), %eax
cmpl -0x98(%rbp), %eax
je 0x3e159
movq -0xe8(%rbp), %rsi
leaq -0x90(%rbp), %rax
movslq -0x94(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movslq -0x98(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rsi
leaq -0xc0(%rbp), %rdi
callq 0x3ec90
movq -0xe8(%rbp), %rdi
movslq -0x94(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
leaq -0xc0(%rbp), %rsi
callq 0x3ecd0
leaq -0x90(%rbp), %rax
movslq -0x94(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
leaq -0x90(%rbp), %rsi
movslq -0x98(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rsi
leaq -0xe0(%rbp), %rdi
callq 0x3ec90
leaq -0x90(%rbp), %rdi
movslq -0x94(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
leaq -0xe0(%rbp), %rsi
callq 0x3ecd0
jmp 0x3e15b
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x3e074
jmp 0x3e171
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x98(%rbp)
jmp 0x3de9a
movq -0xf0(%rbp), %rax
addq $0xf0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop