// File: /workspace/github_cpp_makefile_star2_O2/Luthaf[P]zeopp/rmsd.cc
// Function: fast_rmsd(double (*) [3], double (*) [3], int, double*)
void fast_rmsd(double ref_xlist[][3],
               double mov_xlist[][3], 
               int n_list,
               double* rmsd)
{ 
  double R[3][3];
  double d0,d1,d2,e0,e1,f0;
  double omega;
  double mov_com[3];
  double mov_to_ref[3];

  /* cubic roots */
  double r1,r2,r3;
  double rlow;
  
  double v[3];
  double Eo, residual;
    
  setup_rotation(ref_xlist, mov_xlist, n_list, 
                 mov_com, mov_to_ref, R, &Eo);
  
  /* 
   * check if the determinant is greater than 0 to
   * see if R produces a right-handed or left-handed
   * co-ordinate system.
   */
  cross(v, &R[1][0], &R[2][0]);
  if (dot(&R[0][0], v) > 0.0)
    omega = 1.0;
  else
    omega = -1.0;

  /*
   * get elements we need from tran(R) x R 
   *  (funky matrix naming relic of first attempt using pivots)
   *          matrix = d0 e0 f0
   *                      d1 e1
   *                         d2
   * divide matrix by d0, so that cubic root algorithm can handle it 
   */
   
  d0 =  R[0][0]*R[0][0] + R[1][0]*R[1][0] + R[2][0]*R[2][0];

  d1 = (R[0][1]*R[0][1] + R[1][1]*R[1][1] + R[2][1]*R[2][1])/d0;
  d2 = (R[0][2]*R[0][2] + R[1][2]*R[1][2] + R[2][2]*R[2][2])/d0;

  e0 = (R[0][0]*R[0][1] + R[1][0]*R[1][1] + R[2][0]*R[2][1])/d0;
  e1 = (R[0][1]*R[0][2] + R[1][1]*R[1][2] + R[2][1]*R[2][2])/d0;

  f0 = (R[0][0]*R[0][2] + R[1][0]*R[1][2] + R[2][0]*R[2][2])/d0;

  /* cubic roots */
  {
    double B, C, D, q, q3, r, theta;
    /*
     * solving for eigenvalues as det(A-I*lambda) = 0
     * yeilds the values below corresponding to:
     * lambda**3 + B*lambda**2 + C*lambda + D = 0
     *   (given that d0=1.)
     */
    B = -1.0 - d1 - d2;
    C = d1 + d2 + d1*d2 - e0*e0 - f0*f0 - e1*e1;
    D = e0*e0*d2 + e1*e1 + f0*f0*d1 - d1*d2 - 2*e0*f0*e1;

    /* cubic root method of Viete with all safety belts off */
    q = (B*B - 3.0*C) / 9.0;
    q3 = q*q*q;
    r = (2.0*B*B*B - 9.0*B*C + 27.0*D) / 54.0;
    theta = acos(r/sqrt(q3));
    r1 = r2 = r3 = -2.0*sqrt(q);
    r1 *= cos(theta/3.0);
    r2 *= cos((theta + 2.0*PI) / 3.0);
    r3 *= cos((theta - 2.0*PI) / 3.0);
    r1 -= B / 3.0;
    r2 -= B / 3.0;
    r3 -= B / 3.0;
  }

  /* undo the d0 norm to get eigenvalues */
  r1 = r1*d0;
  r2 = r2*d0;
  r3 = r3*d0;

  /* set rlow to lowest eigenval; set other two to r1,r2 */
  if (r3<r1 && r3<r2)
  {
    rlow = r3;
  }
  else if (r2<r1 && r2<r3)
  {
    rlow = r2; 
    r2 = r3;
  } 
  else 
  { 
    rlow = r1; 
    r1 = r3;
  }

  residual = Eo - sqrt(r1) - sqrt(r2) - omega*sqrt(rlow);
  *rmsd = sqrt( (double) residual*2.0 / ((double) n_list) ); 
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x190, %rsp            # imm = 0x190
movq %rcx, %rbx
movl %edx, %ebp
leaq 0x88(%rsp), %rax
movq %rax, (%rsp)
leaq 0x120(%rsp), %rcx
leaq 0x100(%rsp), %r8
leaq 0x140(%rsp), %r14
movq %r14, %r9
callq 0x78ad8
movsd 0x30(%r14), %xmm7
movsd 0x18(%r14), %xmm8
movsd (%r14), %xmm4
movapd 0x20(%r14), %xmm6
movupd 0x38(%r14), %xmm9
movupd 0x8(%r14), %xmm5
movapd %xmm6, %xmm0
mulpd %xmm6, %xmm0
movapd %xmm5, %xmm1
mulpd %xmm5, %xmm1
addpd %xmm0, %xmm1
movapd %xmm9, %xmm0
mulpd %xmm9, %xmm0
addpd %xmm1, %xmm0
movapd %xmm8, %xmm1
unpcklpd %xmm8, %xmm1            # xmm1 = xmm1[0],xmm8[0]
movapd %xmm6, %xmm2
unpcklpd %xmm8, %xmm2            # xmm2 = xmm2[0],xmm8[0]
mulpd %xmm1, %xmm2
movapd %xmm4, %xmm1
unpcklpd %xmm4, %xmm1            # xmm1 = xmm1[0],xmm4[0]
movapd %xmm5, %xmm3
unpcklpd %xmm4, %xmm3            # xmm3 = xmm3[0],xmm4[0]
mulpd %xmm1, %xmm3
addpd %xmm2, %xmm3
movapd %xmm7, %xmm1
unpcklpd %xmm7, %xmm1            # xmm1 = xmm1[0],xmm7[0]
movapd %xmm9, %xmm12
unpcklpd %xmm7, %xmm12           # xmm12 = xmm12[0],xmm7[0]
mulpd %xmm1, %xmm12
addpd %xmm3, %xmm12
movapd %xmm12, %xmm10
unpckhpd %xmm12, %xmm10          # xmm10 = xmm10[1],xmm12[1]
divpd %xmm10, %xmm0
movapd %xmm6, %xmm11
unpckhpd %xmm6, %xmm11           # xmm11 = xmm11[1],xmm6[1]
movapd %xmm6, 0x70(%rsp)
movapd %xmm6, %xmm1
mulsd %xmm11, %xmm1
movapd %xmm5, %xmm6
unpckhpd %xmm5, %xmm6            # xmm6 = xmm6[1],xmm5[1]
movapd %xmm5, 0x50(%rsp)
movapd %xmm5, %xmm3
mulsd %xmm6, %xmm3
addsd %xmm1, %xmm3
movapd %xmm9, %xmm5
unpckhpd %xmm9, %xmm5            # xmm5 = xmm5[1],xmm9[1]
movapd %xmm9, 0xe0(%rsp)
movapd %xmm9, %xmm2
mulsd %xmm5, %xmm2
addsd %xmm3, %xmm2
movapd %xmm8, 0xf0(%rsp)
movapd %xmm8, %xmm1
movapd %xmm11, 0xc0(%rsp)
mulsd %xmm11, %xmm1
movapd %xmm4, 0x30(%rsp)
movapd %xmm4, %xmm3
movapd %xmm6, 0x40(%rsp)
mulsd %xmm6, %xmm3
addsd %xmm1, %xmm3
movapd %xmm7, 0x60(%rsp)
movapd %xmm7, %xmm1
movapd %xmm5, 0xb0(%rsp)
mulsd %xmm5, %xmm1
addsd %xmm3, %xmm1
unpcklpd %xmm1, %xmm12           # xmm12 = xmm12[0],xmm1[0]
divpd %xmm10, %xmm12
movsd 0x86b0f(%rip), %xmm6    # 0x1002e8
subsd %xmm0, %xmm6
movapd %xmm0, %xmm5
unpckhpd %xmm0, %xmm5            # xmm5 = xmm5[1],xmm0[1]
subsd %xmm5, %xmm6
movapd %xmm0, %xmm1
addsd %xmm5, %xmm1
movapd %xmm0, %xmm3
mulsd %xmm5, %xmm3
addsd %xmm3, %xmm1
movapd %xmm12, %xmm4
mulsd %xmm12, %xmm4
subsd %xmm4, %xmm1
mulsd %xmm5, %xmm4
divsd %xmm10, %xmm2
movapd %xmm12, %xmm5
mulsd 0x8bf56(%rip), %xmm12   # 0x105778
unpckhpd %xmm5, %xmm5            # xmm5 = xmm5[1,1]
mulsd %xmm5, %xmm12
mulsd %xmm5, %xmm5
subsd %xmm5, %xmm1
mulsd %xmm2, %xmm12
mulsd %xmm2, %xmm2
subsd %xmm2, %xmm1
addsd %xmm2, %xmm4
mulsd %xmm0, %xmm5
addsd %xmm4, %xmm5
subsd %xmm3, %xmm5
movsd 0x8b168(%rip), %xmm0    # 0x1049c0
mulsd %xmm1, %xmm0
movapd %xmm6, %xmm2
mulsd %xmm6, %xmm2
addsd %xmm0, %xmm2
divsd 0x827a0(%rip), %xmm2    # 0xfc010
addsd %xmm5, %xmm12
movsd 0x8bf03(%rip), %xmm0    # 0x105780
mulsd %xmm6, %xmm0
mulsd %xmm1, %xmm0
movapd %xmm6, %xmm1
addsd %xmm6, %xmm1
mulsd %xmm6, %xmm1
movapd %xmm6, 0xa0(%rsp)
mulsd %xmm6, %xmm1
addsd %xmm0, %xmm1
movapd %xmm2, %xmm0
mulsd 0x8bed9(%rip), %xmm12   # 0x105788
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm12
divsd 0x8becf(%rip), %xmm12   # 0x105790
movsd %xmm2, 0x20(%rsp)
mulsd %xmm2, %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
movapd %xmm10, 0xd0(%rsp)
jb 0x798e5
sqrtsd %xmm0, %xmm0
jmp 0x798f8
movapd %xmm12, 0x10(%rsp)
callq 0x4390
movapd 0x10(%rsp), %xmm12
divsd %xmm0, %xmm12
movapd %xmm12, %xmm0
callq 0x4450
movsd %xmm0, 0x10(%rsp)
movsd 0x20(%rsp), %xmm0
ucomisd 0x869c5(%rip), %xmm0    # 0x1002e0
jb 0x79923
sqrtsd %xmm0, %xmm0
jmp 0x79928
callq 0x4390
mulsd 0x8be48(%rip), %xmm0    # 0x105778
movapd %xmm0, 0x20(%rsp)
movsd 0x10(%rsp), %xmm0
divsd 0x878d4(%rip), %xmm0    # 0x101218
callq 0x47e0
mulsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x83198(%rip), %xmm0    # 0xfcaf8
addsd 0x10(%rsp), %xmm0
divsd 0x878aa(%rip), %xmm0    # 0x101218
callq 0x47e0
movapd %xmm0, 0x90(%rsp)
movsd 0x10(%rsp), %xmm0
addsd 0x8be0e(%rip), %xmm0    # 0x105798
divsd 0x87886(%rip), %xmm0    # 0x101218
callq 0x47e0
movapd 0xa0(%rsp), %xmm1
divsd 0x87870(%rip), %xmm1    # 0x101218
movsd 0x80(%rsp), %xmm2
subsd %xmm1, %xmm2
movapd 0xd0(%rsp), %xmm7
mulsd %xmm7, %xmm2
movapd 0x20(%rsp), %xmm3
unpcklpd %xmm3, %xmm3            # xmm3 = xmm3[0,0]
unpcklpd 0x90(%rsp), %xmm0       # xmm0 = xmm0[0],mem[0]
mulpd %xmm3, %xmm0
unpcklpd %xmm1, %xmm1            # xmm1 = xmm1[0,0]
subpd %xmm1, %xmm0
mulpd %xmm0, %xmm7
movapd %xmm2, %xmm0
ucomisd %xmm7, %xmm2
movapd %xmm7, %xmm9
unpckhpd %xmm7, %xmm9            # xmm9 = xmm9[1],xmm7[1]
jbe 0x79a18
ucomisd %xmm7, %xmm9
jbe 0x79a18
movsd %xmm7, 0x20(%rsp)
movapd %xmm0, %xmm7
movapd 0x30(%rsp), %xmm1
movapd 0x50(%rsp), %xmm2
jmp 0x79a4a
ucomisd %xmm9, %xmm0
movapd 0x30(%rsp), %xmm1
movapd 0x50(%rsp), %xmm2
jbe 0x79a44
ucomisd %xmm9, %xmm7
jbe 0x79a44
movsd %xmm9, 0x20(%rsp)
movapd %xmm7, %xmm9
movapd %xmm0, %xmm7
jmp 0x79a4a
movsd %xmm0, 0x20(%rsp)
movapd 0x60(%rsp), %xmm4
movapd %xmm4, %xmm0
movapd 0x70(%rsp), %xmm3
mulsd %xmm3, %xmm0
movapd 0xf0(%rsp), %xmm5
movapd %xmm5, %xmm10
movapd 0xe0(%rsp), %xmm6
mulsd %xmm6, %xmm10
subsd %xmm0, %xmm10
movapd 0xc0(%rsp), %xmm0
mulsd %xmm0, %xmm6
movapd 0xb0(%rsp), %xmm8
mulsd %xmm8, %xmm3
subsd %xmm6, %xmm3
mulsd %xmm5, %xmm8
mulsd %xmm4, %xmm0
subsd %xmm8, %xmm0
mulsd %xmm0, %xmm2
mulsd %xmm3, %xmm1
movsd 0x88(%rsp), %xmm3
xorpd %xmm4, %xmm4
ucomisd %xmm4, %xmm7
jb 0x79ace
sqrtsd %xmm7, %xmm0
jmp 0x79b1b
movapd %xmm7, %xmm0
movapd %xmm1, 0x30(%rsp)
movapd %xmm2, 0x50(%rsp)
movapd %xmm9, 0x70(%rsp)
movsd %xmm3, 0x10(%rsp)
movapd %xmm10, 0x60(%rsp)
callq 0x4390
xorpd %xmm4, %xmm4
movapd 0x60(%rsp), %xmm10
movsd 0x10(%rsp), %xmm3
movapd 0x70(%rsp), %xmm9
movapd 0x50(%rsp), %xmm2
movapd 0x30(%rsp), %xmm1
subsd %xmm0, %xmm3
addsd %xmm2, %xmm1
movapd 0x40(%rsp), %xmm2
mulsd %xmm10, %xmm2
ucomisd %xmm4, %xmm9
jb 0x79b3c
sqrtsd %xmm9, %xmm0
jmp 0x79b6a
movapd %xmm9, %xmm0
movapd %xmm1, 0x30(%rsp)
movapd %xmm2, 0x40(%rsp)
movsd %xmm3, 0x10(%rsp)
callq 0x4390
movsd 0x10(%rsp), %xmm3
movapd 0x40(%rsp), %xmm2
movapd 0x30(%rsp), %xmm1
subsd %xmm0, %xmm3
addsd %xmm1, %xmm2
xorpd %xmm4, %xmm4
movsd 0x20(%rsp), %xmm0
ucomisd %xmm4, %xmm0
jb 0x79b88
sqrtsd %xmm0, %xmm0
jmp 0x79ba9
movapd %xmm2, 0x40(%rsp)
movsd %xmm3, 0x10(%rsp)
callq 0x4390
xorpd %xmm4, %xmm4
movsd 0x10(%rsp), %xmm3
movapd 0x40(%rsp), %xmm2
xorl %eax, %eax
ucomisd %xmm4, %xmm2
seta %al
leaq 0x87b97(%rip), %rcx     # 0x101750
mulsd (%rcx,%rax,8), %xmm0
addsd %xmm3, %xmm0
cvtsi2sd %ebp, %xmm1
addsd %xmm0, %xmm0
divsd %xmm1, %xmm0
ucomisd %xmm4, %xmm0
jb 0x79bda
sqrtsd %xmm0, %xmm0
jmp 0x79bdf
callq 0x4390
movsd %xmm0, (%rbx)
addq $0x190, %rsp            # imm = 0x190
popq %rbx
popq %r14
popq %rbp
retq
nop