// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/apps/scn2cam/scn2cam.cpp
// Function: FindIndexOfFurthestPointAlongPath(gaps::R2Grid const&, int, int*, int*)
static int
FindIndexOfFurthestPointAlongPath(const R2Grid& grid, int start_index,
  int *path = NULL, int *path_size = NULL)
{
  // Initialize Dijksra bookkeeping
  R2Grid parent_grid(grid), distance_grid(grid);
  parent_grid.Clear(R2_GRID_UNKNOWN_VALUE);
  distance_grid.Clear(FLT_MAX);
  const RNScalar *grid_values = distance_grid.GridValues();
  int neighbor_index, ix, iy;
  int end_index = -1;
  
  // Compute shortest path to all nonzero points
  RNHeap<const RNScalar *> heap(0);
  distance_grid.SetGridValue(start_index, 0);
  parent_grid.SetGridValue(start_index, start_index);
  heap.Push(grid_values + start_index);
  while (!heap.IsEmpty()) {
    const RNScalar *grid_entry = heap.Pop();
    int grid_index = grid_entry - grid_values;
    end_index = grid_index;
    grid.IndexToIndices(grid_index, ix, iy);
    for (int dx = -1; dx <= 1; dx++) {
      int nx = ix + dx;
      if ((nx < 0) || (nx > grid.XResolution()-1)) continue;
      for (int dy = -1; dy <= 1; dy++) {
        int ny = iy + dy;
        if ((ny < 0) || (ny > grid.YResolution()-1)) continue;
        grid.IndicesToIndex(nx, ny, neighbor_index);
        if (neighbor_index == grid_index) continue;
        if (grid.GridValue(neighbor_index) != R2_GRID_UNKNOWN_VALUE) {
          RNScalar d = distance_grid.GridValue(grid_index) + sqrt(dx*dx + dy*dy);
          RNScalar old_d = distance_grid.GridValue(neighbor_index);
          if (d < old_d) {
            distance_grid.SetGridValue(neighbor_index, d);
            parent_grid.SetGridValue(neighbor_index, grid_index);
            if (old_d == FLT_MAX) heap.Push(grid_values + neighbor_index);
            else heap.Update(grid_values + neighbor_index);
          }
        }
      }
    }
  }

  // Fill in path
  if (path && path_size) {
    // Construct path backwards
    int count = 0;
    path[count++] = end_index;
    while (path[count-1] != start_index) {
      path[count] = (int) parent_grid.GridValue(path[count-1]);
      count++;
    }

    // Reverse order of path
    for (int i = 0; i < count/2; i++) {
      int swap = path[i];
      path[i] = path[count-1-i];
      path[count-1-i] = swap;
    }

    // Fill in path size
    *path_size = count;
  }

  // Return last visited index
  return end_index;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x218, %rsp            # imm = 0x218
movq %rcx, %rbx
movq %rdx, %r14
movl %esi, %ebp
movq %rdi, %r12
leaq 0x78(%rsp), %rdi
movq %r12, %rsi
callq 0x88ce0
leaq 0x148(%rsp), %rdi
movq %r12, %rsi
callq 0x88ce0
leaq 0x78(%rsp), %rdi
movsd 0xc59d5(%rip), %xmm0    # 0xf20a0
callq 0x8a404
leaq 0x148(%rsp), %rdi
movsd 0xc59d8(%rip), %xmm0    # 0xf20b8
callq 0x8a404
movq 0x200(%rsp), %rdx
xorpd %xmm0, %xmm0
leaq 0x40(%rsp), %rdi
movapd %xmm0, (%rdi)
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
movq %rax, 0x10(%rdi)
movupd %xmm0, 0x18(%rdi)
xorl %eax, %eax
movq %rax, 0x28(%rdi)
movl $0x1, 0x30(%rdi)
movslq %ebp, %rcx
movq %rax, (%rdx,%rcx,8)
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movq 0x130(%rsp), %rax
movsd %xmm0, (%rax,%rcx,8)
movl %ecx, %eax
movq %rdx, 0x18(%rsp)
leaq (%rdx,%rax,8), %rsi
callq 0x2da6c
movl %ebp, 0xc(%rsp)
movq %r14, 0x20(%rsp)
movq %rbx, 0x28(%rsp)
cmpl $0x0, 0x48(%rsp)
je 0x2c8b1
leaq 0x40(%rsp), %rdi
callq 0x2db80
movq %rax, %rcx
subq 0x18(%rsp), %rcx
shrq $0x3, %rcx
movl %ecx, %eax
cltd
idivl 0xc8(%r12)
movl %eax, %ebx
movl %edx, 0x10(%rsp)
movq %rcx, %r13
movslq %ecx, %rcx
movq %rcx, 0x38(%rsp)
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd %xmm0, 0x30(%rsp)
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl %ebp, %r14d
addl 0x10(%rsp), %r14d
js 0x2c899
cmpl 0xc0(%r12), %r14d
jge 0x2c899
movl %ebp, %eax
imull %ebp, %eax
movl %eax, 0x14(%rsp)
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
movl %ebx, %eax
addl %r15d, %eax
js 0x2c88c
cmpl 0xc4(%r12), %eax
jge 0x2c88c
imull 0xc8(%r12), %eax
addl %r14d, %eax
cmpl %r13d, %eax
je 0x2c88c
movq 0xb8(%r12), %rcx
cltq
movsd (%rcx,%rax,8), %xmm0
ucomisd 0xc588e(%rip), %xmm0    # 0xf20a0
jne 0x2c816
jnp 0x2c88c
movl %r15d, %ecx
imull %r15d, %ecx
addl 0x14(%rsp), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movq 0x200(%rsp), %rcx
sqrtsd %xmm0, %xmm0
movq 0x38(%rsp), %rdx
addsd (%rcx,%rdx,8), %xmm0
movsd (%rcx,%rax,8), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2c88c
movsd %xmm0, (%rcx,%rax,8)
movq 0x130(%rsp), %rcx
movsd 0x30(%rsp), %xmm0
movsd %xmm0, (%rcx,%rax,8)
ucomisd 0xc584f(%rip), %xmm1    # 0xf20b8
movq 0x18(%rsp), %rcx
leaq (%rcx,%rax,8), %rsi
jne 0x2c882
jp 0x2c882
leaq 0x40(%rsp), %rdi
callq 0x2da6c
jmp 0x2c88c
leaq 0x40(%rsp), %rdi
callq 0x2dc26
incl %r15d
cmpl $0x2, %r15d
jne 0x2c7cd
incl %ebp
cmpl $0x2, %ebp
jne 0x2c7a2
cmpl $0x0, 0x48(%rsp)
jne 0x2c75e
jmp 0x2c8b7
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
movq 0x20(%rsp), %r10
testq %r10, %r10
sete %al
movq 0x28(%rsp), %r9
testq %r9, %r9
sete %cl
orb %al, %cl
jne 0x2c931
movl %r13d, (%r10)
movl $0x1, %eax
movl 0xc(%rsp), %esi
cmpl %esi, %r13d
je 0x2c92e
movl $0x1, %eax
movq 0x130(%rsp), %rcx
movl %r13d, %edx
movslq %edx, %rdx
cvttsd2si (%rcx,%rdx,8), %edx
movl %edx, (%r10,%rax,4)
incq %rax
cmpl %esi, %edx
jne 0x2c8f2
leal -0x1(%rax), %ecx
movslq %ecx, %rcx
leaq (%r10,%rcx,4), %rcx
movl %eax, %edx
shrl %edx
xorl %esi, %esi
movl (%r10,%rsi,4), %edi
movl (%rcx), %r8d
movl %r8d, (%r10,%rsi,4)
movl %edi, (%rcx)
incq %rsi
addq $-0x4, %rcx
cmpq %rsi, %rdx
jne 0x2c915
movl %eax, (%r9)
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x2c940
callq 0x22bf0
leaq 0x148(%rsp), %rdi
callq 0x88eb8
leaq 0x78(%rsp), %rdi
callq 0x88eb8
movl %r13d, %eax
addq $0x218, %rsp            # imm = 0x218
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x2c97a
movq %rax, %rbx
jmp 0x2c999
movq %rax, %rbx
jmp 0x2c98c
jmp 0x2c97a
movq %rax, %rbx
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x2c98c
callq 0x22bf0
leaq 0x148(%rsp), %rdi
callq 0x88eb8
leaq 0x78(%rsp), %rdi
callq 0x88eb8
movq %rbx, %rdi
callq 0x23090
nop