// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R4Matrix.cpp
// Function: gaps::R4Matrix::Invert()
void R4Matrix::
Invert(void)
{
    // Copy matrix into local variables
    RNScalar Ma, Mb, Mc, Md, Me, Mf, Mg, Mh, Mi, Mj, Mk, Ml, Mm, Mn, Mo, Mp;
    Ma = m[0][0]; Mb = m[0][1]; Mc = m[0][2]; Md = m[0][3];
    Me = m[1][0]; Mf = m[1][1]; Mg = m[1][2]; Mh = m[1][3];
    Mi = m[2][0]; Mj = m[2][1]; Mk = m[2][2]; Ml = m[2][3];
    Mm = m[3][0]; Mn = m[3][1]; Mo = m[3][2]; Mp = m[3][3];

    // Compute sub-determinants and determinant
    RNScalar a1 = R4MatrixDet3(Mf, Mg, Mh, Mj, Mk, Ml, Mn, Mo, Mp);
    RNScalar a2 = R4MatrixDet3(Me, Mg, Mh, Mi, Mk, Ml, Mm, Mo, Mp);  
    RNScalar a3 = R4MatrixDet3(Me, Mf, Mh, Mi, Mj, Ml, Mm, Mn, Mp);
    RNScalar a4 = R4MatrixDet3(Me, Mf, Mg, Mi, Mj, Mk, Mm, Mn, Mo);
    RNScalar det = Ma*a1 - Mb*a2 + Mc*a3 - Md*a4;
    if (RNIsZero(det, 1E-8)) {
        RNWarning("Unable to invert matrix with zero determinant");
        return;
    }

    // Compute inverse matrix
    m[0][0] = (a1)/det;
    m[1][0] = -(a2)/det;
    m[2][0] = (a3)/det;
    m[3][0] = -(a4)/det;

    m[0][1] = -(R4MatrixDet3(Mb, Mc, Md, Mj, Mk, Ml, Mn, Mo, Mp))/det;
    m[1][1] = (R4MatrixDet3(Ma, Mc, Md, Mi, Mk, Ml, Mm, Mo, Mp))/det;
    m[2][1] = -(R4MatrixDet3(Ma, Mb, Md, Mi, Mj, Ml, Mm, Mn, Mp))/det;
    m[3][1] = (R4MatrixDet3(Ma, Mb, Mc, Mi, Mj, Mk, Mm, Mn, Mo))/det;

    m[0][2] = (R4MatrixDet3(Mb, Mc, Md, Mf, Mg, Mh, Mn, Mo, Mp))/det;
    m[1][2] = -(R4MatrixDet3(Ma, Mc, Md, Me, Mg, Mh, Mm, Mo, Mp))/det;
    m[2][2] = (R4MatrixDet3(Ma, Mb, Md, Me, Mf, Mh, Mm, Mn, Mp))/det;
    m[3][2] = -(R4MatrixDet3(Ma, Mb, Mc, Me, Mf, Mg, Mm, Mn, Mo))/det;

    m[0][3] = -(R4MatrixDet3(Mb, Mc, Md, Mf, Mg, Mh, Mj, Mk, Ml))/det;
    m[1][3] = (R4MatrixDet3(Ma, Mc, Md, Me, Mg, Mh, Mi, Mk, Ml))/det;
    m[2][3] = -(R4MatrixDet3(Ma, Mb, Md, Me, Mf, Mh, Mi, Mj, Ml))/det;
    m[3][3] = (R4MatrixDet3(Ma, Mb, Mc, Me, Mf, Mg, Mi, Mj, Mk))/det;
}

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq %rax, 0x10(%rsp)
movsd (%rax), %xmm0
movsd %xmm0, 0xb8(%rsp)
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0xb0(%rsp)
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0xa8(%rsp)
movsd 0x18(%rax), %xmm0
movsd %xmm0, 0xa0(%rsp)
movsd 0x20(%rax), %xmm0
movsd %xmm0, 0x98(%rsp)
movsd 0x28(%rax), %xmm0
movsd %xmm0, 0x90(%rsp)
movsd 0x30(%rax), %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x38(%rax), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x40(%rax), %xmm0
movsd %xmm0, 0x78(%rsp)
movsd 0x48(%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x50(%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movsd 0x58(%rax), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x60(%rax), %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x68(%rax), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x70(%rax), %xmm0
movsd %xmm0, 0x48(%rsp)
movsd 0x78(%rax), %xmm0
movsd %xmm0, 0x40(%rsp)
movsd 0x90(%rsp), %xmm0
movsd 0x88(%rsp), %xmm1
movsd 0x80(%rsp), %xmm2
movsd 0x70(%rsp), %xmm3
movsd 0x68(%rsp), %xmm4
movsd 0x60(%rsp), %xmm5
movsd 0x50(%rsp), %xmm6
movsd 0x48(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movsd %xmm0, 0x38(%rsp)
movsd 0x98(%rsp), %xmm0
movsd 0x88(%rsp), %xmm1
movsd 0x80(%rsp), %xmm2
movsd 0x78(%rsp), %xmm3
movsd 0x68(%rsp), %xmm4
movsd 0x60(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x48(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movsd %xmm0, 0x30(%rsp)
movsd 0x98(%rsp), %xmm0
movsd 0x90(%rsp), %xmm1
movsd 0x80(%rsp), %xmm2
movsd 0x78(%rsp), %xmm3
movsd 0x70(%rsp), %xmm4
movsd 0x60(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x50(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movsd %xmm0, 0x28(%rsp)
movsd 0x98(%rsp), %xmm0
movsd 0x90(%rsp), %xmm1
movsd 0x88(%rsp), %xmm2
movsd 0x78(%rsp), %xmm3
movsd 0x70(%rsp), %xmm4
movsd 0x68(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x50(%rsp), %xmm7
movsd 0x48(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movsd %xmm0, 0x20(%rsp)
movsd 0xb8(%rsp), %xmm0
movsd 0x38(%rsp), %xmm2
movsd 0xb0(%rsp), %xmm1
mulsd 0x30(%rsp), %xmm1
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd 0xa8(%rsp), %xmm1
movsd 0x28(%rsp), %xmm2
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd 0xa0(%rsp), %xmm0
movsd 0x20(%rsp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x18(%rsp), %xmm0
movsd 0xe12fb(%rip), %xmm1    # 0x133dd8
callq 0x36b80
cmpl $0x0, %eax
je 0x52afa
leaq 0xe12f2(%rip), %rdi     # 0x133de0
movb $0x0, %al
callq 0xd5010
jmp 0x53086
movq 0x10(%rsp), %rax
movsd 0x38(%rsp), %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, (%rax)
movsd 0x30(%rsp), %xmm0
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x20(%rax)
movsd 0x28(%rsp), %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x40(%rax)
movsd 0x20(%rsp), %xmm0
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x60(%rax)
movsd 0xb0(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x70(%rsp), %xmm3
movsd 0x68(%rsp), %xmm4
movsd 0x60(%rsp), %xmm5
movsd 0x50(%rsp), %xmm6
movsd 0x48(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x8(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x78(%rsp), %xmm3
movsd 0x68(%rsp), %xmm4
movsd 0x60(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x48(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x28(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xb0(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x78(%rsp), %xmm3
movsd 0x70(%rsp), %xmm4
movsd 0x60(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x50(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x48(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xb0(%rsp), %xmm1
movsd 0xa8(%rsp), %xmm2
movsd 0x78(%rsp), %xmm3
movsd 0x70(%rsp), %xmm4
movsd 0x68(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x50(%rsp), %xmm7
movsd 0x48(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x68(%rax)
movsd 0xb0(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x90(%rsp), %xmm3
movsd 0x88(%rsp), %xmm4
movsd 0x80(%rsp), %xmm5
movsd 0x50(%rsp), %xmm6
movsd 0x48(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x10(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x98(%rsp), %xmm3
movsd 0x88(%rsp), %xmm4
movsd 0x80(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x48(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x30(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xb0(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x98(%rsp), %xmm3
movsd 0x90(%rsp), %xmm4
movsd 0x80(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x50(%rsp), %xmm7
movsd 0x40(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x50(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xb0(%rsp), %xmm1
movsd 0xa8(%rsp), %xmm2
movsd 0x98(%rsp), %xmm3
movsd 0x90(%rsp), %xmm4
movsd 0x88(%rsp), %xmm5
movsd 0x58(%rsp), %xmm6
movsd 0x50(%rsp), %xmm7
movsd 0x48(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x70(%rax)
movsd 0xb0(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x90(%rsp), %xmm3
movsd 0x88(%rsp), %xmm4
movsd 0x80(%rsp), %xmm5
movsd 0x70(%rsp), %xmm6
movsd 0x68(%rsp), %xmm7
movsd 0x60(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x18(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x98(%rsp), %xmm3
movsd 0x88(%rsp), %xmm4
movsd 0x80(%rsp), %xmm5
movsd 0x78(%rsp), %xmm6
movsd 0x68(%rsp), %xmm7
movsd 0x60(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x38(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xb0(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
movsd 0x98(%rsp), %xmm3
movsd 0x90(%rsp), %xmm4
movsd 0x80(%rsp), %xmm5
movsd 0x78(%rsp), %xmm6
movsd 0x70(%rsp), %xmm7
movsd 0x60(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
movq %xmm0, %rcx
movabsq $-0x8000000000000000, %rdx # imm = 0x8000000000000000
xorq %rdx, %rcx
movq %rcx, %xmm0
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x58(%rax)
movsd 0xb8(%rsp), %xmm0
movsd 0xb0(%rsp), %xmm1
movsd 0xa8(%rsp), %xmm2
movsd 0x98(%rsp), %xmm3
movsd 0x90(%rsp), %xmm4
movsd 0x88(%rsp), %xmm5
movsd 0x78(%rsp), %xmm6
movsd 0x70(%rsp), %xmm7
movsd 0x68(%rsp), %xmm8
movsd %xmm8, (%rsp)
callq 0x53160
movq 0x10(%rsp), %rax
divsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x78(%rax)
addq $0xc8, %rsp
retq
nop