// File: tomfunkhouser[P]gaps/pkgs/R3Utils/R3Segmentation.cpp
// Function: gaps::R3Segmentation::MergeClusters()
int R3Segmentation::
MergeClusters(void)
{
  // Initialize statistics
  int cluster_count = clusters.NEntries();
  int merge_count = 0;
  int push_count = 0;

  //////////

  // Create pairs between clusters with neighbor points
  RNArray<R3SegmentationPair *> pairs;
  for (int i = 0; i < clusters.NEntries(); i++) {
    R3SegmentationCluster *cluster0 = clusters.Kth(i);

    // Sample points
    const int max_points = 64;
    int jstep = cluster0->points.NEntries() / max_points;
    if (jstep == 0) jstep = 1;
    for (int j = 0; j < cluster0->points.NEntries(); j += jstep) {
      R3SegmentationPoint *point0 = cluster0->points.Kth(j);

      // Check neighbors
      for (int k = 0; k < point0->neighbors.NEntries(); k++) {
        R3SegmentationPoint *point1 = point0->neighbors.Kth(k);
        if (point0 == point1) continue;
        R3SegmentationCluster *cluster1 = point1->cluster;
        if (!cluster1) continue;
        if (cluster0 == cluster1) continue;

        // Check if already have pair
        if (FindR3SegmentationPair(cluster0, cluster1)) continue;

        // Compute affinity
        RNScalar affinity = cluster0->Affinity(cluster1);
        if ((affinity < min_pair_affinity) && (cluster_count <= max_clusters) && (min_cluster_points == 0) && (min_cluster_area == 0)) continue;

        // Create pair
        R3SegmentationPair *pair = new R3SegmentationPair(cluster0, cluster1, affinity);
        if (!pair) continue;

        // Insert pair
        pairs.Insert(pair);
      }        
    }
  }

  // Check if there are any pairs
  if (pairs.IsEmpty()) return 1;

  //////////

  // Initialize heap
  R3SegmentationPair tmp;
  RNHeap<R3SegmentationPair *> heap(&tmp, &tmp.affinity, &tmp.heapentry, FALSE);
  for (int i = 0; i < pairs.NEntries(); i++) {
    R3SegmentationPair *pair = pairs.Kth(i);
    heap.Push(pair);
  }

  // Merge clusters hierarchically
  while (!heap.IsEmpty()) {
    // Get pair
    R3SegmentationPair *pair = heap.Pop();

    // Check if we are done
    if ((pair->affinity < min_pair_affinity) && (cluster_count <= max_clusters) && (min_cluster_points == 0) && (min_cluster_area == 0)) {
      break;
    }

    // Get clusters
    R3SegmentationCluster *cluster0 = pair->clusters[0];
    R3SegmentationCluster *cluster1 = pair->clusters[1];

    // Check if either cluster has already been merged
    if (cluster0->parent || cluster1->parent) {
      // Find ancestors
      R3SegmentationCluster *ancestor0 = cluster0;
      R3SegmentationCluster *ancestor1 = cluster1;
      while (ancestor0->parent) ancestor0 = ancestor0->parent;
      while (ancestor1->parent) ancestor1 = ancestor1->parent;
      if (ancestor0 != ancestor1) {
        if (!FindR3SegmentationPair(ancestor0, ancestor1)) {
          RNScalar affinity = ancestor0->Affinity(ancestor1);
          if ((cluster_count > max_clusters) || (min_cluster_points > 0) || (min_cluster_area > 0) || (affinity >= min_pair_affinity)) {
            // Create a pair between the ancestors
            R3SegmentationPair *pair = new R3SegmentationPair(ancestor0, ancestor1, affinity);
            heap.Push(pair);
            push_count++;
          }
        }
      }
    }
    else {
      // Check if should merge
      RNBoolean merge = TRUE;
      if ((min_pair_affinity > 0) && (pair->affinity < min_pair_affinity)) merge = FALSE;
      if ((min_cluster_area > 0) && (cluster0->area < min_cluster_area)) merge = TRUE;
      if ((min_cluster_area > 0) && (cluster1->area < min_cluster_area)) merge = TRUE;
      if ((min_cluster_points > 0) && (cluster0->points.NEntries() < min_cluster_points)) merge = TRUE;
      if ((min_cluster_points > 0) && (cluster1->points.NEntries() < min_cluster_points)) merge = TRUE;
      if ((max_clusters > 0) && (cluster_count > max_clusters)) merge = TRUE;
      if (!merge) { delete pair; continue; }

      // Print message (do not print, but keep so that compiler does not complain
      // about unused variables merge_count and push_count
      if (print_progress == 123) {
        static unsigned long count = 0;
        if ((count++ % 1000) == 0) {
          printf("        %15.12f : %9d %9d : %15d %15d %15d %15d\n", pair->affinity, 
                 cluster0->points.NEntries(), cluster1->points.NEntries(), 
                 heap.NEntries(), merge_count, push_count, cluster_count);
        }
      }
      
#if 0
      // Create merged cluster
      R3SegmentationCluster *cluster = new R3SegmentationCluster(cluster0, cluster1);
      clusters.Insert(cluster);
      cluster_count--;
      merge_count++;
#else
      // Merge smaller cluster into bigger one
      R3SegmentationCluster *parent = (cluster0->points.NEntries() > cluster1->points.NEntries()) ? cluster0 : cluster1;
      R3SegmentationCluster *child = (cluster0->points.NEntries() > cluster1->points.NEntries()) ? cluster1 : cluster0;
      parent->InsertChild(child);
      cluster_count--;
      merge_count++;
#endif
    }

    // Delete pair
    delete pair;
  }

  // Remove merged clusters
  RNArray<R3SegmentationCluster *> merged_clusters;
  RNArray<R3SegmentationCluster *> all_clusters = clusters;
  clusters.Empty();
  for (int i = 0; i < all_clusters.NEntries(); i++) {
    R3SegmentationCluster *cluster = all_clusters.Kth(i);
    cluster->segmentation = this;
    cluster->segmentation_index = clusters.NEntries();    
    if (!cluster->parent) { clusters.Insert(cluster); continue; }
    cluster->parent->RemoveChild(cluster);
    merged_clusters.Insert(cluster);
  }

  // Delete merged clusters
  for (int i = 0; i < merged_clusters.NEntries(); i++) {
    R3SegmentationCluster *cluster = merged_clusters.Kth(i);
    delete cluster;
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x2b8, %rsp            # imm = 0x2B8
movq %rdi, 0x2a8(%rsp)
movq 0x2a8(%rsp), %rdi
movq %rdi, 0x118(%rsp)
addq $0x18, %rdi
callq 0x1ecf0
movl %eax, 0x2a4(%rsp)
movl $0x0, 0x2a0(%rsp)
movl $0x0, 0x29c(%rsp)
leaq 0x288(%rsp), %rdi
callq 0x47660
movl $0x0, 0x284(%rsp)
movq 0x118(%rsp), %rdi
movl 0x284(%rsp), %eax
movl %eax, 0x110(%rsp)
addq $0x18, %rdi
callq 0x1ecf0
movl %eax, 0x114(%rsp)
jmp 0x44925
movl 0x110(%rsp), %eax
movl 0x114(%rsp), %ecx
cmpl %ecx, %eax
jge 0x44cd2
movq 0x118(%rsp), %rdi
addq $0x18, %rdi
movl 0x284(%rsp), %esi
callq 0x20270
movq %rax, 0x108(%rsp)
jmp 0x4495d
movq 0x108(%rsp), %rax
movq %rax, 0x268(%rsp)
movl $0x40, 0x264(%rsp)
movq 0x268(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x104(%rsp)
jmp 0x44992
movl 0x104(%rsp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movl %eax, 0x260(%rsp)
cmpl $0x0, 0x260(%rsp)
jne 0x449d8
movl $0x1, 0x260(%rsp)
jmp 0x449d8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
jmp 0x45799
movl $0x0, 0x25c(%rsp)
movl 0x25c(%rsp), %eax
movl %eax, 0xfc(%rsp)
movq 0x268(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x100(%rsp)
jmp 0x44a0b
movl 0xfc(%rsp), %eax
movl 0x100(%rsp), %ecx
cmpl %ecx, %eax
jge 0x44cba
movq 0x268(%rsp), %rdi
addq $0x8, %rdi
movl 0x25c(%rsp), %esi
callq 0x1f6a0
movq %rax, 0xf0(%rsp)
jmp 0x44a43
movq 0xf0(%rsp), %rax
movq %rax, 0x250(%rsp)
movl $0x0, 0x24c(%rsp)
movl 0x24c(%rsp), %eax
movl %eax, 0xe8(%rsp)
movq 0x250(%rsp), %rdi
addq $0xb0, %rdi
callq 0x1ecf0
movl %eax, 0xec(%rsp)
jmp 0x44a89
movl 0xe8(%rsp), %eax
movl 0xec(%rsp), %ecx
cmpl %ecx, %eax
jge 0x44c9e
movq 0x250(%rsp), %rdi
addq $0xb0, %rdi
movl 0x24c(%rsp), %esi
callq 0x1f6a0
movq %rax, 0xe0(%rsp)
jmp 0x44ac4
movq 0xe0(%rsp), %rax
movq %rax, 0x240(%rsp)
movq 0x250(%rsp), %rax
cmpq 0x240(%rsp), %rax
jne 0x44aeb
jmp 0x44c88
movq 0x240(%rsp), %rax
movq 0xc0(%rax), %rax
movq %rax, 0x238(%rsp)
cmpq $0x0, 0x238(%rsp)
jne 0x44b12
jmp 0x44c88
movq 0x268(%rsp), %rax
cmpq 0x238(%rsp), %rax
jne 0x44b29
jmp 0x44c88
movq 0x268(%rsp), %rdi
movq 0x238(%rsp), %rsi
callq 0x457c0
movq %rax, 0xd8(%rsp)
jmp 0x44b48
movq 0xd8(%rsp), %rax
cmpq $0x0, %rax
je 0x44b5b
jmp 0x44c88
movq 0x268(%rsp), %rdi
movq 0x238(%rsp), %rsi
callq 0x409d0
movsd %xmm0, 0xd0(%rsp)
jmp 0x44b7b
movq 0x118(%rsp), %rax
movsd 0xd0(%rsp), %xmm0
movsd %xmm0, 0x230(%rsp)
movsd 0x230(%rsp), %xmm1
movsd 0xb0(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x44beb
movq 0x118(%rsp), %rcx
movl 0x2a4(%rsp), %eax
cmpl 0x34(%rcx), %eax
jg 0x44beb
movq 0x118(%rsp), %rax
cmpl $0x0, 0x38(%rax)
jne 0x44beb
movq 0x118(%rsp), %rax
movsd 0x40(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x44beb
jp 0x44beb
jmp 0x44c88
movl $0x28, %edi
callq 0x16740
movq %rax, 0xc8(%rsp)
jmp 0x44bff
movq 0xc8(%rsp), %rdi
movq 0x268(%rsp), %rsi
movq 0x238(%rsp), %rdx
movsd 0x230(%rsp), %xmm0
callq 0x41f70
jmp 0x44c27
movq 0xc8(%rsp), %rax
movq %rax, 0x228(%rsp)
cmpq $0x0, 0x228(%rsp)
jne 0x44c6f
jmp 0x44c88
movq 0xc8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
movl $0x28, %esi
callq 0x16750
jmp 0x45799
movq 0x228(%rsp), %rsi
leaq 0x288(%rsp), %rdi
callq 0x47aa0
jmp 0x44c86
jmp 0x44c88
movl 0x24c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24c(%rsp)
jmp 0x44a5e
jmp 0x44ca0
movl 0x260(%rsp), %eax
addl 0x25c(%rsp), %eax
movl %eax, 0x25c(%rsp)
jmp 0x449e3
jmp 0x44cbc
movl 0x284(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x284(%rsp)
jmp 0x448fd
leaq 0x288(%rsp), %rdi
callq 0x3b4b0
movl %eax, 0xc4(%rsp)
jmp 0x44ce8
movl 0xc4(%rsp), %eax
cmpl $0x0, %eax
je 0x44d0f
movl $0x1, 0x2b4(%rsp)
movl $0x1, 0x224(%rsp)
jmp 0x4577d
xorl %eax, %eax
movl %eax, %edx
leaq 0x1f8(%rsp), %rdi
xorps %xmm0, %xmm0
movq %rdx, %rsi
callq 0x41f70
jmp 0x44d28
leaq 0x210(%rsp), %rdx
leaq 0x218(%rsp), %rcx
leaq 0x1c0(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
xorl %r8d, %r8d
callq 0x47dc0
jmp 0x44d52
movl $0x0, 0x1bc(%rsp)
movl 0x1bc(%rsp), %eax
movl %eax, 0xbc(%rsp)
leaq 0x288(%rsp), %rdi
callq 0x1ecf0
movl %eax, 0xc0(%rsp)
jmp 0x44d81
movl 0xbc(%rsp), %eax
movl 0xc0(%rsp), %ecx
cmpl %ecx, %eax
jge 0x44e26
movl 0x1bc(%rsp), %esi
leaq 0x288(%rsp), %rdi
callq 0x47e60
movq %rax, 0xb0(%rsp)
jmp 0x44db5
movq 0xb0(%rsp), %rax
movq %rax, 0x1b0(%rsp)
movq 0x1b0(%rsp), %rsi
leaq 0x1c0(%rsp), %rdi
callq 0x47e80
jmp 0x44ddc
jmp 0x44dde
movl 0x1bc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1bc(%rsp)
jmp 0x44d5d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
jmp 0x4576e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
jmp 0x45761
jmp 0x44e28
leaq 0x1c0(%rsp), %rdi
callq 0x480a0
movl %eax, 0xac(%rsp)
jmp 0x44e3e
movl 0xac(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x44e56
jmp 0x454e2
leaq 0x1c0(%rsp), %rdi
callq 0x480c0
movq %rax, 0xa0(%rsp)
jmp 0x44e6d
movq 0x118(%rsp), %rax
movq 0xa0(%rsp), %rcx
movq %rcx, 0x1a8(%rsp)
movq 0x1a8(%rsp), %rcx
movsd 0x18(%rcx), %xmm1
movsd 0xb0(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x44edf
movq 0x118(%rsp), %rcx
movl 0x2a4(%rsp), %eax
cmpl 0x34(%rcx), %eax
jg 0x44edf
movq 0x118(%rsp), %rax
cmpl $0x0, 0x38(%rax)
jne 0x44edf
movq 0x118(%rsp), %rax
movsd 0x40(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x44edf
jp 0x44edf
jmp 0x454e2
movq 0x1a8(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x1a0(%rsp)
movq 0x1a8(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x198(%rsp)
movq 0x1a0(%rsp), %rax
cmpq $0x0, 0x18(%rax)
jne 0x44f28
movq 0x198(%rsp), %rax
cmpq $0x0, 0x18(%rax)
je 0x4510e
movq 0x1a0(%rsp), %rax
movq %rax, 0x190(%rsp)
movq 0x198(%rsp), %rax
movq %rax, 0x188(%rsp)
movq 0x190(%rsp), %rax
cmpq $0x0, 0x18(%rax)
je 0x44f6d
movq 0x190(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x190(%rsp)
jmp 0x44f48
jmp 0x44f6f
movq 0x188(%rsp), %rax
cmpq $0x0, 0x18(%rax)
je 0x44f94
movq 0x188(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x188(%rsp)
jmp 0x44f6f
movq 0x190(%rsp), %rax
cmpq 0x188(%rsp), %rax
je 0x45109
movq 0x190(%rsp), %rdi
movq 0x188(%rsp), %rsi
callq 0x457c0
movq %rax, 0x98(%rsp)
jmp 0x44fc9
movq 0x98(%rsp), %rax
cmpq $0x0, %rax
jne 0x45107
movq 0x190(%rsp), %rdi
movq 0x188(%rsp), %rsi
callq 0x409d0
movsd %xmm0, 0x90(%rsp)
jmp 0x44ffb
movq 0x118(%rsp), %rcx
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0x180(%rsp)
movl 0x2a4(%rsp), %eax
cmpl 0x34(%rcx), %eax
jg 0x45064
movq 0x118(%rsp), %rax
cmpl $0x0, 0x38(%rax)
jg 0x45064
movq 0x118(%rsp), %rax
movsd 0x40(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
ja 0x45064
movq 0x118(%rsp), %rax
movsd 0x180(%rsp), %xmm0
ucomisd 0xb0(%rax), %xmm0
jb 0x45105
movl $0x28, %edi
callq 0x16740
movq %rax, 0x88(%rsp)
jmp 0x45078
movq 0x88(%rsp), %rdi
movq 0x190(%rsp), %rsi
movq 0x188(%rsp), %rdx
movsd 0x180(%rsp), %xmm0
callq 0x41f70
jmp 0x450a0
movq 0x88(%rsp), %rax
movq %rax, 0x178(%rsp)
movq 0x178(%rsp), %rsi
leaq 0x1c0(%rsp), %rdi
callq 0x47e80
jmp 0x450c7
movl 0x29c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x29c(%rsp)
jmp 0x45105
movq 0x88(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
movl $0x28, %esi
callq 0x16750
jmp 0x45761
jmp 0x45107
jmp 0x45109
jmp 0x454b1
movq 0x118(%rsp), %rax
movl $0x1, 0x174(%rsp)
movsd 0xb0(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x45160
movq 0x118(%rsp), %rax
movq 0x1a8(%rsp), %rcx
movsd 0x18(%rcx), %xmm1
movsd 0xb0(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x45160
movl $0x0, 0x174(%rsp)
movq 0x118(%rsp), %rax
movsd 0x40(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x451a4
movq 0x118(%rsp), %rax
movq 0x1a0(%rsp), %rcx
movsd 0xe8(%rcx), %xmm1
movsd 0x40(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x451a4
movl $0x1, 0x174(%rsp)
movq 0x118(%rsp), %rax
movsd 0x40(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x451e8
movq 0x118(%rsp), %rax
movq 0x198(%rsp), %rcx
movsd 0xe8(%rcx), %xmm1
movsd 0x40(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x451e8
movl $0x1, 0x174(%rsp)
movq 0x118(%rsp), %rax
cmpl $0x0, 0x38(%rax)
jle 0x4522f
movq 0x1a0(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x84(%rsp)
jmp 0x45210
movl 0x84(%rsp), %eax
movq 0x118(%rsp), %rcx
cmpl 0x38(%rcx), %eax
jge 0x4522f
movl $0x1, 0x174(%rsp)
movq 0x118(%rsp), %rax
cmpl $0x0, 0x38(%rax)
jle 0x45276
movq 0x198(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x80(%rsp)
jmp 0x45257
movl 0x80(%rsp), %eax
movq 0x118(%rsp), %rcx
cmpl 0x38(%rcx), %eax
jge 0x45276
movl $0x1, 0x174(%rsp)
movq 0x118(%rsp), %rax
cmpl $0x0, 0x34(%rax)
jle 0x452a3
movq 0x118(%rsp), %rcx
movl 0x2a4(%rsp), %eax
cmpl 0x34(%rcx), %eax
jle 0x452a3
movl $0x1, 0x174(%rsp)
cmpl $0x0, 0x174(%rsp)
jne 0x452de
movq 0x1a8(%rsp), %rax
movq %rax, 0x78(%rsp)
cmpq $0x0, %rax
je 0x452d9
movq 0x78(%rsp), %rdi
callq 0x42040
movq 0x78(%rsp), %rdi
movl $0x28, %esi
callq 0x16750
jmp 0x44e28
movq 0x118(%rsp), %rax
cmpl $0x7b, 0xdc(%rax)
jne 0x453b2
movq 0x223556(%rip), %rax    # 0x268850
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x223548(%rip)    # 0x268850
movl $0x3e8, %ecx            # imm = 0x3E8
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x453b0
movq 0x1a8(%rsp), %rax
movsd 0x18(%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq 0x1a0(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x74(%rsp)
jmp 0x45346
movq 0x198(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x64(%rsp)
jmp 0x4535d
leaq 0x1c0(%rsp), %rdi
callq 0x481d0
movl %eax, 0x60(%rsp)
jmp 0x45370
movl 0x60(%rsp), %ecx
movl 0x64(%rsp), %edx
movl 0x74(%rsp), %esi
movsd 0x68(%rsp), %xmm0
movl 0x2a0(%rsp), %r8d
movl 0x29c(%rsp), %r9d
movl 0x2a4(%rsp), %edi
movq %rsp, %rax
movl %edi, (%rax)
leaq 0x1b8f3f(%rip), %rdi    # 0x1fe2e4
movb $0x1, %al
callq 0x16090
jmp 0x453ae
jmp 0x453b0
jmp 0x453b2
movq 0x1a0(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x5c(%rsp)
jmp 0x453c9
movq 0x198(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x58(%rsp)
jmp 0x453e0
movl 0x5c(%rsp), %eax
movl 0x58(%rsp), %ecx
cmpl %ecx, %eax
jle 0x453fb
movq 0x1a0(%rsp), %rax
movq %rax, 0x50(%rsp)
jmp 0x45408
movq 0x198(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
movq %rax, 0x168(%rsp)
movq 0x1a0(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x4c(%rsp)
jmp 0x4542c
movq 0x198(%rsp), %rdi
addq $0x8, %rdi
callq 0x1ecf0
movl %eax, 0x48(%rsp)
jmp 0x45443
movl 0x4c(%rsp), %eax
movl 0x48(%rsp), %ecx
cmpl %ecx, %eax
jle 0x4545e
movq 0x198(%rsp), %rax
movq %rax, 0x40(%rsp)
jmp 0x4546b
movq 0x1a0(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x160(%rsp)
movq 0x168(%rsp), %rdi
movq 0x160(%rsp), %rsi
callq 0x3f6b0
jmp 0x4548f
movl 0x2a4(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x2a4(%rsp)
movl 0x2a0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2a0(%rsp)
movq 0x1a8(%rsp), %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, %rax
je 0x454dd
movq 0x38(%rsp), %rdi
callq 0x42040
movq 0x38(%rsp), %rdi
movl $0x28, %esi
callq 0x16750
jmp 0x44e28
leaq 0x150(%rsp), %rdi
callq 0x47650
jmp 0x454f1
movq 0x118(%rsp), %rsi
addq $0x18, %rsi
leaq 0x140(%rsp), %rdi
callq 0x47d60
jmp 0x4550c
movq 0x118(%rsp), %rdi
addq $0x18, %rdi
xorl %esi, %esi
callq 0x173a50
jmp 0x45521
movl $0x0, 0x13c(%rsp)
movl 0x13c(%rsp), %eax
movl %eax, 0x30(%rsp)
leaq 0x140(%rsp), %rdi
callq 0x1ecf0
movl %eax, 0x34(%rsp)
jmp 0x4554a
movl 0x30(%rsp), %eax
movl 0x34(%rsp), %ecx
cmpl %ecx, %eax
jge 0x45667
movl 0x13c(%rsp), %esi
leaq 0x140(%rsp), %rdi
callq 0x20270
movq %rax, 0x28(%rsp)
jmp 0x45575
movq 0x118(%rsp), %rdi
movq 0x28(%rsp), %rax
movq %rax, 0x130(%rsp)
movq 0x130(%rsp), %rax
movq %rdi, 0x130(%rax)
addq $0x18, %rdi
callq 0x1ecf0
movl %eax, 0x24(%rsp)
jmp 0x455a8
movl 0x24(%rsp), %ecx
movq 0x130(%rsp), %rax
movl %ecx, 0x138(%rax)
movq 0x130(%rsp), %rax
cmpq $0x0, 0x18(%rax)
jne 0x45625
movq 0x118(%rsp), %rdi
addq $0x18, %rdi
movq 0x130(%rsp), %rsi
callq 0x476c0
jmp 0x455e4
jmp 0x45651
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
jmp 0x45754
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
leaq 0x140(%rsp), %rdi
callq 0x476a0
jmp 0x45754
movq 0x130(%rsp), %rsi
movq 0x18(%rsi), %rdi
callq 0x3fe30
jmp 0x45638
movq 0x130(%rsp), %rsi
leaq 0x150(%rsp), %rdi
callq 0x476c0
jmp 0x4564f
jmp 0x45651
movl 0x13c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x13c(%rsp)
jmp 0x4552c
movl $0x0, 0x12c(%rsp)
movl 0x12c(%rsp), %eax
movl %eax, 0x1c(%rsp)
leaq 0x150(%rsp), %rdi
callq 0x1ecf0
movl %eax, 0x20(%rsp)
jmp 0x45690
movl 0x1c(%rsp), %eax
movl 0x20(%rsp), %ecx
cmpl %ecx, %eax
jge 0x45708
movl 0x12c(%rsp), %esi
leaq 0x150(%rsp), %rdi
callq 0x20270
movq %rax, 0x10(%rsp)
jmp 0x456b7
movq 0x10(%rsp), %rax
movq %rax, 0x120(%rsp)
movq 0x120(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x456f0
movq 0x8(%rsp), %rdi
callq 0x3ee60
movq 0x8(%rsp), %rdi
movl $0x140, %esi            # imm = 0x140
callq 0x16750
jmp 0x456f2
movl 0x12c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x12c(%rsp)
jmp 0x45672
movl $0x1, 0x2b4(%rsp)
movl $0x1, 0x224(%rsp)
leaq 0x140(%rsp), %rdi
callq 0x476a0
leaq 0x150(%rsp), %rdi
callq 0x476a0
leaq 0x1c0(%rsp), %rdi
callq 0x481e0
leaq 0x1f8(%rsp), %rdi
callq 0x42040
jmp 0x4577d
leaq 0x150(%rsp), %rdi
callq 0x476a0
leaq 0x1c0(%rsp), %rdi
callq 0x481e0
leaq 0x1f8(%rsp), %rdi
callq 0x42040
jmp 0x45799
leaq 0x288(%rsp), %rdi
callq 0x47690
movl 0x2b4(%rsp), %eax
addq $0x2b8, %rsp            # imm = 0x2B8
retq
leaq 0x288(%rsp), %rdi
callq 0x47690
movq 0x278(%rsp), %rdi
callq 0x16ca0
nopw %cs:(%rax,%rax)