// File: /workspace/github_cpp_makefile_star2_O1/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), %xmm0
addsd 0x28(%rsi), %xmm0
addsd 0x50(%rsi), %xmm0
movsd 0x768d2(%rip), %xmm3    # 0xa2038
addsd %xmm3, %xmm0
movsd 0x7763e(%rip), %xmm4    # 0xa2db0
mulsd %xmm4, %xmm0
movsd %xmm0, (%rdi)
movsd (%rsi), %xmm1
subsd 0x28(%rsi), %xmm1
subsd 0x50(%rsi), %xmm1
addsd %xmm3, %xmm1
mulsd %xmm4, %xmm1
movsd %xmm1, 0x8(%rdi)
movsd 0x28(%rsi), %xmm2
subsd (%rsi), %xmm2
subsd 0x50(%rsi), %xmm2
addsd %xmm3, %xmm2
mulsd %xmm4, %xmm2
movsd %xmm2, 0x10(%rdi)
movsd (%rsi), %xmm5
xorpd 0x76864(%rip), %xmm5    # 0xa2020
subsd 0x28(%rsi), %xmm5
addsd 0x50(%rsi), %xmm5
addsd %xmm3, %xmm5
mulsd %xmm4, %xmm5
movsd %xmm5, 0x18(%rdi)
xorpd %xmm3, %xmm3
ucomisd %xmm0, %xmm3
jbe 0x2b7e4
movq $0x0, (%rbx)
ucomisd %xmm1, %xmm3
jbe 0x2b7f2
movq $0x0, 0x8(%rbx)
xorpd %xmm0, %xmm0
ucomisd %xmm2, %xmm0
jbe 0x2b804
movq $0x0, 0x10(%rbx)
ucomisd %xmm5, %xmm0
jbe 0x2b812
movq $0x0, 0x18(%rbx)
movsd (%rbx), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x2b826
sqrtsd %xmm0, %xmm0
jmp 0x2b82f
callq 0xe340
xorpd %xmm1, %xmm1
movsd %xmm0, (%rbx)
movsd 0x8(%rbx), %xmm0
ucomisd %xmm1, %xmm0
jb 0x2b844
sqrtsd %xmm0, %xmm0
jmp 0x2b849
callq 0xe340
movsd %xmm0, 0x8(%rbx)
movsd 0x10(%rbx), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x2b863
sqrtsd %xmm0, %xmm0
jmp 0x2b86c
callq 0xe340
xorpd %xmm1, %xmm1
movsd %xmm0, 0x10(%rbx)
movsd 0x18(%rbx), %xmm0
ucomisd %xmm1, %xmm0
jb 0x2b882
sqrtsd %xmm0, %xmm0
jmp 0x2b887
callq 0xe340
movsd %xmm0, 0x18(%rbx)
movsd (%rbx), %xmm3
movsd 0x8(%rbx), %xmm2
ucomisd %xmm2, %xmm3
movsd 0x10(%rbx), %xmm1
jb 0x2b971
ucomisd %xmm1, %xmm3
jb 0x2b971
ucomisd %xmm0, %xmm3
jb 0x2b971
movsd 0x48(%r14), %xmm4
subsd 0x30(%r14), %xmm4
xorpd %xmm3, %xmm3
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm3, %xmm4
movsd 0x7676a(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x76746(%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 0x2bb18
ucomisd %xmm3, %xmm2
jb 0x2ba47
ucomisd %xmm1, %xmm2
jb 0x2ba47
ucomisd %xmm0, %xmm2
jb 0x2ba47
movsd 0x48(%r14), %xmm4
subsd 0x30(%r14), %xmm4
xorpd %xmm2, %xmm2
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm2, %xmm4
movsd 0x76693(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x7666f(%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 0x2bb18
ucomisd %xmm3, %xmm1
jb 0x2bb2c
ucomisd %xmm2, %xmm1
jb 0x2bb2c
ucomisd %xmm0, %xmm1
jb 0x2bb2c
movsd 0x10(%r14), %xmm4
subsd 0x40(%r14), %xmm4
xorpd %xmm1, %xmm1
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm1, %xmm4
movsd 0x765bd(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x76599(%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 0x2b38e
ucomisd %xmm3, %xmm0
jb 0x2bc07
ucomisd %xmm2, %xmm0
jb 0x2bc07
ucomisd %xmm1, %xmm0
jb 0x2bc07
movsd 0x20(%r14), %xmm4
subsd 0x8(%r14), %xmm4
xorpd %xmm0, %xmm0
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm0, %xmm4
movsd 0x764d8(%rip), %xmm5    # 0xa2048
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x764b4(%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 0x2bb1d
xorpd %xmm0, %xmm0
movupd %xmm0, 0x10(%rbx)
movupd %xmm0, (%rbx)
jmp 0x2bb1d
nop