// File: tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: IsLocalExtremum(gaps::R3Mesh*, gaps::R3MeshVertex*, gaps::R3MeshProperty*, int, double)
static RNBoolean 
IsLocalExtremum(R3Mesh *mesh, R3MeshVertex *vertex, R3MeshProperty *property, int extrema_type, RNScalar epsilon = 0)
{
  // Return whether value at vertex is local extremum
  RNBoolean minimum = TRUE;
  RNBoolean maximum = TRUE;
  RNScalar value = property->VertexValue(mesh->VertexID(vertex));
  if (value == RN_UNKNOWN) return FALSE;
  for (int i = 0; i < mesh->VertexValence(vertex); i++) {
    R3MeshEdge *edge = mesh->EdgeOnVertex(vertex, i);
    R3MeshVertex *neighbor_vertex = mesh->VertexAcrossEdge(edge, vertex);
    RNScalar neighbor_value = property->VertexValue(mesh->VertexID(neighbor_vertex));
    if (neighbor_value == RN_UNKNOWN) continue;
    minimum &= (value + epsilon < neighbor_value) ? TRUE : FALSE;
    if ((extrema_type == PROPERTY_MINIMA) && !minimum) return FALSE;
    maximum &= (value - epsilon > neighbor_value) ? TRUE : FALSE;
    if ((extrema_type == PROPERTY_MAXIMA) && !maximum) return FALSE;
  }

  // Vertex value is extremum
  if (extrema_type == PROPERTY_MINIMA) return minimum;
  else if (extrema_type == PROPERTY_MAXIMA) return maximum;
  return minimum || maximum;
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x78(%rsp)
movq %rsi, 0x70(%rsp)
movq %rdx, 0x68(%rsp)
movl %ecx, 0x64(%rsp)
movsd %xmm0, 0x58(%rsp)
movl $0x1, 0x54(%rsp)
movl $0x1, 0x50(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x78(%rsp), %rdi
movq 0x70(%rsp), %rsi
callq 0x1b320
movq 0x20(%rsp), %rdi
movl %eax, %esi
callq 0x1ba10
movsd %xmm0, 0x48(%rsp)
movsd 0x48(%rsp), %xmm0
movsd 0x12facf(%rip), %xmm1   # 0x14a038
ucomisd %xmm1, %xmm0
jne 0x1a581
jp 0x1a581
movl $0x0, 0x84(%rsp)
jmp 0x1a713
movl $0x0, 0x44(%rsp)
movl 0x44(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0x78(%rsp), %rdi
movq 0x70(%rsp), %rsi
callq 0x1e5e0
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x1a6c0
movq 0x78(%rsp), %rdi
movq 0x70(%rsp), %rsi
movl 0x44(%rsp), %edx
callq 0x1ea60
movq %rax, 0x38(%rsp)
movq 0x78(%rsp), %rdi
movq 0x38(%rsp), %rsi
movq 0x70(%rsp), %rdx
callq 0x1ea90
movq %rax, 0x30(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x78(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0x1b320
movq 0x10(%rsp), %rdi
movl %eax, %esi
callq 0x1ba10
movsd %xmm0, 0x28(%rsp)
movsd 0x28(%rsp), %xmm0
movsd 0x12fa20(%rip), %xmm1   # 0x14a038
ucomisd %xmm1, %xmm0
jne 0x1a625
jp 0x1a625
jmp 0x1a6b0
movsd 0x48(%rsp), %xmm1
addsd 0x58(%rsp), %xmm1
movsd 0x28(%rsp), %xmm0
xorl %eax, %eax
movl $0x1, %ecx
ucomisd %xmm1, %xmm0
cmoval %ecx, %eax
andl 0x54(%rsp), %eax
movl %eax, 0x54(%rsp)
cmpl $0xb, 0x64(%rsp)
jne 0x1a66b
cmpl $0x0, 0x54(%rsp)
jne 0x1a66b
movl $0x0, 0x84(%rsp)
jmp 0x1a713
movsd 0x48(%rsp), %xmm0
subsd 0x58(%rsp), %xmm0
movsd 0x28(%rsp), %xmm1
xorl %eax, %eax
movl $0x1, %ecx
ucomisd %xmm1, %xmm0
cmoval %ecx, %eax
andl 0x50(%rsp), %eax
movl %eax, 0x50(%rsp)
cmpl $0xa, 0x64(%rsp)
jne 0x1a6ae
cmpl $0x0, 0x50(%rsp)
jne 0x1a6ae
movl $0x0, 0x84(%rsp)
jmp 0x1a713
jmp 0x1a6b0
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x1a589
cmpl $0xb, 0x64(%rsp)
jne 0x1a6d4
movl 0x54(%rsp), %eax
movl %eax, 0x84(%rsp)
jmp 0x1a713
cmpl $0xa, 0x64(%rsp)
jne 0x1a6e8
movl 0x50(%rsp), %eax
movl %eax, 0x84(%rsp)
jmp 0x1a713
jmp 0x1a6ea
movb $0x1, %al
cmpl $0x0, 0x54(%rsp)
movb %al, 0xf(%rsp)
jne 0x1a703
cmpl $0x0, 0x50(%rsp)
setne %al
movb %al, 0xf(%rsp)
movb 0xf(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0x84(%rsp)
movl 0x84(%rsp), %eax
addq $0x88, %rsp
retq
nopw %cs:(%rax,%rax)