// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Grid.cpp
// Function: gaps::R3Grid::GridValue(double, double, double, double) const
RNScalar R3Grid::
GridValue(RNScalar x, RNScalar y, RNScalar z, 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;
  if ((z < 0) || (z > grid_resolution[2]-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);
  int zmin = (int) (z - f + 0.5);
  int zmax = (int) (z + 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;
  if (zmin < 0) zmin = 0;
  if (zmax > ZResolution()-1) zmax = ZResolution()-1;

  // Compute Gaussian weighting variables
  const RNScalar sqrt_two_pi = sqrt(RN_TWO_PI);
  double a = sqrt_two_pi * sigma;
  double fac = 1.0 / (a * a * a);
  double denom = 2.0 * sigma * sigma;

  // Filter sample with Gaussian
  RNScalar value = 0.0;
  RNScalar weight = 0.0;
  for (int k = zmin; k <= zmax; k++) {
    for (int j = ymin; j <= ymax; j++) {
      for (int i = xmin; i <= xmax; i++) {
        RNScalar dx = x - i;
        RNScalar dy = y - j;
        RNScalar dz = z - k;
        RNScalar d = dx*dx + dy*dy + dz*dz;
        RNScalar w = fac * exp(-d / denom);
        value += w * GridValue(i, j, k);
        weight += w;
      }
    }
  }

  // Normalize value based on total weight of Gaussian samples
  if (RNIsNotZero(weight)) value /= weight;

  // Return value
  return value;
}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xd8(%rsp)
movsd %xmm0, 0xd0(%rsp)
movsd %xmm1, 0xc8(%rsp)
movsd %xmm2, 0xc0(%rsp)
movsd %xmm3, 0xb8(%rsp)
movq 0xd8(%rsp), %rax
movq %rax, 0x28(%rsp)
xorps %xmm0, %xmm0
ucomisd 0xd0(%rsp), %xmm0
ja 0x572cf
movq 0x28(%rsp), %rax
movsd 0xd0(%rsp), %xmm0
movl 0x238(%rax), %eax
subl $0x1, %eax
cvtsi2sd %eax, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x572e0
xorps %xmm0, %xmm0
movsd %xmm0, 0xe0(%rsp)
jmp 0x577f9
xorps %xmm0, %xmm0
ucomisd 0xc8(%rsp), %xmm0
ja 0x5730f
movq 0x28(%rsp), %rax
movsd 0xc8(%rsp), %xmm0
movl 0x23c(%rax), %eax
subl $0x1, %eax
cvtsi2sd %eax, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x57320
xorps %xmm0, %xmm0
movsd %xmm0, 0xe0(%rsp)
jmp 0x577f9
xorps %xmm0, %xmm0
ucomisd 0xc0(%rsp), %xmm0
ja 0x5734f
movq 0x28(%rsp), %rax
movsd 0xc0(%rsp), %xmm0
movl 0x240(%rax), %eax
subl $0x1, %eax
cvtsi2sd %eax, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x57360
xorps %xmm0, %xmm0
movsd %xmm0, 0xe0(%rsp)
jmp 0x577f9
movsd 0xb8(%rsp), %xmm0
movsd 0xdbe6f(%rip), %xmm1    # 0x1331e0
mulsd %xmm1, %xmm0
movsd 0xdbc93(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xb4(%rsp)
movsd 0xd0(%rsp), %xmm0
cvtsi2sdl 0xb4(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd 0xdbc66(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xb0(%rsp)
movsd 0xd0(%rsp), %xmm0
cvtsi2sdl 0xb4(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd 0xdbc39(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xac(%rsp)
movsd 0xc8(%rsp), %xmm0
cvtsi2sdl 0xb4(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd 0xdbc0c(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xa8(%rsp)
movsd 0xc8(%rsp), %xmm0
cvtsi2sdl 0xb4(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd 0xdbbdf(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xa4(%rsp)
movsd 0xc0(%rsp), %xmm0
cvtsi2sdl 0xb4(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd 0xdbbb2(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xa0(%rsp)
movsd 0xc0(%rsp), %xmm0
cvtsi2sdl 0xb4(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd 0xdbb85(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x9c(%rsp)
cmpl $0x0, 0xb0(%rsp)
jge 0x574af
movl $0x0, 0xb0(%rsp)
movq 0x28(%rsp), %rdi
movl 0xac(%rsp), %eax
movl %eax, 0x24(%rsp)
callq 0x138c0
movl %eax, %ecx
movl 0x24(%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0x574e5
movq 0x28(%rsp), %rdi
callq 0x138c0
subl $0x1, %eax
movl %eax, 0xac(%rsp)
cmpl $0x0, 0xa8(%rsp)
jge 0x574fa
movl $0x0, 0xa8(%rsp)
movq 0x28(%rsp), %rdi
movl 0xa4(%rsp), %eax
movl %eax, 0x20(%rsp)
callq 0x138e0
movl %eax, %ecx
movl 0x20(%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0x57530
movq 0x28(%rsp), %rdi
callq 0x138e0
subl $0x1, %eax
movl %eax, 0xa4(%rsp)
cmpl $0x0, 0xa0(%rsp)
jge 0x57545
movl $0x0, 0xa0(%rsp)
movq 0x28(%rsp), %rdi
movl 0x9c(%rsp), %eax
movl %eax, 0x1c(%rsp)
callq 0x13900
movl %eax, %ecx
movl 0x1c(%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jle 0x5757b
movq 0x28(%rsp), %rdi
callq 0x13900
subl $0x1, %eax
movl %eax, 0x9c(%rsp)
leaq 0xdf376(%rip), %rax     # 0x1368f8
movsd (%rax), %xmm0
callq 0xf390
movsd %xmm0, 0x90(%rsp)
movsd 0x90(%rsp), %xmm0
mulsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x88(%rsp), %xmm1
mulsd 0x88(%rsp), %xmm1
mulsd 0x88(%rsp), %xmm1
movsd 0xdba36(%rip), %xmm0    # 0x133008
divsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0xdbc19(%rip), %xmm0    # 0x133200
mulsd 0xb8(%rsp), %xmm0
mulsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x70(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x68(%rsp)
movl 0xa0(%rsp), %eax
movl %eax, 0x64(%rsp)
movl 0x64(%rsp), %eax
cmpl 0x9c(%rsp), %eax
jg 0x577b9
movl 0xa8(%rsp), %eax
movl %eax, 0x60(%rsp)
movl 0x60(%rsp), %eax
cmpl 0xa4(%rsp), %eax
jg 0x577a7
movl 0xb0(%rsp), %eax
movl %eax, 0x5c(%rsp)
movl 0x5c(%rsp), %eax
cmpl 0xac(%rsp), %eax
jg 0x57795
movsd 0xd0(%rsp), %xmm0
cvtsi2sdl 0x5c(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0xc8(%rsp), %xmm0
cvtsi2sdl 0x60(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
movsd 0xc0(%rsp), %xmm0
cvtsi2sdl 0x64(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x40(%rsp)
movsd 0x50(%rsp), %xmm1
movsd 0x50(%rsp), %xmm2
movsd 0x48(%rsp), %xmm0
mulsd 0x48(%rsp), %xmm0
mulsd %xmm2, %xmm1
addsd %xmm0, %xmm1
movsd 0x40(%rsp), %xmm0
movsd 0x40(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x38(%rsp)
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x38(%rsp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
divsd 0x78(%rsp), %xmm0
callq 0xf8c0
movq 0x28(%rsp), %rdi
movaps %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rsp)
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movl 0x5c(%rsp), %esi
movl 0x60(%rsp), %edx
movl 0x64(%rsp), %ecx
callq 0x6bad0
movaps %xmm0, %xmm2
movsd 0x10(%rsp), %xmm0
movsd 0x70(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x30(%rsp), %xmm0
addsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x68(%rsp)
movl 0x5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5c(%rsp)
jmp 0x57654
jmp 0x57797
movl 0x60(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x60(%rsp)
jmp 0x57638
jmp 0x577a9
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64(%rsp)
jmp 0x5761c
movsd 0x68(%rsp), %xmm0
leaq 0x120d1a(%rip), %rax    # 0x1784e0
movsd (%rax), %xmm1
callq 0x555a0
cmpl $0x0, %eax
je 0x577ea
movsd 0x68(%rsp), %xmm1
movsd 0x70(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x70(%rsp), %xmm0
movsd %xmm0, 0xe0(%rsp)
movsd 0xe0(%rsp), %xmm0
addq $0xe8, %rsp
retq
nopw (%rax,%rax)