// File: logicx24[P]RayTracer/./algebra3.h
// 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.)
	ALGEBRA_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 0x7e80
movq -0xe8(%rbp), %rdi
callq 0x6a00
movl $0x0, -0x98(%rbp)
cmpl $0x4, -0x98(%rbp)
jge 0xab95
movl -0x98(%rbp), %eax
movl %eax, -0x9c(%rbp)
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
cmpl $0x4, -0x94(%rbp)
jge 0xa95f
leaq -0x90(%rbp), %rax
movslq -0x94(%rbp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movslq -0x98(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movaps 0x1a749(%rip), %xmm1    # 0x25050
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 0x1a71d(%rip), %xmm2    # 0x25050
pand %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xa949
movl -0x94(%rbp), %eax
movl %eax, -0x9c(%rbp)
jmp 0xa94b
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0xa8d2
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 0xabb0
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 0xabb0
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 0xaa04
jp 0xaa04
leaq 0x1aa59(%rip), %rdi     # 0x25445
leaq 0x1a9ea(%rip), %rsi     # 0x253dd
movl $0x47d, %edx            # imm = 0x47D
leaq 0x1aa4c(%rip), %rcx     # 0x2544b
callq 0x3170
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 0xabf0
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 0xabf0
movl $0x0, -0x94(%rbp)
cmpl $0x4, -0x94(%rbp)
jge 0xab7f
movl -0x94(%rbp), %eax
cmpl -0x98(%rbp), %eax
je 0xab69
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 0xac50
movq -0xe8(%rbp), %rdi
movslq -0x94(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
leaq -0xc0(%rbp), %rsi
callq 0xac90
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 0xac50
leaq -0x90(%rbp), %rdi
movslq -0x94(%rbp), %rax
shlq $0x5, %rax
addq %rax, %rdi
leaq -0xe0(%rbp), %rsi
callq 0xac90
jmp 0xab6b
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0xaa84
jmp 0xab81
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x98(%rbp)
jmp 0xa8aa
movq -0xf0(%rbp), %rax
addq $0xf0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nop