// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Grid.cpp
// Function: gaps::R2Grid::GridValue(double, double, double) const
RNScalar R2Grid::
GridValue(RNScalar x, RNScalar y, RNLength sigma) const
{
  // Check if within bounds
  if ((x < 0) || (x > grid_resolution[0]-1)) return 0.0;
  if ((y < 0) || (y > grid_resolution[1]-1)) return 0.0;

  // Determine Gaussian filter extent
  int f = (int) (3 * sigma + 0.5);
  int xmin = (int) (x - f + 0.5);
  int xmax = (int) (x + f + 0.5);
  int ymin = (int) (y - f + 0.5);
  int ymax = (int) (y + f + 0.5);
  if (xmin < 0) xmin = 0;
  if (xmax > XResolution()-1) xmax = XResolution()-1;
  if (ymin < 0) ymin = 0;
  if (ymax > YResolution()-1) ymax = YResolution()-1;

  // Filter sample with Gaussian
  RNScalar sum = 0.0;
  RNScalar weight = 0.0;
  double denom = 2.0 * sigma * sigma;
  for (int j = ymin; j <= ymax; j++) {
    for (int i = xmin; i <= xmax; i++) {
      RNScalar value = GridValue(i, j);
      if (value != R2_GRID_UNKNOWN_VALUE) { 
        RNScalar dx = x - i;
        RNScalar dy = y - j;
        RNScalar d = dx*dx + dy*dy;
        RNScalar w = exp(-d / denom);
        sum += w * value;
        weight += w;
      }
    }
  }

  // Normalize value based on total weight of Gaussian samples
  if (weight > 0) return sum / weight;
  else return R2_GRID_UNKNOWN_VALUE;
}

// Assembly:
subq $0x98, %rsp
movq %rdi, 0x88(%rsp)
movsd %xmm0, 0x80(%rsp)
movsd %xmm1, 0x78(%rsp)
movsd %xmm2, 0x70(%rsp)
movq 0x88(%rsp), %rax
movq %rax, 0x8(%rsp)
xorps %xmm0, %xmm0
ucomisd 0x80(%rsp), %xmm0
ja 0xb4180
movq 0x8(%rsp), %rax
movsd 0x80(%rsp), %xmm0
movl 0xc0(%rax), %eax
subl $0x1, %eax
cvtsi2sd %eax, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xb4191
xorps %xmm0, %xmm0
movsd %xmm0, 0x90(%rsp)
jmp 0xb449e
xorps %xmm0, %xmm0
ucomisd 0x78(%rsp), %xmm0
ja 0xb41ba
movq 0x8(%rsp), %rax
movsd 0x78(%rsp), %xmm0
movl 0xc4(%rax), %eax
subl $0x1, %eax
cvtsi2sd %eax, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xb41cb
xorps %xmm0, %xmm0
movsd %xmm0, 0x90(%rsp)
jmp 0xb449e
movsd 0x70(%rsp), %xmm0
movsd 0x7f007(%rip), %xmm1    # 0x1331e0
mulsd %xmm1, %xmm0
movsd 0x7ee2b(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x6c(%rsp)
movsd 0x80(%rsp), %xmm0
cvtsi2sdl 0x6c(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd 0x7ee04(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x68(%rsp)
movsd 0x80(%rsp), %xmm0
cvtsi2sdl 0x6c(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd 0x7eddd(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x64(%rsp)
movsd 0x78(%rsp), %xmm0
cvtsi2sdl 0x6c(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd 0x7edb9(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x60(%rsp)
movsd 0x78(%rsp), %xmm0
cvtsi2sdl 0x6c(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd 0x7ed95(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x5c(%rsp)
cmpl $0x0, 0x68(%rsp)
jge 0xb4296
movl $0x0, 0x68(%rsp)
movq 0x8(%rsp), %rdi
movl 0x64(%rsp), %eax
movl %eax, 0x4(%rsp)
callq 0xb9260
movl %eax, %ecx
movl 0x4(%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0xb42c6
movq 0x8(%rsp), %rdi
callq 0xb9260
subl $0x1, %eax
movl %eax, 0x64(%rsp)
cmpl $0x0, 0x60(%rsp)
jge 0xb42d5
movl $0x0, 0x60(%rsp)
movq 0x8(%rsp), %rdi
movl 0x5c(%rsp), %eax
movl %eax, (%rsp)
callq 0xb9280
movl %eax, %ecx
movl (%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0xb4303
movq 0x8(%rsp), %rdi
callq 0xb9280
subl $0x1, %eax
movl %eax, 0x5c(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x50(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x48(%rsp)
movsd 0x7eee3(%rip), %xmm0    # 0x133200
mulsd 0x70(%rsp), %xmm0
mulsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
movl 0x60(%rsp), %eax
movl %eax, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0x5c(%rsp), %eax
jg 0xb4467
movl 0x68(%rsp), %eax
movl %eax, 0x38(%rsp)
movl 0x38(%rsp), %eax
cmpl 0x64(%rsp), %eax
jg 0xb4455
movq 0x8(%rsp), %rdi
movl 0x38(%rsp), %esi
movl 0x3c(%rsp), %edx
callq 0xb92a0
movsd %xmm0, 0x30(%rsp)
movsd 0x30(%rsp), %xmm0
movsd 0x7fb2f(%rip), %xmm1    # 0x133eb0
ucomisd %xmm1, %xmm0
jne 0xb438e
jp 0xb438e
jmp 0xb4443
movsd 0x80(%rsp), %xmm0
cvtsi2sdl 0x38(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x78(%rsp), %xmm0
cvtsi2sdl 0x3c(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x20(%rsp)
movsd 0x28(%rsp), %xmm0
movsd 0x28(%rsp), %xmm2
movsd 0x20(%rsp), %xmm1
mulsd 0x20(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x18(%rsp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
divsd 0x40(%rsp), %xmm0
callq 0xf8c0
movsd %xmm0, 0x10(%rsp)
movsd 0x10(%rsp), %xmm0
movsd 0x30(%rsp), %xmm2
movsd 0x50(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x10(%rsp), %xmm0
addsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
jmp 0xb4445
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0xb434d
jmp 0xb4457
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xb4337
movsd 0x48(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xb448d
movsd 0x50(%rsp), %xmm0
divsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x90(%rsp)
jmp 0xb449e
movsd 0x7fa1b(%rip), %xmm0    # 0x133eb0
movsd %xmm0, 0x90(%rsp)
movsd 0x90(%rsp), %xmm0
addq $0x98, %rsp
retq
nop