// File: tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: FindFurthestVertex(gaps::R3Mesh*, gaps::RNArray<gaps::R3MeshVertex*> const&, VertexData*)
static R3MeshVertex *
FindFurthestVertex(R3Mesh *mesh, const RNArray<R3MeshVertex *>& seeds, VertexData *vertex_data)
{
  // Initialize vertex data
  for (int i = 0; i < mesh->NVertices(); i++) {
    VertexData *data = &vertex_data[i];
    data->distance = FLT_MAX;
    data->closest_seed = NULL;
    data->heappointer = NULL;
  }

  // Initialize heap
  VertexData tmp;
  RNHeap<VertexData *> heap(&tmp, &(tmp.distance), &(tmp.heappointer));
  for (int i = 0; i < seeds.NEntries(); i++) {
    R3MeshVertex *vertex = seeds.Kth(i);
    VertexData *data = &vertex_data[mesh->VertexID(vertex)];
    data->closest_seed = vertex;
    data->distance = 0;
    heap.Push(data);
  }

  // Iteratively pop off heap until find furthest vertex
  R3MeshVertex *vertex = NULL;
  while (!heap.IsEmpty()) {
    VertexData *data = heap.Pop();
    vertex = data->vertex;
    for (int j = 0; j < mesh->VertexValence(vertex); j++) {
      R3MeshEdge *edge = mesh->EdgeOnVertex(vertex, j);
      R3MeshVertex *neighbor_vertex = mesh->VertexAcrossEdge(edge, vertex);
      VertexData *neighbor_data = (VertexData *) mesh->VertexData(neighbor_vertex);
      RNScalar old_distance = neighbor_data->distance;
      RNScalar new_distance = mesh->EdgeLength(edge) + data->distance;
      if (new_distance < old_distance) {
        neighbor_data->distance = new_distance;
        neighbor_data->closest_seed = data->closest_seed;
        if (old_distance < FLT_MAX) heap.Update(neighbor_data);
        else heap.Push(neighbor_data);
      }
    }
  }

  // Return furthest vertex
  return vertex;
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x130(%rsp)
movq %rsi, 0x128(%rsp)
movq %rdx, 0x120(%rsp)
movl $0x0, 0x11c(%rsp)
movl 0x11c(%rsp), %eax
movl %eax, 0x4c(%rsp)
movq 0x130(%rsp), %rdi
callq 0x1b460
movl %eax, %ecx
movl 0x4c(%rsp), %eax
cmpl %ecx, %eax
jge 0x1a1b6
movq 0x120(%rsp), %rax
movslq 0x11c(%rsp), %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x110(%rsp)
movq 0x110(%rsp), %rax
movsd 0x12fe8d(%rip), %xmm0   # 0x14a008
movsd %xmm0, 0x8(%rax)
movq 0x110(%rsp), %rax
movq $0x0, 0x10(%rax)
movq 0x110(%rsp), %rax
movq $0x0, 0x18(%rax)
movl 0x11c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x11c(%rsp)
jmp 0x1a12a
leaq 0xf0(%rsp), %rdx
addq $0x8, %rdx
leaq 0xf0(%rsp), %rcx
addq $0x18, %rcx
leaq 0xb8(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
movl $0x1, %r8d
callq 0x1e670
movl $0x0, 0xb4(%rsp)
movl 0xb4(%rsp), %eax
movl %eax, 0x48(%rsp)
movq 0x128(%rsp), %rdi
callq 0x1b2f0
movl %eax, %ecx
movl 0x48(%rsp), %eax
cmpl %ecx, %eax
jge 0x1a2ea
movq 0x128(%rsp), %rdi
movl 0xb4(%rsp), %esi
callq 0x1e590
movq %rax, 0xa8(%rsp)
movq 0x120(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x130(%rsp), %rdi
movq 0xa8(%rsp), %rsi
callq 0x1b320
movl %eax, %ecx
movq 0x40(%rsp), %rax
movslq %ecx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0xa0(%rsp)
movq 0xa8(%rsp), %rcx
movq 0xa0(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0xa0(%rsp), %rax
movq $0x0, 0x8(%rax)
movq 0xa0(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x1e710
jmp 0x1a2ac
jmp 0x1a2ae
movl 0xb4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb4(%rsp)
jmp 0x1a1f4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x98(%rsp)
movl %eax, 0x94(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x1ec70
jmp 0x1a4f1
movq $0x0, 0x88(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x1e930
movl %eax, 0x3c(%rsp)
jmp 0x1a309
movl 0x3c(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x1a31e
jmp 0x1a4cc
leaq 0xb8(%rsp), %rdi
callq 0x1e950
movq %rax, 0x30(%rsp)
jmp 0x1a332
movq 0x30(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x88(%rsp)
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
movl %eax, 0x2c(%rsp)
movq 0x130(%rsp), %rdi
movq 0x88(%rsp), %rsi
callq 0x1e5e0
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jge 0x1a4c7
movq 0x130(%rsp), %rdi
movq 0x88(%rsp), %rsi
movl 0x7c(%rsp), %edx
callq 0x1ea60
movq %rax, 0x20(%rsp)
jmp 0x1a3a5
movq 0x20(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0x130(%rsp), %rdi
movq 0x70(%rsp), %rsi
movq 0x88(%rsp), %rdx
callq 0x1ea90
movq %rax, 0x18(%rsp)
jmp 0x1a3d0
movq 0x18(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x130(%rsp), %rdi
movq 0x68(%rsp), %rsi
callq 0x1eae0
movq %rax, 0x10(%rsp)
jmp 0x1a3f3
movq 0x10(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rax
movsd 0x8(%rax), %xmm0
movsd %xmm0, 0x58(%rsp)
movq 0x130(%rsp), %rdi
movq 0x70(%rsp), %rsi
callq 0x1eb00
movsd %xmm0, 0x8(%rsp)
jmp 0x1a427
movsd 0x8(%rsp), %xmm0
movq 0x80(%rsp), %rax
addsd 0x8(%rax), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x50(%rsp), %xmm1
movsd 0x58(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1a4b5
movsd 0x50(%rsp), %xmm0
movq 0x60(%rsp), %rax
movsd %xmm0, 0x8(%rax)
movq 0x80(%rsp), %rax
movq 0x10(%rax), %rcx
movq 0x60(%rsp), %rax
movq %rcx, 0x10(%rax)
movsd 0x12fb89(%rip), %xmm0   # 0x14a008
ucomisd 0x58(%rsp), %xmm0
jbe 0x1a49d
movq 0x60(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x1eb70
jmp 0x1a49b
jmp 0x1a4b3
movq 0x60(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x1e710
jmp 0x1a4b1
jmp 0x1a4b3
jmp 0x1a4b5
jmp 0x1a4b7
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x1a35a
jmp 0x1a2f6
movq 0x88(%rsp), %rax
movq %rax, (%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x1ec70
movq (%rsp), %rax
addq $0x138, %rsp            # imm = 0x138
retq
movq 0x98(%rsp), %rdi
callq 0xf8a0
nop