// File: tomfunkhouser[P]gaps/pkgs/R3Utils/R3Segmentation.cpp
// Function: gaps::MergedConvexity(gaps::R3SegmentationCluster const*, gaps::R3SegmentationCluster const*)
static RNScalar
MergedConvexity(const R3SegmentationCluster *cluster1, const R3SegmentationCluster *cluster2)
{
  // THIS DOES NOT MAKE CLUSTERS MORE CONVEX :(
  
  // int external1 = 0;
  int internal1 = 0;
  int interface1 = 0;
  // int external2 = 0;
  int internal2 = 0;
  int interface2 = 0;
  int max_samples = 1024;

  int step1 = cluster1->points.NEntries() / max_samples;
  if (step1 == 0) step1 = 1;
  for (int i1 = 0; i1 < cluster1->points.NEntries(); i1 += step1) {
    R3SegmentationPoint *point1 = cluster1->points.Kth(i1);
    for (int j1 = 0; j1 < point1->neighbors.NEntries(); j1++) {
      R3SegmentationPoint *neighbor = point1->neighbors.Kth(j1);
      if (neighbor->cluster == cluster1) internal1++;
      else if (neighbor->cluster == cluster2) interface1++;
      // else external1++;
    }
  }

  RNScalar numerator1 = interface1;
  RNScalar denominator1 = interface1 + internal1;
  RNScalar convexity1 = (denominator1 > 0) ? numerator1 / denominator1 : 0;
           
  int step2 = cluster2->points.NEntries() / max_samples;
  if (step2 == 0) step2 = 1;
  for (int i2 = 0; i2 < cluster2->points.NEntries(); i2 += step2) {
    R3SegmentationPoint *point2 = cluster2->points.Kth(i2);
    for (int j2 = 0; j2 < point2->neighbors.NEntries(); j2++) {
      R3SegmentationPoint *neighbor = point2->neighbors.Kth(j2);
      if (neighbor->cluster == cluster2) internal2++;
      else if (neighbor->cluster == cluster1) interface2++;
      // else external2++;
    }
  }

  RNScalar numerator2 = interface2;
  RNScalar denominator2 = interface2 + internal2;
  RNScalar convexity2 = (denominator2 > 0) ? numerator2 / denominator2 : 0;
           
  return sqrt(convexity1 * convexity2);
}

// Assembly:
subq $0xb8, %rsp
movq %rdi, 0xb0(%rsp)
movq %rsi, 0xa8(%rsp)
movl $0x0, 0xa4(%rsp)
movl $0x0, 0xa0(%rsp)
movl $0x0, 0x9c(%rsp)
movl $0x0, 0x98(%rsp)
movl $0x400, 0x94(%rsp) # imm = 0x400
movq 0xb0(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
cltd
idivl 0x94(%rsp)
movl %eax, 0x90(%rsp)
cmpl $0x0, 0x90(%rsp)
jne 0x41c43
movl $0x1, 0x90(%rsp)
movl $0x0, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0xb0(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x41d67
movq 0xb0(%rsp), %rdi
addq $0x8, %rdi
movl 0x8c(%rsp), %esi
callq 0x1f6a0
movq %rax, 0x80(%rsp)
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
movl %eax, 0x18(%rsp)
movq 0x80(%rsp), %rdi
addq $0xb0, %rdi
callq 0x1ecf0
movl %eax, %ecx
movl 0x18(%rsp), %eax
cmpl %ecx, %eax
jge 0x41d4b
movq 0x80(%rsp), %rdi
addq $0xb0, %rdi
movl 0x7c(%rsp), %esi
callq 0x1f6a0
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rax
movq 0xc0(%rax), %rax
cmpq 0xb0(%rsp), %rax
jne 0x41d10
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x41d39
movq 0x70(%rsp), %rax
movq 0xc0(%rax), %rax
cmpq 0xa8(%rsp), %rax
jne 0x41d37
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x41d39
jmp 0x41d3b
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x41ca0
jmp 0x41d4d
movl 0x90(%rsp), %eax
addl 0x8c(%rsp), %eax
movl %eax, 0x8c(%rsp)
jmp 0x41c4e
cvtsi2sdl 0xa0(%rsp), %xmm0
movsd %xmm0, 0x68(%rsp)
movl 0xa0(%rsp), %eax
addl 0xa4(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x60(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x41db1
movsd 0x68(%rsp), %xmm0
divsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
jmp 0x41dbc
xorps %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
jmp 0x41dbc
movsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x58(%rsp)
movq 0xa8(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
cltd
idivl 0x94(%rsp)
movl %eax, 0x54(%rsp)
cmpl $0x0, 0x54(%rsp)
jne 0x41df4
movl $0x1, 0x54(%rsp)
movl $0x0, 0x50(%rsp)
movl 0x50(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0xa8(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0x41ef9
movq 0xa8(%rsp), %rdi
addq $0x8, %rdi
movl 0x50(%rsp), %esi
callq 0x1f6a0
movq %rax, 0x48(%rsp)
movl $0x0, 0x44(%rsp)
movl 0x44(%rsp), %eax
movl %eax, 0x8(%rsp)
movq 0x48(%rsp), %rdi
addq $0xb0, %rdi
callq 0x1ecf0
movl %eax, %ecx
movl 0x8(%rsp), %eax
cmpl %ecx, %eax
jge 0x41ee6
movq 0x48(%rsp), %rdi
addq $0xb0, %rdi
movl 0x44(%rsp), %esi
callq 0x1f6a0
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rax
movq 0xc0(%rax), %rax
cmpq 0xa8(%rsp), %rax
jne 0x41eab
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x41ed4
movq 0x38(%rsp), %rax
movq 0xc0(%rax), %rax
cmpq 0xb0(%rsp), %rax
jne 0x41ed2
movl 0x98(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x98(%rsp)
jmp 0x41ed4
jmp 0x41ed6
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x41e45
jmp 0x41ee8
movl 0x54(%rsp), %eax
addl 0x50(%rsp), %eax
movl %eax, 0x50(%rsp)
jmp 0x41dfc
cvtsi2sdl 0x98(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
movl 0x98(%rsp), %eax
addl 0x9c(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x28(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x41f42
movsd 0x30(%rsp), %xmm0
divsd 0x28(%rsp), %xmm0
movsd %xmm0, (%rsp)
jmp 0x41f4c
xorps %xmm0, %xmm0
movsd %xmm0, (%rsp)
jmp 0x41f4c
movsd (%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movsd 0x58(%rsp), %xmm0
mulsd 0x20(%rsp), %xmm0
callq 0x165a0
addq $0xb8, %rsp
retq