// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Align.cpp
// Function: gaps::R3AlignError(gaps::RNArray<gaps::R3Point*> const&, gaps::RNArray<gaps::R3Point*> const&, gaps::R4Matrix const&, gaps::R3Point const&, gaps::R3Point const&, double, double, double const*)
RNScalar 
R3AlignError(const RNArray<R3Point *>& points1, const RNArray<R3Point *>& points2, 
  const R4Matrix& rotation, const R3Point& center1, const R3Point& center2, RNScalar s1, RNScalar s2, 
  const RNScalar* weights)
{
  // Get number of points
  int count = points1.NEntries();
  if (points2.NEntries() < count) count = points2.NEntries();
  if (count == 0) return -1;

  // Compute sum of squared distances
  RNScalar ssd = 0;
  RNScalar total_weight = 0;
  for(int i = 0; i < count; i++) {
    RNScalar weight = (weights) ? weights[i] : 1;
    R3Point *point1 = points1[i];
    R3Point *point2 = points2[i];
    R3Vector v1 = (*point1 - center1) / s1;
    R3Vector v2 = (*point2 - center2) / s2;
    R3Vector v = v1 - rotation * v2;
    ssd += weight * v.Dot(v);
    total_weight += weight;
  }

  // Return RMSD
  if (total_weight == 0) return -1;
  return sqrt(ssd / total_weight);
}

// Assembly:
subq $0x128, %rsp            # imm = 0x128
movq %rdi, 0x118(%rsp)
movq %rsi, 0x110(%rsp)
movq %rdx, 0x108(%rsp)
movq %rcx, 0x100(%rsp)
movq %r8, 0xf8(%rsp)
movsd %xmm0, 0xf0(%rsp)
movsd %xmm1, 0xe8(%rsp)
movq %r9, 0xe0(%rsp)
movq 0x118(%rsp), %rdi
callq 0x13600
movl %eax, 0xdc(%rsp)
movq 0x110(%rsp), %rdi
callq 0x13600
cmpl 0xdc(%rsp), %eax
jge 0x8dc87
movq 0x110(%rsp), %rdi
callq 0x13600
movl %eax, 0xdc(%rsp)
cmpl $0x0, 0xdc(%rsp)
jne 0x8dca7
movsd 0xa537f(%rip), %xmm0    # 0x133018
movsd %xmm0, 0x120(%rsp)
jmp 0x8dea9
xorps %xmm0, %xmm0
movsd %xmm0, 0xd0(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0xc8(%rsp)
movl $0x0, 0xc4(%rsp)
movl 0xc4(%rsp), %eax
cmpl 0xdc(%rsp), %eax
jge 0x8de62
cmpq $0x0, 0xe0(%rsp)
je 0x8dd06
movq 0xe0(%rsp), %rax
movslq 0xc4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, 0x10(%rsp)
jmp 0x8dd16
movsd 0xa52fa(%rip), %xmm0    # 0x133008
movsd %xmm0, 0x10(%rsp)
jmp 0x8dd16
movsd 0x10(%rsp), %xmm0
movsd %xmm0, 0xb8(%rsp)
movq 0x118(%rsp), %rdi
movl 0xc4(%rsp), %esi
callq 0x6d3e0
movq %rax, 0xb0(%rsp)
movq 0x110(%rsp), %rdi
movl 0xc4(%rsp), %esi
callq 0x6d3e0
movq %rax, 0xa8(%rsp)
movq 0xb0(%rsp), %rsi
movq 0x100(%rsp), %rdx
leaq 0x78(%rsp), %rdi
callq 0x6eeb0
movsd 0xf0(%rsp), %xmm0
leaq 0x90(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x711f0
movq 0xa8(%rsp), %rsi
movq 0xf8(%rsp), %rdx
leaq 0x48(%rsp), %rdi
callq 0x6eeb0
movsd 0xe8(%rsp), %xmm0
leaq 0x60(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x711f0
movq 0x108(%rsp), %rsi
leaq 0x18(%rsp), %rdi
leaq 0x60(%rsp), %rdx
callq 0x54fe0
leaq 0x30(%rsp), %rdi
leaq 0x90(%rsp), %rsi
leaq 0x18(%rsp), %rdx
callq 0x710a0
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
leaq 0x30(%rsp), %rsi
movq %rsi, %rdi
callq 0x702c0
movaps %xmm0, %xmm2
movsd 0x8(%rsp), %xmm0
movsd 0xd0(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xd0(%rsp)
movsd 0xb8(%rsp), %xmm0
addsd 0xc8(%rsp), %xmm0
movsd %xmm0, 0xc8(%rsp)
movl 0xc4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc4(%rsp)
jmp 0x8dcca
movsd 0xc8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x8de89
jp 0x8de89
movsd 0xa519a(%rip), %xmm0    # 0x133018
movsd %xmm0, 0x120(%rsp)
jmp 0x8dea9
movsd 0xd0(%rsp), %xmm0
divsd 0xc8(%rsp), %xmm0
callq 0xf390
movsd %xmm0, 0x120(%rsp)
movsd 0x120(%rsp), %xmm0
addq $0x128, %rsp            # imm = 0x128
retq
nopw (%rax,%rax)