// File: 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
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl -0x14(%rbp), %edx
leaq -0xc0(%rbp), %rcx
leaq -0xe0(%rbp), %r8
leaq -0x70(%rbp), %r9
leaq -0x128(%rbp), %rax
movq %rax, (%rsp)
callq 0x1153e0
leaq -0x120(%rbp), %rdi
leaq -0x70(%rbp), %rsi
addq $0x18, %rsi
leaq -0x70(%rbp), %rdx
addq $0x30, %rdx
callq 0x116830
leaq -0x70(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x115380
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x116a7e
movsd 0xdb5dc(%rip), %xmm0    # 0x1f2050
movsd %xmm0, -0xa8(%rbp)
jmp 0x116a8e
movsd 0xdbcf2(%rip), %xmm0    # 0x1f2778
movsd %xmm0, -0xa8(%rbp)
movsd -0x70(%rbp), %xmm1
movsd -0x70(%rbp), %xmm2
movsd -0x58(%rbp), %xmm0
mulsd -0x58(%rbp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x40(%rbp), %xmm0
movsd -0x40(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x78(%rbp)
movsd -0x68(%rbp), %xmm1
movsd -0x68(%rbp), %xmm2
movsd -0x50(%rbp), %xmm0
mulsd -0x50(%rbp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x38(%rbp), %xmm0
movsd -0x38(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
divsd -0x78(%rbp), %xmm0
movsd %xmm0, -0x80(%rbp)
movsd -0x60(%rbp), %xmm1
movsd -0x60(%rbp), %xmm2
movsd -0x48(%rbp), %xmm0
mulsd -0x48(%rbp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x30(%rbp), %xmm0
movsd -0x30(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
divsd -0x78(%rbp), %xmm0
movsd %xmm0, -0x88(%rbp)
movsd -0x70(%rbp), %xmm1
movsd -0x68(%rbp), %xmm2
movsd -0x58(%rbp), %xmm0
mulsd -0x50(%rbp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x40(%rbp), %xmm0
movsd -0x38(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
divsd -0x78(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
movsd -0x68(%rbp), %xmm1
movsd -0x60(%rbp), %xmm2
movsd -0x50(%rbp), %xmm0
mulsd -0x48(%rbp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x38(%rbp), %xmm0
movsd -0x30(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
divsd -0x78(%rbp), %xmm0
movsd %xmm0, -0x98(%rbp)
movsd -0x70(%rbp), %xmm1
movsd -0x60(%rbp), %xmm2
movsd -0x58(%rbp), %xmm0
mulsd -0x48(%rbp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x40(%rbp), %xmm0
movsd -0x30(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
divsd -0x78(%rbp), %xmm0
movsd %xmm0, -0xa0(%rbp)
movsd 0xdbb8b(%rip), %xmm0    # 0x1f2778
subsd -0x80(%rbp), %xmm0
subsd -0x88(%rbp), %xmm0
movsd %xmm0, -0x138(%rbp)
movsd -0x80(%rbp), %xmm0
addsd -0x88(%rbp), %xmm0
movsd -0x80(%rbp), %xmm1
movsd -0x88(%rbp), %xmm2
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x90(%rbp), %xmm0
movsd -0x90(%rbp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd -0xa0(%rbp), %xmm1
movsd -0xa0(%rbp), %xmm2
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x98(%rbp), %xmm0
movsd -0x98(%rbp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x140(%rbp)
movsd -0x90(%rbp), %xmm1
mulsd -0x90(%rbp), %xmm1
movsd -0x88(%rbp), %xmm2
movsd -0x98(%rbp), %xmm0
mulsd -0x98(%rbp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0xa0(%rbp), %xmm0
mulsd -0xa0(%rbp), %xmm0
movsd -0x80(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd -0x80(%rbp), %xmm1
movsd -0x88(%rbp), %xmm2
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd 0xdb30e(%rip), %xmm0    # 0x1f2048
mulsd -0x90(%rbp), %xmm0
mulsd -0xa0(%rbp), %xmm0
movsd -0x98(%rbp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x148(%rbp)
movsd -0x138(%rbp), %xmm0
movsd -0x138(%rbp), %xmm2
movsd 0xe0637(%rip), %xmm1    # 0x1f73c8
mulsd -0x140(%rbp), %xmm1
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd 0xdb268(%rip), %xmm1    # 0x1f2028
divsd %xmm1, %xmm0
movsd %xmm0, -0x150(%rbp)
movsd -0x150(%rbp), %xmm0
mulsd -0x150(%rbp), %xmm0
mulsd -0x150(%rbp), %xmm0
movsd %xmm0, -0x158(%rbp)
movsd 0xdb254(%rip), %xmm1    # 0x1f2048
mulsd -0x138(%rbp), %xmm1
mulsd -0x138(%rbp), %xmm1
movsd -0x138(%rbp), %xmm2
movsd 0xdb214(%rip), %xmm0    # 0x1f2028
mulsd -0x138(%rbp), %xmm0
mulsd -0x140(%rbp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd -0x148(%rbp), %xmm0
movsd 0xe6ced(%rip), %xmm2    # 0x1fdb40
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd 0xe6cd5(%rip), %xmm1    # 0x1fdb38
divsd %xmm1, %xmm0
movsd %xmm0, -0x160(%rbp)
movsd -0x160(%rbp), %xmm0
movsd %xmm0, -0x170(%rbp)
movsd -0x158(%rbp), %xmm0
callq 0x53f0
movaps %xmm0, %xmm1
movsd -0x170(%rbp), %xmm0
divsd %xmm1, %xmm0
callq 0x54f0
movsd %xmm0, -0x168(%rbp)
movsd -0x150(%rbp), %xmm0
callq 0x53f0
movaps %xmm0, %xmm1
movsd 0xe6c70(%rip), %xmm0    # 0x1fdb30
mulsd %xmm1, %xmm0
movsd %xmm0, -0xf8(%rbp)
movsd %xmm0, -0xf0(%rbp)
movsd %xmm0, -0xe8(%rbp)
movsd -0x168(%rbp), %xmm0
movsd 0xe04dc(%rip), %xmm1    # 0x1f73c8
divsd %xmm1, %xmm0
callq 0x5970
mulsd -0xe8(%rbp), %xmm0
movsd %xmm0, -0xe8(%rbp)
movsd 0xdbb93(%rip), %xmm0    # 0x1f2aa0
addsd -0x168(%rbp), %xmm0
movsd 0xe04ab(%rip), %xmm1    # 0x1f73c8
divsd %xmm1, %xmm0
callq 0x5970
mulsd -0xf0(%rbp), %xmm0
movsd %xmm0, -0xf0(%rbp)
movsd -0x168(%rbp), %xmm0
movsd 0xdbb5a(%rip), %xmm1    # 0x1f2aa0
subsd %xmm1, %xmm0
movsd 0xe0476(%rip), %xmm1    # 0x1f73c8
divsd %xmm1, %xmm0
callq 0x5970
mulsd -0xf8(%rbp), %xmm0
movsd %xmm0, -0xf8(%rbp)
movsd -0x138(%rbp), %xmm1
movsd 0xe044d(%rip), %xmm0    # 0x1f73c8
divsd %xmm0, %xmm1
movsd -0xe8(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0xe8(%rbp)
movsd -0x138(%rbp), %xmm1
movsd 0xe0425(%rip), %xmm0    # 0x1f73c8
divsd %xmm0, %xmm1
movsd -0xf0(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0xf0(%rbp)
movsd -0x138(%rbp), %xmm1
movsd 0xe03fd(%rip), %xmm0    # 0x1f73c8
divsd %xmm0, %xmm1
movsd -0xf8(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0xf8(%rbp)
movsd -0xe8(%rbp), %xmm0
mulsd -0x78(%rbp), %xmm0
movsd %xmm0, -0xe8(%rbp)
movsd -0xf0(%rbp), %xmm0
mulsd -0x78(%rbp), %xmm0
movsd %xmm0, -0xf0(%rbp)
movsd -0xf8(%rbp), %xmm0
mulsd -0x78(%rbp), %xmm0
movsd %xmm0, -0xf8(%rbp)
movsd -0xf8(%rbp), %xmm1
movsd -0xe8(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x117060
movsd -0xf8(%rbp), %xmm1
movsd -0xf0(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x117060
movsd -0xf8(%rbp), %xmm0
movsd %xmm0, -0x100(%rbp)
jmp 0x1170d0
movsd -0xf0(%rbp), %xmm1
movsd -0xe8(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1170ae
movsd -0xf0(%rbp), %xmm1
movsd -0xf8(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1170ae
movsd -0xf0(%rbp), %xmm0
movsd %xmm0, -0x100(%rbp)
movsd -0xf8(%rbp), %xmm0
movsd %xmm0, -0xf0(%rbp)
jmp 0x1170ce
movsd -0xe8(%rbp), %xmm0
movsd %xmm0, -0x100(%rbp)
movsd -0xf8(%rbp), %xmm0
movsd %xmm0, -0xe8(%rbp)
jmp 0x1170d0
movsd -0x128(%rbp), %xmm0
movsd %xmm0, -0x190(%rbp)
movsd -0xe8(%rbp), %xmm0
callq 0x53f0
movaps %xmm0, %xmm1
movsd -0x190(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0x188(%rbp)
movsd -0xf0(%rbp), %xmm0
callq 0x53f0
movaps %xmm0, %xmm1
movsd -0x188(%rbp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, -0x180(%rbp)
movsd -0xa8(%rbp), %xmm0
movsd %xmm0, -0x178(%rbp)
movsd -0x100(%rbp), %xmm0
callq 0x53f0
movsd -0x180(%rbp), %xmm1
movaps %xmm0, %xmm2
movsd -0x178(%rbp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x130(%rbp)
movsd 0xdaec1(%rip), %xmm0    # 0x1f2048
mulsd -0x130(%rbp), %xmm0
cvtsi2sdl -0x14(%rbp), %xmm1
divsd %xmm1, %xmm0
callq 0x53f0
movq -0x20(%rbp), %rax
movsd %xmm0, (%rax)
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
nop