// File: tomfunkhouser[P]gaps/apps/pfm2pfm/pfm2pfm.cpp
// Function: Delta(gaps::R2Grid*, int, int)
RNScalar 
Delta(R2Grid *grid, int x, int y)
{
  // Check value
  RNScalar value = grid->GridValue(x, y);
  if (value == R2_GRID_UNKNOWN_VALUE) return R2_GRID_UNKNOWN_VALUE;

  // Find sum of neighbor values
  int neighbor_count = 0;
  RNScalar neighbor_sum = 0;
  RNScalar neighbor_minimum = FLT_MAX;
  for (int dy = -1; dy <= 1; dy++) {
    for (int dx = -1; dx <= 1; dx++) {
      if ((dx == 0) && (dy == 0)) continue;
      int i = x + dx;
      if ((i < 0) || (i >= grid->XResolution())) continue;
      int j = y + dy;
      if ((j < 0) || (j >= grid->YResolution())) continue;
      RNScalar neighbor_value = grid->GridValue(i, j);
      if (neighbor_value == R2_GRID_UNKNOWN_VALUE) continue;
      if (neighbor_value < neighbor_minimum) neighbor_minimum = neighbor_value;
      neighbor_sum += neighbor_value;
      neighbor_count++;
    }
  }

  // Check if has any neighbors
  if (neighbor_count == 0) return R2_GRID_UNKNOWN_VALUE;

  // Compute mean of neighbor values
  RNScalar neighbor_mean = neighbor_sum / neighbor_count;
  //RNScalar delta = value - neighbor_minimum;
  RNScalar delta = value - neighbor_mean;
  return delta;
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x58(%rsp)
movl %esi, 0x54(%rsp)
movl %edx, 0x50(%rsp)
movq 0x58(%rsp), %rdi
movl 0x54(%rsp), %esi
movl 0x50(%rsp), %edx
callq 0xae90
movsd %xmm0, 0x48(%rsp)
movsd 0x48(%rsp), %xmm0
movsd 0xa5ba1(%rip), %xmm1    # 0xab008
ucomisd %xmm1, %xmm0
jne 0x5482
jp 0x5482
movsd 0xa5b91(%rip), %xmm0    # 0xab008
movsd %xmm0, 0x60(%rsp)
jmp 0x5615
movl $0x0, 0x44(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x38(%rsp)
movsd 0xa5b75(%rip), %xmm0    # 0xab010
movsd %xmm0, 0x30(%rsp)
movl $0xffffffff, 0x2c(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x2c(%rsp)
jg 0x55ca
movl $0xffffffff, 0x28(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x28(%rsp)
jg 0x55b8
cmpl $0x0, 0x28(%rsp)
jne 0x54da
cmpl $0x0, 0x2c(%rsp)
jne 0x54da
jmp 0x55a8
movl 0x54(%rsp), %eax
addl 0x28(%rsp), %eax
movl %eax, 0x24(%rsp)
cmpl $0x0, 0x24(%rsp)
jl 0x5509
movl 0x24(%rsp), %eax
movl %eax, 0x4(%rsp)
movq 0x58(%rsp), %rdi
callq 0xaed0
movl %eax, %ecx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
jl 0x550e
jmp 0x55a8
movl 0x50(%rsp), %eax
addl 0x2c(%rsp), %eax
movl %eax, 0x20(%rsp)
cmpl $0x0, 0x20(%rsp)
jl 0x553b
movl 0x20(%rsp), %eax
movl %eax, (%rsp)
movq 0x58(%rsp), %rdi
callq 0xaef0
movl %eax, %ecx
movl (%rsp), %eax
cmpl %ecx, %eax
jl 0x553d
jmp 0x55a8
movq 0x58(%rsp), %rdi
movl 0x24(%rsp), %esi
movl 0x20(%rsp), %edx
callq 0xae90
movsd %xmm0, 0x18(%rsp)
movsd 0x18(%rsp), %xmm0
movsd 0xa5aa5(%rip), %xmm1    # 0xab008
ucomisd %xmm1, %xmm0
jne 0x556d
jp 0x556d
jmp 0x55a8
movsd 0x18(%rsp), %xmm1
movsd 0x30(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x558b
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
movsd 0x18(%rsp), %xmm0
addsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
movl 0x28(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x28(%rsp)
jmp 0x54bc
jmp 0x55ba
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x54a9
cmpl $0x0, 0x44(%rsp)
jne 0x55e1
movsd 0xa5a2f(%rip), %xmm0    # 0xab008
movsd %xmm0, 0x60(%rsp)
jmp 0x5615
movsd 0x38(%rsp), %xmm0
cvtsi2sdl 0x44(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x48(%rsp), %xmm0
subsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x60(%rsp), %xmm0
addq $0x68, %rsp
retq