// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Quaternion.cpp
// Function: gaps::R3Quaternion::R3Quaternion(gaps::R4Matrix const&, int)
R3Quaternion::
R3Quaternion(const R4Matrix& m, int /* dummy */)
{
#if 1
    // From http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/teche52.html
    v[0] = ( m[0][0] + m[1][1] + m[2][2] + 1.0) / 4.0;
    v[1] = ( m[0][0] - m[1][1] - m[2][2] + 1.0) / 4.0;
    v[2] = (-m[0][0] + m[1][1] - m[2][2] + 1.0) / 4.0;
    v[3] = (-m[0][0] - m[1][1] + m[2][2] + 1.0) / 4.0;
    if (v[0] < 0.0) v[0] = 0.0;
    if (v[1] < 0.0) v[1] = 0.0;
    if (v[2] < 0.0) v[2] = 0.0;
    if (v[3] < 0.0) v[3] = 0.0;
    v[0] = sqrt(v[0]);
    v[1] = sqrt(v[1]);
    v[2] = sqrt(v[2]);
    v[3] = sqrt(v[3]);
    if ((v[0] >= v[1]) && (v[0] >= v[2]) && (v[0] >= v[3])) {
        v[1] *= RNSign(m[2][1] - m[1][2]);
        v[2] *= RNSign(m[0][2] - m[2][0]);
        v[3] *= RNSign(m[1][0] - m[0][1]);
    } 
    else if ((v[1] >= v[0]) && (v[1] >= v[2]) && (v[1] >= v[3])) {
        v[0] *= RNSign(m[2][1] - m[1][2]);
        v[2] *= RNSign(m[1][0] + m[0][1]);
        v[3] *= RNSign(m[0][2] + m[2][0]);
    } 
    else if ((v[2] >= v[0]) && (v[2] >= v[1]) && (v[2] >= v[3])) {
        v[0] *= RNSign(m[0][2] - m[2][0]);
        v[1] *= RNSign(m[1][0] + m[0][1]);
        v[3] *= RNSign(m[2][1] + m[1][2]);
    } 
    else if ((v[3] >= v[0]) && (v[3] >= v[1]) && (v[3] >= v[2])) {
        v[0] *= RNSign(m[1][0] - m[0][1]);
        v[1] *= RNSign(m[2][0] + m[0][2]);
        v[2] *= RNSign(m[2][1] + m[1][2]);
    } 
    else {
        v[0] = 0;
        v[1] = 0;
        v[2] = 0;
        v[3] = 0;
    }
#elif 0
    // Also probably works
    // From http://vamos.sourceforge.net/matrixfaq.htm#Q48
    RNScalar T = m[0][0] + m[1][1] + m[2][2] + 1.0;
    if (T > 0.0) {
        RNScalar S = 0.5 / sqrt(T);
        v[0] = 0.25 / S;
        v[1] = ( m[2][1] - m[1][2] ) * S;
        v[2] = ( m[0][2] - m[2][0] ) * S;
        v[3] = ( m[1][0] - m[0][1] ) * S;
    }
    else {
        if ((m[0][0] >= m[1][1]) && (m[0][0] >= m[2][2])) {
            RNScalar S  = sqrt( 1.0 + m[0][0] - m[1][1] - m[2][2] ) * 2.0;
            v[1] = 0.5 / S;
            v[2] = (m[0][1] + m[1][0] ) / S;
            v[3] = (m[0][2] + m[2][0] ) / S;
            v[0] = (m[1][2] + m[2][1] ) / S;
        }
        else if ((m[1][1] >= m[0][0]) && (m[1][1] >= m[2][2])) {
            RNScalar S  = sqrt( 1.0 + m[1][1] - m[0][0] - m[2][2] ) * 2;
            v[1] = (m[0][1] + m[1][0] ) / S;
            v[2] = 0.5 / S;
            v[3] = (m[1][2] + m[2][1] ) / S;
            v[0] = (m[0][2] + m[2][0] ) / S;
        }
        else if ((m[2][2] >= m[0][0]) && (m[2][2] >= m[1][1])) {
            RNScalar S  = sqrt( 1.0 + m[2][2] - m[0][0] - m[1][1] ) * 2;
            v[1] = (m[0][2] + m[2][0] ) / S;
            v[2] = (m[1][2] + m[2][1] ) / S;
            v[3] = 0.5 / S;
            v[0] = (m[0][1] + m[1][0] ) / S;
        }
    }
#else
    RNAbort("Not implemented");
#endif

    // Normalize
    Normalize();
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movsd (%rsi), %xmm1
addsd 0x28(%rsi), %xmm1
addsd 0x50(%rsi), %xmm1
movsd 0x76b26(%rip), %xmm0    # 0xa2038
addsd %xmm0, %xmm1
movsd 0x77892(%rip), %xmm2    # 0xa2db0
mulsd %xmm2, %xmm1
movsd %xmm1, (%rdi)
movsd (%rsi), %xmm3
subsd 0x28(%rsi), %xmm3
subsd 0x50(%rsi), %xmm3
addsd %xmm0, %xmm3
mulsd %xmm2, %xmm3
movsd %xmm3, 0x8(%rdi)
movsd 0x28(%rsi), %xmm4
subsd (%rsi), %xmm4
subsd 0x50(%rsi), %xmm4
addsd %xmm0, %xmm4
mulsd %xmm2, %xmm4
movsd %xmm4, 0x10(%rdi)
movsd (%rsi), %xmm5
xorpd 0x76ab8(%rip), %xmm5    # 0xa2020
subsd 0x28(%rsi), %xmm5
addsd 0x50(%rsi), %xmm5
addsd %xmm0, %xmm5
mulsd %xmm2, %xmm5
movsd %xmm5, 0x18(%rdi)
xorpd %xmm0, %xmm0
ucomisd %xmm3, %xmm0
jbe 0x2b591
movq $0x0, 0x8(%rbx)
ucomisd %xmm4, %xmm0
jbe 0x2b59f
movq $0x0, 0x10(%rbx)
maxsd %xmm1, %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm5, %xmm1
jbe 0x2b5b5
movq $0x0, 0x18(%rbx)
ucomisd %xmm1, %xmm0
jb 0x2b5c1
sqrtsd %xmm0, %xmm0
jmp 0x2b5c6
callq 0xe340
movsd %xmm0, (%rbx)
movsd 0x8(%rbx), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x2b5df
sqrtsd %xmm0, %xmm0
jmp 0x2b5e8
callq 0xe340
xorpd %xmm1, %xmm1
movsd %xmm0, 0x8(%rbx)
movsd 0x10(%rbx), %xmm0
ucomisd %xmm1, %xmm0
jb 0x2b5fe
sqrtsd %xmm0, %xmm0
jmp 0x2b603
callq 0xe340
movsd %xmm0, 0x10(%rbx)
movsd 0x18(%rbx), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x2b61d
sqrtsd %xmm0, %xmm0
jmp 0x2b622
callq 0xe340
movsd %xmm0, 0x18(%rbx)
movsd (%rbx), %xmm3
movsd 0x8(%rbx), %xmm2
ucomisd %xmm2, %xmm3
movsd 0x10(%rbx), %xmm1
jb 0x2b70c
ucomisd %xmm1, %xmm3
jb 0x2b70c
ucomisd %xmm0, %xmm3
jb 0x2b70c
movsd 0x48(%r14), %xmm4
subsd 0x30(%r14), %xmm4
xorpd %xmm3, %xmm3
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm3, %xmm4
movsd 0x769cf(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x769ab(%rip), %xmm4    # 0xa2038
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm2
movsd %xmm2, 0x8(%rbx)
movsd 0x10(%r14), %xmm2
subsd 0x40(%r14), %xmm2
xorpd %xmm6, %xmm6
cmpltsd %xmm2, %xmm6
cmpltsd %xmm3, %xmm2
andpd %xmm5, %xmm2
movapd %xmm6, %xmm7
andnpd %xmm2, %xmm7
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm1
movsd %xmm1, 0x10(%rbx)
movsd 0x20(%r14), %xmm1
subsd 0x8(%r14), %xmm1
movapd %xmm1, %xmm2
cmpltsd %xmm3, %xmm2
andpd %xmm5, %xmm2
cmpltsd %xmm1, %xmm3
movapd %xmm3, %xmm1
andnpd %xmm2, %xmm1
andpd %xmm4, %xmm3
orpd %xmm1, %xmm3
mulsd %xmm3, %xmm0
jmp 0x2b8b3
ucomisd %xmm3, %xmm2
jb 0x2b7e2
ucomisd %xmm1, %xmm2
jb 0x2b7e2
ucomisd %xmm0, %xmm2
jb 0x2b7e2
movsd 0x48(%r14), %xmm4
subsd 0x30(%r14), %xmm4
xorpd %xmm2, %xmm2
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm2, %xmm4
movsd 0x768f8(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x768d4(%rip), %xmm4    # 0xa2038
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm3
movsd %xmm3, (%rbx)
movsd 0x20(%r14), %xmm3
addsd 0x8(%r14), %xmm3
xorpd %xmm6, %xmm6
cmpltsd %xmm3, %xmm6
cmpltsd %xmm2, %xmm3
andpd %xmm5, %xmm3
movapd %xmm6, %xmm7
andnpd %xmm3, %xmm7
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm1
movsd %xmm1, 0x10(%rbx)
movsd 0x10(%r14), %xmm1
addsd 0x40(%r14), %xmm1
movapd %xmm1, %xmm3
cmpltsd %xmm2, %xmm3
andpd %xmm5, %xmm3
cmpltsd %xmm1, %xmm2
movapd %xmm2, %xmm1
andnpd %xmm3, %xmm1
andpd %xmm4, %xmm2
orpd %xmm1, %xmm2
mulsd %xmm2, %xmm0
jmp 0x2b8b3
ucomisd %xmm3, %xmm1
jb 0x2b8c7
ucomisd %xmm2, %xmm1
jb 0x2b8c7
ucomisd %xmm0, %xmm1
jb 0x2b8c7
movsd 0x10(%r14), %xmm4
subsd 0x40(%r14), %xmm4
xorpd %xmm1, %xmm1
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm1, %xmm4
movsd 0x76822(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x767fe(%rip), %xmm4    # 0xa2038
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm3
movsd %xmm3, (%rbx)
movsd 0x20(%r14), %xmm3
addsd 0x8(%r14), %xmm3
xorpd %xmm6, %xmm6
cmpltsd %xmm3, %xmm6
cmpltsd %xmm1, %xmm3
andpd %xmm5, %xmm3
movapd %xmm6, %xmm7
andnpd %xmm3, %xmm7
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm2
movsd %xmm2, 0x8(%rbx)
movsd 0x48(%r14), %xmm2
addsd 0x30(%r14), %xmm2
movapd %xmm2, %xmm3
cmpltsd %xmm1, %xmm3
andpd %xmm5, %xmm3
cmpltsd %xmm2, %xmm1
movapd %xmm1, %xmm2
andnpd %xmm3, %xmm2
andpd %xmm4, %xmm1
orpd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rbx)
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x2b146
ucomisd %xmm3, %xmm0
jb 0x2b9a2
ucomisd %xmm2, %xmm0
jb 0x2b9a2
ucomisd %xmm1, %xmm0
jb 0x2b9a2
movsd 0x20(%r14), %xmm4
subsd 0x8(%r14), %xmm4
xorpd %xmm0, %xmm0
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm0, %xmm4
movsd 0x7673d(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x76719(%rip), %xmm4    # 0xa2038
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm3
movsd %xmm3, (%rbx)
movsd 0x40(%r14), %xmm3
addsd 0x10(%r14), %xmm3
xorpd %xmm6, %xmm6
cmpltsd %xmm3, %xmm6
cmpltsd %xmm0, %xmm3
andpd %xmm5, %xmm3
movapd %xmm6, %xmm7
andnpd %xmm3, %xmm7
andpd %xmm4, %xmm6
orpd %xmm7, %xmm6
mulsd %xmm6, %xmm2
movsd %xmm2, 0x8(%rbx)
movsd 0x48(%r14), %xmm2
addsd 0x30(%r14), %xmm2
movapd %xmm2, %xmm3
cmpltsd %xmm0, %xmm3
andpd %xmm5, %xmm3
cmpltsd %xmm2, %xmm0
movapd %xmm0, %xmm2
andnpd %xmm3, %xmm2
andpd %xmm4, %xmm0
orpd %xmm2, %xmm0
mulsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rbx)
jmp 0x2b8b8
xorpd %xmm0, %xmm0
movupd %xmm0, 0x10(%rbx)
movupd %xmm0, (%rbx)
jmp 0x2b8b8