// File: /workspace/github_cpp_makefile_star2_O2/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 0x6a48a(%rip), %xmm0    # 0x93008
addsd %xmm0, %xmm1
movsd 0x6b1d6(%rip), %xmm2    # 0x93d60
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 0x6a45c(%rip), %xmm5    # 0x93030
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 0x28bfa
andq $0x0, 0x8(%rbx)
ucomisd %xmm4, %xmm0
jbe 0x28c05
andq $0x0, 0x10(%rbx)
maxsd %xmm1, %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm5, %xmm1
jbe 0x28c18
andq $0x0, 0x18(%rbx)
ucomisd %xmm1, %xmm0
jb 0x28c24
sqrtsd %xmm0, %xmm0
jmp 0x28c29
callq 0xe350
movsd %xmm0, (%rbx)
movsd 0x8(%rbx), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x28c42
sqrtsd %xmm0, %xmm0
jmp 0x28c4b
callq 0xe350
xorpd %xmm1, %xmm1
movsd %xmm0, 0x8(%rbx)
movsd 0x10(%rbx), %xmm0
ucomisd %xmm1, %xmm0
jb 0x28c61
sqrtsd %xmm0, %xmm0
jmp 0x28c66
callq 0xe350
movsd %xmm0, 0x10(%rbx)
movsd 0x18(%rbx), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x28c80
sqrtsd %xmm0, %xmm0
jmp 0x28c85
callq 0xe350
movsd %xmm0, 0x18(%rbx)
movsd (%rbx), %xmm3
movsd 0x8(%rbx), %xmm2
ucomisd %xmm2, %xmm3
movsd 0x10(%rbx), %xmm1
jb 0x28d6f
ucomisd %xmm1, %xmm3
jb 0x28d6f
ucomisd %xmm0, %xmm3
jb 0x28d6f
movsd 0x48(%r14), %xmm4
subsd 0x30(%r14), %xmm4
xorpd %xmm3, %xmm3
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm3, %xmm4
movsd 0x6a344(%rip), %xmm5    # 0x93020
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x6a318(%rip), %xmm4    # 0x93008
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 0x28f16
ucomisd %xmm3, %xmm2
jb 0x28e45
ucomisd %xmm1, %xmm2
jb 0x28e45
ucomisd %xmm0, %xmm2
jb 0x28e45
movsd 0x48(%r14), %xmm4
subsd 0x30(%r14), %xmm4
xorpd %xmm2, %xmm2
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm2, %xmm4
movsd 0x6a26d(%rip), %xmm5    # 0x93020
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x6a241(%rip), %xmm4    # 0x93008
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 0x28f16
ucomisd %xmm3, %xmm1
jb 0x28f2a
ucomisd %xmm2, %xmm1
jb 0x28f2a
ucomisd %xmm0, %xmm1
jb 0x28f2a
movsd 0x10(%r14), %xmm4
subsd 0x40(%r14), %xmm4
xorpd %xmm1, %xmm1
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm1, %xmm4
movsd 0x6a197(%rip), %xmm5    # 0x93020
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x6a16b(%rip), %xmm4    # 0x93008
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 0x28780
ucomisd %xmm3, %xmm0
jb 0x29005
ucomisd %xmm2, %xmm0
jb 0x29005
ucomisd %xmm1, %xmm0
jb 0x29005
movsd 0x20(%r14), %xmm4
subsd 0x8(%r14), %xmm4
xorpd %xmm0, %xmm0
xorpd %xmm6, %xmm6
cmpltsd %xmm4, %xmm6
cmpltsd %xmm0, %xmm4
movsd 0x6a0b2(%rip), %xmm5    # 0x93020
andpd %xmm5, %xmm4
movapd %xmm6, %xmm7
andnpd %xmm4, %xmm7
movsd 0x6a086(%rip), %xmm4    # 0x93008
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 0x28f1b
xorpd %xmm0, %xmm0
movupd %xmm0, 0x10(%rbx)
movupd %xmm0, (%rbx)
jmp 0x28f1b
nop