// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: SelectPropertyExtrema(gaps::R3Mesh*, gaps::R3MeshProperty*, int, double, int)
static RNArray<Point *> *
SelectPropertyExtrema(R3Mesh *mesh, R3MeshProperty *prp,
  int npoints, double min_spacing, int extrema_type)
{
  // Copy property 
  R3MeshProperty property(*prp);

  // Normalize property
  property.Normalize();

  // Select points from successively blurred property until number of extrema is npoints
  int max_blurs = 0;
  RNScalar epsilon = 0;
  RNScalar sigma = 0.01 * sqrt(mesh->Area());
  RNArray<R3MeshVertex *> selected_vertices;
  for (int blur = 0; blur <= max_blurs; blur++) { 
    // Find extremum vertices
    RNArray<R3MeshVertex *> extremum_vertices;
    for (int i = 0; i < mesh->NVertices(); i++) {
      R3MeshVertex *vertex = mesh->Vertex(i);
      if (!IsLocalExtremum(mesh, vertex, &property, extrema_type, epsilon)) continue; 
      extremum_vertices.Insert(vertex);
    }

    // Sort extremum vertices by property value
    for (int i = 0; i < extremum_vertices.NEntries(); i++) {
      for (int j = i+1; j < extremum_vertices.NEntries(); j++) {
        RNScalar value_i = property.VertexValue(extremum_vertices[i]);
        RNScalar value_j = property.VertexValue(extremum_vertices[j]);
        if (extrema_type == PROPERTY_MINIMA) { if (value_i > value_j) extremum_vertices.Swap(i, j); }
        else if (extrema_type == PROPERTY_MAXIMA) { if (value_i < value_j) extremum_vertices.Swap(i, j); }
        else { if (fabs(value_i) < fabs(value_j)) extremum_vertices.Swap(i, j); }
      }
    }

    // Select amongst extremum vertices taking into account min_spacing
    R3mesh_mark++;
    selected_vertices.Empty();
    for (int i = 0; i < extremum_vertices.NEntries(); i++) {
      R3MeshVertex *vertex = extremum_vertices.Kth(i);

      // Check if vertex is marked (i.e., too close to vertex previously selected)
      if (mesh->VertexMark(vertex) == R3mesh_mark) continue;

      // Check if vertex is disconnected completely
      if (mesh->VertexValence(vertex) == 0) continue;
    
      // Select vertex
      selected_vertices.Insert(vertex);

      // Mark nearby vertices
      mesh->SetVertexMark(vertex, R3mesh_mark);
      if (min_spacing > 0) {
        RNLength *distances = mesh->DijkstraDistances(vertex, min_spacing);
        for (int j = 0; j < mesh->NVertices(); j++) {
          R3MeshVertex *nearby_vertex = mesh->Vertex(j);
          if (mesh->VertexMark(nearby_vertex) != R3mesh_mark) {
            if (distances[j] <= min_spacing) {
              mesh->SetVertexMark(nearby_vertex, R3mesh_mark);
            }
          }
        } 
        delete [] distances;
      }
    }

    // Print debug statement
    if (print_debug) printf("  %d : %d %g %g\n", blur, selected_vertices.NEntries(), sigma, property.StandardDeviation());

    // Check if found correct number of points
    if ((npoints <= 0) || (selected_vertices.NEntries() <= npoints)) break;

    // Blur the property and iterate
    if (blur < max_blurs) {
      property.Blur(sigma);
      sigma *= 1.1;
    }
  }

  // For debugging purposes
  if (print_debug) property.Write("foo.val");

  // Allocate array of points
  RNArray<Point *> *points = new RNArray<Point *>();
  if (!points) {
    RNFail("Unable to allocate array of points\n");
    return NULL;
  }

  // Create points
  for (int i = 0; (i < selected_vertices.NEntries()) && (i < npoints); i++) {
    R3MeshVertex *vertex = selected_vertices[i];
    Point *point = new Point(mesh, vertex);
    points->Insert(point);
  }

  // Return points
  return points;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x488, %rsp            # imm = 0x488
movl %ecx, %r14d
movsd %xmm0, 0x30(%rsp)
movl %edx, %ebx
movq %rdi, %r13
leaq 0x40(%rsp), %r15
movq %r15, %rdi
callq 0x1a0a8
movq %r15, %rdi
callq 0x1bba2
movq %r13, %rdi
callq 0x27ca6
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x14d15
sqrtsd %xmm0, %xmm0
jmp 0x14d1a
callq 0xe340
movsd %xmm0, 0x28(%rsp)
leaq 0x10(%rsp), %rdi
callq 0x7b688
movl %ebx, 0x24(%rsp)
movq %rsp, %rdi
callq 0x7b688
movl 0x14(%r13), %eax
testl %eax, %eax
jle 0x14e51
xorl %r12d, %r12d
movsd 0x992db(%rip), %xmm2    # 0xae028
movq %rsp, %r15
movq 0x8(%r13), %rcx
movq (%rcx,%r12,8), %rsi
movq 0x450(%rsp), %rcx
movslq 0x70(%rsi), %rdx
movsd (%rcx,%rdx,8), %xmm0
ucomisd %xmm2, %xmm0
jne 0x14d75
jnp 0x14e42
movslq 0x14(%rsi), %rdx
testq %rdx, %rdx
jle 0x14dfd
movq 0x8(%rsi), %rdi
movl $0x1, %ebx
xorl %r8d, %r8d
movl $0x1, %r11d
movq (%rdi,%r8,8), %r10
movq 0x8(%r10), %r9
cmpq %rsi, %r9
jne 0x14da1
movq 0x10(%r10), %r9
movslq 0x70(%r9), %r9
movsd (%rcx,%r9,8), %xmm1
ucomisd %xmm2, %xmm1
jne 0x14dbb
jp 0x14dbb
movl %r11d, %r10d
movl %ebx, %r9d
jmp 0x14ded
xorl %r9d, %r9d
ucomisd %xmm0, %xmm1
seta %r9b
andl %ebx, %r9d
cmpl $0xb, %r14d
jne 0x14dd4
testl %r9d, %r9d
je 0x14e42
xorl %r10d, %r10d
ucomisd %xmm1, %xmm0
seta %r10b
andl %r11d, %r10d
cmpl $0xa, %r14d
jne 0x14ded
testl %r10d, %r10d
je 0x14e42
incq %r8
movl %r9d, %ebx
movl %r10d, %r11d
cmpq %r8, %rdx
jne 0x14d90
jmp 0x14e09
movl $0x1, %r10d
movl $0x1, %r9d
cmpl $0xb, %r14d
je 0x14e25
cmpl $0xa, %r14d
jne 0x14e1a
movl %r10d, %r9d
jmp 0x14e25
xorl %ecx, %ecx
orl %r10d, %r9d
setne %cl
movl %ecx, %r9d
testl %r9d, %r9d
je 0x14e42
movl 0xc(%rsp), %edx
movq %r15, %rdi
callq 0x7b71e
movl 0x14(%r13), %eax
movsd 0x991e6(%rip), %xmm2    # 0xae028
incq %r12
movslq %eax, %rcx
cmpq %rcx, %r12
jl 0x14d50
movq %r13, 0x38(%rsp)
movl 0xc(%rsp), %eax
testl %eax, %eax
jle 0x14ef6
movl $0x1, %ebp
xorl %ebx, %ebx
movq %rsp, %r15
movq %rbx, %r12
incq %rbx
movslq %eax, %rcx
cmpq %rcx, %rbx
jge 0x14eea
movq %rbp, %r13
movq (%rsp), %rax
movq (%rax,%r12,8), %rcx
movslq 0x70(%rcx), %rcx
movq 0x450(%rsp), %rdx
movsd (%rdx,%rcx,8), %xmm0
movq (%rax,%r13,8), %rax
movslq 0x70(%rax), %rax
movsd (%rdx,%rax,8), %xmm1
cmpl $0xa, %r14d
je 0x14ec7
cmpl $0xb, %r14d
jne 0x14eb7
ucomisd %xmm1, %xmm0
ja 0x14ecd
jmp 0x14edb
movapd 0x991e1(%rip), %xmm2    # 0xae0a0
andpd %xmm2, %xmm0
andpd %xmm2, %xmm1
ucomisd %xmm0, %xmm1
jbe 0x14edb
movq %r15, %rdi
movl %r12d, %esi
movl %r13d, %edx
callq 0x7b9bc
incq %r13
movl 0xc(%rsp), %eax
cmpl %r13d, %eax
jg 0x14e7d
movslq %eax, %rcx
incq %rbp
cmpq %rcx, %rbx
jl 0x14e6c
leaq 0xdf5e3(%rip), %r12     # 0xf44e0
incl (%r12)
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0x7b8e8
movq 0x38(%rsp), %rbp
cmpl $0x0, 0xc(%rsp)
jle 0x14fda
xorl %r13d, %r13d
leaq 0x10(%rsp), %r14
movq (%rsp), %rax
movq (%rax,%r13,8), %r15
movl 0x88(%r15), %eax
cmpl (%r12), %eax
je 0x14fc9
cmpl $0x0, 0x14(%r15)
je 0x14fc9
movl 0x1c(%rsp), %edx
movq %r14, %rdi
movq %r15, %rsi
callq 0x7b71e
movsd 0x30(%rsp), %xmm0
ucomisd 0x990ea(%rip), %xmm0    # 0xae050
movl (%r12), %eax
movl %eax, 0x88(%r15)
jbe 0x14fc9
movq %rbp, %rdi
movq %r15, %rsi
xorl %edx, %edx
callq 0x32456
movslq 0x14(%rbp), %rcx
testq %rcx, %rcx
movsd 0x30(%rsp), %xmm0
jle 0x14fbc
movq 0x8(%rbp), %rdx
movl (%r12), %esi
xorl %edi, %edi
movq (%rdx,%rdi,8), %r8
cmpl %esi, 0x88(%r8)
je 0x14fb4
ucomisd (%rax,%rdi,8), %xmm0
jb 0x14fb4
movl %esi, 0x88(%r8)
incq %rdi
cmpq %rdi, %rcx
jne 0x14f99
testq %rax, %rax
je 0x14fc9
movq %rax, %rdi
callq 0xe5c0
incq %r13
movslq 0xc(%rsp), %rax
cmpq %rax, %r13
jl 0x14f25
cmpb $0x0, 0xdfccb(%rip)     # 0xf4cac
je 0x15017
movl 0x1c(%rsp), %r14d
leaq 0x40(%rsp), %rdi
callq 0x1a848
movapd %xmm0, %xmm1
movsd 0x28(%rsp), %xmm0
mulsd 0x99054(%rip), %xmm0    # 0xae058
leaq 0x99677(%rip), %rdi     # 0xae682
xorl %esi, %esi
movl %r14d, %edx
movb $0x2, %al
callq 0xe070
movq %rsp, %rdi
callq 0x7b6f2
cmpb $0x0, 0xdfc86(%rip)     # 0xf4cac
je 0x15039
leaq 0x99664(%rip), %rsi     # 0xae693
leaq 0x40(%rsp), %rdi
callq 0x1ccdc
movl $0x10, %edi
callq 0xe450
movl 0x24(%rsp), %ebx
movq %rax, %r14
movq %rax, %rdi
callq 0x7b688
testl %ebx, %ebx
jle 0x150af
cmpl $0x0, 0x1c(%rsp)
jle 0x150af
movl %ebx, %ebx
movl $0x1, %r13d
movq 0x10(%rsp), %rax
movq -0x8(%rax,%r13,8), %r12
movl $0x48, %edi
callq 0xe450
movq %rax, %r15
movq %rax, %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0x15826
movl 0xc(%r14), %edx
movq %r14, %rdi
movq %r15, %rsi
callq 0x7b71e
cmpq %rbx, %r13
jae 0x150af
movslq 0x1c(%rsp), %rax
leaq 0x1(%r13), %rcx
cmpq %rax, %r13
movq %rcx, %r13
jl 0x15065
leaq 0x10(%rsp), %rdi
callq 0x7b6f2
leaq 0x40(%rsp), %rdi
callq 0x1a158
movq %r14, %rax
addq $0x488, %rsp            # imm = 0x488
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1510e
movq %rax, %rbx
movl $0x10, %esi
movq %r14, %rdi
jmp 0x15107
jmp 0x1510e
jmp 0x1510e
jmp 0x150ef
jmp 0x150ef
movq %rax, %rbx
jmp 0x15128
jmp 0x15113
jmp 0x15113
jmp 0x15113
jmp 0x15113
movq %rax, %rbx
movl $0x48, %esi
movq %r15, %rdi
callq 0xe460
jmp 0x1511e
movq %rax, %rbx
jmp 0x1511e
movq %rax, %rbx
movq %rsp, %rdi
callq 0x7b6f2
leaq 0x10(%rsp), %rdi
callq 0x7b6f2
leaq 0x40(%rsp), %rdi
callq 0x1a158
movq %rbx, %rdi
callq 0xe7f0