// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::CreateClusterObjects(gaps::R3SurfelScene*, gaps::R3SurfelPointGraph*, gaps::R3SurfelObject*, gaps::R3SurfelNode*, double, double, int)
RNArray<R3SurfelObject *> *
CreateClusterObjects(R3SurfelScene *scene, R3SurfelPointGraph *graph, 
  R3SurfelObject *parent_object, R3SurfelNode *parent_node, 
  RNLength max_offplane_distance, RNAngle max_normal_angle,
  int min_points_per_object)
{
  // Get convenient variables
  R3SurfelTree *tree = scene->Tree();
  if (!tree) return 0;
  R3SurfelDatabase *database = tree->Database();
  if (!database) return 0;

  // Check number of points
  if (graph->NPoints() < min_points_per_object) return NULL;

  // Check parent object
  if (!parent_object) parent_object = scene->RootObject();

  // Check parent node
  if (!parent_node) parent_node = tree->RootNode();

  // Create normals
  R3Vector *normals = NULL;
  if ((max_offplane_distance > 0) || (max_normal_angle > 0)) {
    normals = CreateNormals(graph, FALSE);
  }

  // Create cluster for every point
  RNArray<R3SurfelCluster *> clusters;
  for (int i = 0; i < graph->NPoints(); i++) {
    R3SurfelPoint *point = graph->Point(i);
    R3Point position = point->Position();
    R3SurfelCluster *cluster = new R3SurfelCluster();
    cluster->parent = NULL;
    cluster->points.Insert(point);
    cluster->bbox.Reset(position, position);
    cluster->id = i;
    clusters.Insert(cluster);
  }

  // Check clusters
  if (clusters.IsEmpty()) {
    if (normals) delete [] normals;
    return NULL;  
  }

  // Create cluster pairs and add to heap
  R3SurfelClusterPair tmp;
  RNHeap<R3SurfelClusterPair *> heap(&tmp, &tmp.similarity, NULL, FALSE);;
  for (int index0 = 0; index0 < graph->NPoints(); index0++) {
    R3SurfelPoint *point0 = graph->Point(index0);
    R3SurfelCluster *cluster0 = clusters.Kth(index0);
    R3Point position0 = point0->Position();
    const R3Vector& normal0 = (normals) ? normals[index0] : R3zero_vector;
    R3Plane plane0(position0, normal0);
    for (int j = 0; j < graph->NNeighbors(index0); j++) {
      R3SurfelPoint *point1 = graph->Neighbor(index0, j);
      int index1 = graph->PointIndex(point1);
      if (index1 < index0) continue;
      R3Point position1 = point1->Position();

      // Compute plane similarity
      RNScalar plane_similarity = 1;
      if (max_offplane_distance > 0) {
        RNScalar offplane_distance = R3Distance(plane0, position1);
        if (offplane_distance > max_offplane_distance) continue;
        plane_similarity *= 1.0 - 0.9 * offplane_distance / max_offplane_distance;
      }

      // Compute normal similarity
      RNScalar normal_similarity = 1;
      if (max_normal_angle > 0) {
        if (normals) {
          const R3Vector& normal1 = normals[index1];
          RNScalar dot = fabs(normal0.Dot(normal1));
          RNAngle normal_angle = (dot < 1) ? acos(dot) : 0;
          if (normal_angle > max_normal_angle) continue;
          normal_similarity *= 1.0 - 0.9 * normal_angle / max_normal_angle;
        }
      }

      // Compute distance similarity
      RNScalar distance_similarity = 1.0;
      if (graph->MaxDistance() > 0) {
        RNScalar distance = R3Distance(position0, position1);
        distance_similarity = 1.0 - 0.99 * distance / graph->MaxDistance();
      }

      // Create pair
      R3SurfelCluster *cluster1 = clusters.Kth(index1);
      R3SurfelClusterPair *pair = new R3SurfelClusterPair();
      pair->clusters[0] = cluster0;
      pair->clusters[1] = cluster1;
      pair->similarity = distance_similarity * normal_similarity * plane_similarity;
      heap.Push(pair);
    }
  }

  // Check cluster pairs
  if (heap.IsEmpty()) {
    for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
    if (normals) delete [] normals;
    return NULL;
  }

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

    // Get clusters
    R3SurfelCluster *cluster0 = pair->clusters[0];
    R3SurfelCluster *cluster1 = pair->clusters[1];
    while (cluster0->parent) cluster0 = cluster0->parent;
    while (cluster1->parent) cluster1 = cluster1->parent;
    if (cluster0 == cluster1) continue;

    // Merge clusters
    cluster0->points.Append(cluster1->points);
    cluster0->bbox.Union(cluster1->bbox);
    cluster1->parent = cluster0;
    cluster1->points.Empty(TRUE);
    cluster1->bbox = R3null_box;

    // Delete pair
    delete pair;
  }

  // Create array of objects
  RNArray<R3SurfelObject *> *objects = new RNArray<R3SurfelObject *>();
  if (!objects) {
    RNFail("Unable to create array of objects\n");
    for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
    if (normals) delete [] normals;
    return NULL;
  }

  // Create objects with copies of surfels
  for (int i = 0; i < clusters.NEntries(); i++) {
    R3SurfelCluster *cluster = clusters.Kth(i);

    // Check cluster
    if (cluster->points.NEntries() < min_points_per_object) { delete cluster; continue; }
    if (cluster->parent) { delete cluster; continue; }

    // Create surfels
    R3Point origin = cluster->bbox.Centroid();
    R3Surfel *surfels = new R3Surfel [ cluster->points.NEntries() ];
    for (int j = 0; j < cluster->points.NEntries(); j++) {
      R3SurfelPoint *point = cluster->points.Kth(j);
      R3SurfelBlock *block = point->Block();
      const R3Surfel *surfel = point->Surfel();
      RNCoord x = surfel->X() + block->PositionOrigin().X() - origin.X();
      RNCoord y = surfel->Y() + block->PositionOrigin().Y() - origin.Y();
      RNCoord z = surfel->Z() + block->PositionOrigin().Z() - origin.Z();
      surfels[j].SetPosition(x, y, z);
      surfels[j].SetColor(surfel->Color());
      surfels[j].SetAerial(surfel->IsAerial());
    }

    // Create block
    R3SurfelBlock *block = new R3SurfelBlock(surfels, cluster->points.NEntries(), origin);
    if (!block) {
      RNFail("Unable to create node\n");
      for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
      if (normals) delete [] normals;
      delete [] surfels;
      return NULL;
    }

    // Delete surfels
    delete [] surfels;

    // Create node
    char node_name[256];
    sprintf(node_name, "O%d\n", objects->NEntries());
    R3SurfelNode *node = new R3SurfelNode(node_name);
    if (!node) {
      RNFail("Unable to create node\n");
      for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
      if (normals) delete [] normals;
      delete block;
      return NULL;
    }

    // Create object
    char object_name[256];
    sprintf(object_name, "O%d\n", objects->NEntries());
    R3SurfelObject *object = new R3SurfelObject(object_name);
    if (!object) {
      RNFail("Unable to create object\n");
      for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
      if (normals) delete [] normals;
      delete block;
      delete node;
      return NULL;
    }
     
    // Insert everything
    block->UpdateProperties();
    database->InsertBlock(block);
    node->InsertBlock(block);
    tree->InsertNode(node, parent_node);
    object->InsertNode(node);
    scene->InsertObject(object, parent_object);
    objects->Insert(object);

    // Delete cluster
    delete cluster;

    // Print debug statement
    printf("    %d %d\n", i, block->NSurfels());
  }
  
  // Delete normals
  delete [] normals;

  // Return objects
  return objects;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2f8, %rsp            # imm = 0x2F8
movsd %xmm1, 0x40(%rsp)
movsd %xmm0, 0x38(%rsp)
movq %rsi, %r14
movq 0x8(%rdi), %rsi
testq %rsi, %rsi
je 0x2993d
movq 0x10(%rsi), %r9
testq %r9, %r9
je 0x2993d
cmpl %r8d, 0x18(%r14)
jge 0x29955
xorl %r12d, %r12d
movq %r12, %rax
addq $0x2f8, %rsp            # imm = 0x2F8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %rdx, %rdx
jne 0x29961
movq 0x10(%rdi), %rax
movq (%rax), %rdx
testq %rcx, %rcx
jne 0x2996d
movq 0x18(%rsi), %rax
movq (%rax), %rcx
movl %r8d, 0x4c(%rsp)
xorpd %xmm0, %xmm0
movsd 0x38(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movq %rdi, 0x78(%rsp)
movq %r9, 0x90(%rsp)
movq %rcx, 0x88(%rsp)
movq %rdx, 0x70(%rsp)
movq %rsi, 0x80(%rsp)
ja 0x299b4
movsd 0x40(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x299b4
xorl %ebx, %ebx
jmp 0x299c1
movq %r14, %rdi
xorl %esi, %esi
callq 0x26e3b
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0xa9ca8
movq %r14, 0x8(%rsp)
cmpl $0x0, 0x18(%r14)
movq %rbx, 0x18(%rsp)
jle 0x29ae8
xorl %ebx, %ebx
leaq 0x1f0(%rsp), %rbp
xorl %r12d, %r12d
movq 0x8(%rsp), %rcx
movq 0x10(%rcx), %r13
movq (%r13,%rbx), %rax
movq 0x8(%r13,%rbx), %rcx
xorps %xmm0, %xmm0
cvtss2sd (%rcx), %xmm0
addsd 0x10(%rax), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x4(%rcx), %xmm1
addsd 0x18(%rax), %xmm1
cvtss2sd 0x8(%rcx), %xmm2
addsd 0x20(%rax), %xmm2
movq %rbp, %rdi
callq 0x83dc2
movl $0x58, %edi
callq 0x134e0
movq %rax, %r14
movq %r12, 0x30(%rsp)
movq %rbp, %r12
xorpd %xmm0, %xmm0
movapd %xmm0, 0x40(%rax)
movapd %xmm0, 0x30(%rax)
movapd %xmm0, 0x20(%rax)
movapd %xmm0, 0x10(%rax)
movapd %xmm0, (%rax)
movq $0x0, 0x50(%rax)
leaq 0x8(%rax), %rbp
movq %rbp, %rdi
callq 0xa9ca8
movq %r14, %r15
addq $0x18, %r15
movq %r15, %rdi
callq 0x6d310
addq %rbx, %r13
movq $0x0, (%r14)
movl 0x14(%r14), %edx
movq %rbp, %rdi
movq %r13, %rsi
callq 0xa9d3e
movq %r12, %rbp
movq 0x30(%rsp), %r12
movq %r15, %rdi
movq %rbp, %rsi
movq %rbp, %rdx
callq 0x6e11e
movl %r12d, 0x50(%r14)
movl 0x2c(%rsp), %edx
leaq 0x20(%rsp), %rdi
movq %r14, %rsi
callq 0xa9d3e
incq %r12
movq 0x8(%rsp), %rcx
movslq 0x18(%rcx), %rax
addq $0x10, %rbx
cmpq %rax, %r12
jl 0x299f2
testl %eax, %eax
setg %al
movq 0x18(%rsp), %rbx
jmp 0x29aea
xorl %eax, %eax
cmpl $0x0, 0x2c(%rsp)
je 0x2a1dd
xorpd %xmm0, %xmm0
movapd %xmm0, 0xb0(%rsp)
movupd %xmm0, 0xc8(%rsp)
movupd %xmm0, 0xd4(%rsp)
movabsq $-0xfffffff0, %rcx      # imm = 0xFFFFFFFF00000010
movq %rcx, 0xc0(%rsp)
testb %al, %al
movq 0x8(%rsp), %r12
je 0x2a170
xorpd %xmm1, %xmm1
movsd 0x40(%rsp), %xmm0
ucomisd %xmm1, %xmm0
seta %al
testq %rbx, %rbx
setne %cl
andb %al, %cl
movb %cl, 0x17(%rsp)
xorl %r15d, %r15d
movq 0x10(%r12), %rax
movq %r15, %r13
shlq $0x4, %r13
movq 0x20(%rsp), %rcx
movq (%rcx,%r15,8), %rbx
movq (%rax,%r13), %rcx
movq 0x8(%rax,%r13), %rax
xorps %xmm0, %xmm0
cvtss2sd (%rax), %xmm0
addsd 0x10(%rcx), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x4(%rax), %xmm1
addsd 0x18(%rcx), %xmm1
xorps %xmm2, %xmm2
cvtss2sd 0x8(%rax), %xmm2
addsd 0x20(%rcx), %xmm2
leaq 0xf0(%rsp), %rdi
callq 0x83dc2
leaq (%r15,%r15,2), %rax
movq 0x18(%rsp), %rcx
leaq (%rcx,%rax,8), %rdx
movq %rdx, 0x98(%rsp)
testq %rcx, %rcx
jne 0x29bc5
leaq 0xbb5f3(%rip), %rdx     # 0xe51b8
leaq 0x1f0(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x82942
movq 0x68(%r12), %rax
cmpl $0x0, 0xc(%rax,%r13)
jle 0x29dd2
xorl %r14d, %r14d
movq (%rax,%r13), %rcx
movq (%rcx,%r14,8), %rcx
movq %rcx, %rbp
subq 0x10(%r12), %rbp
shrq $0x4, %rbp
movslq %ebp, %rdx
cmpq %rdx, %r15
jg 0x29dc1
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
xorps %xmm0, %xmm0
cvtss2sd (%rcx), %xmm0
addsd 0x10(%rax), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x4(%rcx), %xmm1
addsd 0x18(%rax), %xmm1
xorps %xmm2, %xmm2
cvtss2sd 0x8(%rcx), %xmm2
addsd 0x20(%rax), %xmm2
leaq 0x50(%rsp), %rdi
callq 0x83dc2
movsd 0x38(%rsp), %xmm0
ucomisd 0xb3735(%rip), %xmm0    # 0xdd388
movsd 0xb34ed(%rip), %xmm1    # 0xdd148
jbe 0x29c97
leaq 0x50(%rsp), %rdi
leaq 0x1f0(%rsp), %rsi
callq 0x500ce
movapd %xmm0, %xmm1
movsd 0x38(%rsp), %xmm0
ucomisd %xmm0, %xmm1
mulsd 0xb3eab(%rip), %xmm1    # 0xddb30
divsd %xmm0, %xmm1
addsd 0xb34b7(%rip), %xmm1    # 0xdd148
ja 0x29db7
movsd 0xb34a9(%rip), %xmm2    # 0xdd148
cmpb $0x0, 0x17(%rsp)
movsd %xmm1, 0x30(%rsp)
je 0x29d10
movslq %ebp, %rax
leaq (%rax,%rax,2), %rax
movq 0x18(%rsp), %rcx
leaq (%rcx,%rax,8), %rsi
movq 0x98(%rsp), %rdi
callq 0x84ae2
andpd 0xb36ff(%rip), %xmm0    # 0xdd3d0
xorpd %xmm2, %xmm2
movsd 0xb346b(%rip), %xmm1    # 0xdd148
ucomisd %xmm0, %xmm1
jbe 0x29cec
callq 0x13490
movapd %xmm0, %xmm2
movsd 0x40(%rsp), %xmm0
ucomisd %xmm0, %xmm2
mulsd 0xb3e32(%rip), %xmm2    # 0xddb30
divsd %xmm0, %xmm2
addsd 0xb343e(%rip), %xmm2    # 0xdd148
ja 0x29db7
movsd %xmm2, 0xa8(%rsp)
movq 0x8(%rsp), %r12
movsd 0x78(%r12), %xmm0
ucomisd 0xb365b(%rip), %xmm0    # 0xdd388
movsd 0xb3413(%rip), %xmm0    # 0xdd148
jbe 0x29d60
leaq 0xf0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x4ff14
mulsd 0xb3de7(%rip), %xmm0    # 0xddb38
divsd 0x78(%r12), %xmm0
addsd 0xb33e8(%rip), %xmm0    # 0xdd148
movsd %xmm0, 0xa0(%rsp)
movq 0x20(%rsp), %rax
movslq %ebp, %rcx
movq (%rax,%rcx,8), %r12
movl $0x18, %edi
callq 0x134e0
movsd 0x30(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
movq %rbx, (%rax)
movq %r12, 0x8(%rax)
mulsd 0xa0(%rsp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rax)
leaq 0xb0(%rsp), %rdi
movq %rax, %rsi
callq 0x2a9a6
movq 0x8(%rsp), %r12
movq 0x68(%r12), %rax
incq %r14
movslq 0xc(%rax,%r13), %rcx
cmpq %rcx, %r14
jl 0x29bee
incq %r15
movslq 0x18(%r12), %rax
cmpq %rax, %r15
jl 0x29b53
cmpl $0x0, 0xb8(%rsp)
je 0x2a170
cmpl $0x0, 0xb8(%rsp)
je 0x29ea4
leaq 0x10abc2(%rip), %r14    # 0x1349c8
leaq 0x8(%r14), %r15
addq $0x20, %r14
leaq 0xb0(%rsp), %rdi
callq 0x2aaba
movq %rax, %r12
movq (%rax), %rcx
movq 0x8(%rax), %rax
movq %rcx, %rbx
movq (%rcx), %rcx
testq %rcx, %rcx
jne 0x29e25
movq %rax, %r13
movq (%rax), %rax
testq %rax, %rax
jne 0x29e30
cmpq %r13, %rbx
je 0x29e96
leaq 0x8(%rbx), %rdi
leaq 0x8(%r13), %rbp
movq %rbp, %rsi
callq 0xa9ffa
leaq 0x18(%rbx), %rdi
leaq 0x18(%r13), %rsi
callq 0x6de0c
movq %rbx, (%r13)
movq %rbp, %rdi
movl $0x1, %esi
callq 0xa9f08
leaq 0x20(%r13), %rdi
movq %r15, %rsi
callq 0x8412a
addq $0x38, %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0x8412a
movl $0x18, %esi
movq %r12, %rdi
callq 0x134f0
cmpl $0x0, 0xb8(%rsp)
jne 0x29e0e
movl $0x10, %edi
callq 0x134e0
movq %rax, %r12
movq %rax, %rdi
callq 0xa9ca8
movq 0x18(%rsp), %rbx
cmpl $0x0, 0x2c(%rsp)
jle 0x2a1bc
xorl %r14d, %r14d
movq %r12, 0x30(%rsp)
movq 0x20(%rsp), %rax
movq (%rax,%r14,8), %rbp
leaq 0x8(%rbp), %r15
movl 0x4c(%rsp), %eax
cmpl %eax, 0x14(%rbp)
jge 0x29ef5
leaq 0x18(%rbp), %rdi
callq 0x6e174
movq %r15, %rdi
jmp 0x29f0f
movq %r15, 0x8(%rsp)
cmpq $0x0, (%rbp)
je 0x29f33
leaq 0x18(%rbp), %rdi
callq 0x6e174
movq 0x8(%rsp), %rdi
callq 0xa9d12
movl $0x58, %esi
movq %rbp, %rdi
callq 0x134f0
incq %r14
movslq 0x2c(%rsp), %rax
cmpq %rax, %r14
jl 0x29ed1
jmp 0x2a1bc
leaq 0x18(%rbp), %rsi
leaq 0x50(%rsp), %rdi
movq %rsi, 0x38(%rsp)
callq 0x6db6a
movslq 0x14(%rbp), %r15
movq %r15, %rax
movl $0x30, %ecx
mulq %rcx
movq %rax, %rbx
movq $-0x1, %rax
cmovoq %rax, %rbx
movq %rbx, %rdi
callq 0x13030
movq %rax, %r13
testl %r15d, %r15d
je 0x29f90
shlq $0x4, %r15
leaq (%r15,%r15,2), %r15
xorl %r12d, %r12d
leaq (%r12,%r13), %rdi
callq 0x2b118
addq $0x30, %r12
cmpq %r12, %r15
jne 0x29f7e
cmpl $0x0, 0x14(%rbp)
jle 0x2a026
movapd 0x50(%rsp), %xmm0
movsd 0x60(%rsp), %xmm1
movq %r13, %rax
addq $0x2f, %rax
xorl %ecx, %ecx
movq 0x8(%rbp), %rdx
movq (%rdx,%rcx,8), %rdx
movq 0x8(%rdx), %rsi
xorps %xmm2, %xmm2
cvtss2sd 0x8(%rsi), %xmm2
movq (%rdx), %rdx
addsd 0x20(%rdx), %xmm2
subsd %xmm1, %xmm2
cvtsd2ss %xmm2, %xmm2
cvtps2pd (%rsi), %xmm3
movupd 0x10(%rdx), %xmm4
addpd %xmm3, %xmm4
subpd %xmm0, %xmm4
cvtpd2ps %xmm4, %xmm3
movlpd %xmm3, -0x2f(%rax)
movss %xmm2, -0x27(%rax)
movb 0x2c(%rsi), %dl
movb %dl, -0x3(%rax)
movb 0x2d(%rsi), %dl
movb %dl, -0x2(%rax)
movb 0x2e(%rsi), %dl
movb %dl, -0x1(%rax)
movb 0x2f(%rsi), %dl
andb $0x2, %dl
movb (%rax), %sil
andb $-0x3, %sil
orb %dl, %sil
movb %sil, (%rax)
incq %rcx
movslq 0x14(%rbp), %rdx
addq $0x30, %rax
cmpq %rdx, %rcx
jl 0x29faf
movl $0xc8, %edi
callq 0x134e0
movq 0x30(%rsp), %r12
leaq 0x1f0(%rsp), %r15
movq %rax, %rbx
movl 0x14(%rbp), %edx
xorpd %xmm0, %xmm0
movq %rax, %rdi
movq %r13, %rsi
leaq 0x50(%rsp), %rcx
callq 0x2c262
movq %r13, %rdi
callq 0x13680
movl 0xc(%r12), %edx
movq %r15, %rdi
leaq 0xb3c6d(%rip), %rsi     # 0xddcdb
xorl %eax, %eax
callq 0x130e0
movl $0xd0, %edi
callq 0x134e0
movq %rax, %r13
movq %rax, %rdi
movq %r15, %rsi
callq 0x3715c
movl 0xc(%r12), %edx
leaq 0xf0(%rsp), %rdi
leaq 0xb3c3a(%rip), %rsi     # 0xddcdb
xorl %eax, %eax
callq 0x130e0
movl $0xf8, %edi
callq 0x134e0
movq %rax, %r15
movq %rax, %rdi
leaq 0xf0(%rsp), %rsi
callq 0x16b68
movq %rbx, %rdi
callq 0x2dfb8
movq 0x90(%rsp), %rdi
movq (%rdi), %rax
movq %rbx, %rsi
callq *0x10(%rax)
movq (%r13), %rax
movq %r13, %rdi
movq %rbx, %rsi
callq *0x28(%rax)
movq 0x80(%rsp), %rdi
movq %r13, %rsi
movq 0x88(%rsp), %rdx
callq 0x38f02
movq %r15, %rdi
movq %r13, %rsi
callq 0x17dd6
movq 0x78(%rsp), %rdi
movq (%rdi), %rax
movq %r15, %rsi
movq 0x70(%rsp), %rdx
callq *0x18(%rax)
movl 0xc(%r12), %edx
movq %r12, %rdi
movq %r15, %rsi
callq 0xa9d3e
movq 0x38(%rsp), %rdi
callq 0x6e174
movq 0x8(%rsp), %rdi
callq 0xa9d12
movl $0x58, %esi
movq %rbp, %rdi
callq 0x134f0
movl 0x8(%rbx), %edx
leaq 0xb3b84(%rip), %rdi     # 0xddce0
movl %r14d, %esi
xorl %eax, %eax
callq 0x13070
movq 0x18(%rsp), %rbx
jmp 0x29f21
cmpl $0x0, 0x2c(%rsp)
jle 0x2a1b4
xorl %r14d, %r14d
movq 0x20(%rsp), %rax
movq (%rax,%r14,8), %rbx
testq %rbx, %rbx
je 0x2a19a
leaq 0x18(%rbx), %rdi
callq 0x6e174
leaq 0x8(%rbx), %rdi
callq 0xa9d12
movl $0x58, %esi
movq %rbx, %rdi
callq 0x134f0
incq %r14
movslq 0x2c(%rsp), %rax
cmpq %rax, %r14
jl 0x2a17a
xorl %r12d, %r12d
movq 0x18(%rsp), %rbx
testq %rbx, %rbx
je 0x2a1c9
movq %rbx, %rdi
callq 0x13680
movq 0xb0(%rsp), %rdi
testq %rdi, %rdi
je 0x2a1ed
callq 0x13680
jmp 0x2a1ed
testq %rbx, %rbx
je 0x2a1ea
movq %rbx, %rdi
callq 0x13680
xorl %r12d, %r12d
leaq 0x20(%rsp), %rdi
callq 0xa9d12
jmp 0x29940
movq %rax, 0x8(%rsp)
movl $0x10, %esi
movq %r12, %rdi
jmp 0x2a23d
jmp 0x2a29a
movq %rax, 0x8(%rsp)
movl $0xf8, %esi
movq %r15, %rdi
jmp 0x2a23d
movq %rax, 0x8(%rsp)
movl $0xd0, %esi
movq %r13, %rdi
jmp 0x2a23d
jmp 0x2a29a
movq %rax, 0x8(%rsp)
movl $0xc8, %esi
movq %rbx, %rdi
callq 0x134f0
jmp 0x2a29f
jmp 0x2a29a
jmp 0x2a29a
jmp 0x2a29a
jmp 0x2a29a
jmp 0x2a29a
jmp 0x2a29a
jmp 0x2a29a
jmp 0x2a29a
movq %rax, 0x8(%rsp)
movq %r13, %rdi
movq %rbx, %rsi
callq 0x139b0
jmp 0x2a29f
jmp 0x2a291
movq %rax, 0x8(%rsp)
jmp 0x2a27c
movq %rax, 0x8(%rsp)
movq %rbp, %rdi
callq 0xa9d12
movl $0x58, %esi
movq %r14, %rdi
callq 0x134f0
jmp 0x2a2b1
jmp 0x2a29a
jmp 0x2a29a
jmp 0x2a29a
movq %rax, 0x8(%rsp)
jmp 0x2a2b1
jmp 0x2a29a
movq %rax, 0x8(%rsp)
movq 0xb0(%rsp), %rdi
testq %rdi, %rdi
je 0x2a2b1
callq 0x13680
leaq 0x20(%rsp), %rdi
callq 0xa9d12
movq 0x8(%rsp), %rdi
callq 0x138b0