// File: /workspace/github_cpp_makefile_star2_O1/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, 0x38(%rsp)
movl %edx, %ebp
movq %rdi, %rbx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
callq 0x1a2b8
movq %r15, %rdi
callq 0x1bd9c
movq %rbx, %rdi
callq 0x28474
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x14e34
sqrtsd %xmm0, %xmm0
jmp 0x14e39
callq 0xe340
movsd %xmm0, 0x30(%rsp)
leaq 0x10(%rsp), %rdi
callq 0x7c644
movl %ebp, 0x2c(%rsp)
movq %rsp, %rdi
callq 0x7c644
cmpl $0x0, 0x14(%rbx)
movq %rbx, 0x20(%rsp)
jle 0x14fb8
xorl %r12d, %r12d
movsd 0x991b9(%rip), %xmm2    # 0xae028
movq %rsp, %r15
movq 0x8(%rbx), %rax
movq (%rax,%r12,8), %rsi
movslq 0x70(%rsi), %rax
movq 0x450(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm0
ucomisd %xmm2, %xmm0
movl $0x0, %edi
jne 0x14e9c
jnp 0x14f90
movslq 0x14(%rsi), %rdi
testq %rdi, %rdi
setg %dl
jle 0x14f58
movq 0x8(%rsi), %r8
movq %rdi, %r9
negq %r9
movl $0x1, %ebx
movb $0x1, %dl
movl $0x1, %r10d
movl $0x1, %eax
movq -0x8(%r8,%r10,8), %r13
movq 0x8(%r13), %r11
cmpq %rsi, %r11
jne 0x14eda
movq 0x10(%r13), %r11
movslq 0x70(%r11), %r11
movsd (%rcx,%r11,8), %xmm1
movl $0x4, %ebp
ucomisd %xmm2, %xmm1
jne 0x14ef6
jp 0x14ef6
movl %ebx, %r11d
jmp 0x14f33
xorl %r11d, %r11d
ucomisd %xmm0, %xmm1
seta %r11b
andl %ebx, %r11d
cmpl $0xb, %r14d
jne 0x14f19
testl %r11d, %r11d
jne 0x14f19
xorl %r11d, %r11d
movl $0x1, %ebp
jmp 0x14f33
movl %r14d, %ebx
xorl $0xa, %ebx
xorl %ebp, %ebp
ucomisd %xmm1, %xmm0
seta %bpl
andl %ebp, %eax
xorl %ebp, %ebp
orl %eax, %ebx
sete %bpl
testb $0x3, %bpl
jne 0x14f63
cmpq %rdi, %r10
setb %dl
leaq (%r9,%r10), %r13
incq %r13
incq %r10
movl %r11d, %ebx
cmpq $0x1, %r13
jne 0x14ec8
jmp 0x14f63
movl $0x1, %eax
movl $0x1, %r11d
movl $0x0, %edi
testb $0x1, %dl
movq 0x20(%rsp), %rbx
jne 0x14f90
cmpl $0xb, %r14d
je 0x14f82
cmpl $0xa, %r14d
jne 0x14f87
movl %eax, %edi
jmp 0x14f90
movl %r11d, %edi
jmp 0x14f90
xorl %edi, %edi
orl %eax, %r11d
setne %dil
testl %edi, %edi
je 0x14fa8
movl 0xc(%rsp), %edx
movq %r15, %rdi
callq 0x7c6da
movsd 0x99080(%rip), %xmm2    # 0xae028
incq %r12
movslq 0x14(%rbx), %rax
cmpq %rax, %r12
jl 0x14e72
cmpl $0x0, 0xc(%rsp)
jle 0x15059
movl $0x1, %ebp
xorl %ebx, %ebx
movq %rsp, %r15
movq %rbx, %r12
incq %rbx
movslq 0xc(%rsp), %rax
cmpq %rax, %rbx
jge 0x15048
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 0x1502a
cmpl $0xb, %r14d
jne 0x1501a
ucomisd %xmm1, %xmm0
ja 0x15030
jmp 0x1503e
movapd 0x9907e(%rip), %xmm2    # 0xae0a0
andpd %xmm2, %xmm0
andpd %xmm2, %xmm1
ucomisd %xmm0, %xmm1
jbe 0x1503e
movq %r15, %rdi
movl %r12d, %esi
movl %r13d, %edx
callq 0x7c956
incq %r13
cmpl %r13d, 0xc(%rsp)
jg 0x14fe0
movslq 0xc(%rsp), %rax
incq %rbp
cmpq %rax, %rbx
jl 0x14fcd
leaq 0xdf480(%rip), %r12     # 0xf44e0
incl (%r12)
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0x7c884
movq 0x20(%rsp), %rbx
cmpl $0x0, 0xc(%rsp)
jle 0x1513d
xorl %r13d, %r13d
leaq 0x10(%rsp), %r14
movq (%rsp), %rax
movq (%rax,%r13,8), %r15
movl 0x88(%r15), %eax
cmpl (%r12), %eax
je 0x1512c
cmpl $0x0, 0x14(%r15)
je 0x1512c
movl 0x1c(%rsp), %edx
movq %r14, %rdi
movq %r15, %rsi
callq 0x7c6da
movsd 0x38(%rsp), %xmm0
ucomisd 0x98f87(%rip), %xmm0    # 0xae050
movl (%r12), %eax
movl %eax, 0x88(%r15)
jbe 0x1512c
movq %rbx, %rdi
movq %r15, %rsi
xorl %edx, %edx
callq 0x32b8c
movslq 0x14(%rbx), %rcx
testq %rcx, %rcx
movsd 0x38(%rsp), %xmm0
jle 0x1511f
movq 0x8(%rbx), %rdx
movl (%r12), %esi
xorl %edi, %edi
movq (%rdx,%rdi,8), %r8
cmpl %esi, 0x88(%r8)
je 0x15117
ucomisd (%rax,%rdi,8), %xmm0
jb 0x15117
movl %esi, 0x88(%r8)
incq %rdi
cmpq %rdi, %rcx
jne 0x150fc
testq %rax, %rax
je 0x1512c
movq %rax, %rdi
callq 0xe5c0
incq %r13
movslq 0xc(%rsp), %rax
cmpq %rax, %r13
jl 0x15088
cmpb $0x0, 0xdfb68(%rip)     # 0xf4cac
je 0x1517a
movl 0x1c(%rsp), %r14d
leaq 0x40(%rsp), %rdi
callq 0x1aa48
movapd %xmm0, %xmm1
movsd 0x30(%rsp), %xmm0
mulsd 0x98ef1(%rip), %xmm0    # 0xae058
leaq 0x99517(%rip), %rdi     # 0xae685
xorl %esi, %esi
movl %r14d, %edx
movb $0x2, %al
callq 0xe070
movq %rsp, %rdi
callq 0x7c6ae
cmpb $0x0, 0xdfb23(%rip)     # 0xf4cac
je 0x1519c
leaq 0x99504(%rip), %rsi     # 0xae696
leaq 0x40(%rsp), %rdi
callq 0x1cf16
movl $0x10, %edi
callq 0xe450
movl 0x2c(%rsp), %ebx
movq %rax, %r14
movq %rax, %rdi
callq 0x7c644
testl %ebx, %ebx
jle 0x15214
cmpl $0x0, 0x1c(%rsp)
jle 0x15214
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 0x20(%rsp), %rsi
movq %r12, %rdx
callq 0x159b2
movl 0xc(%r14), %edx
movq %r14, %rdi
movq %r15, %rsi
callq 0x7c6da
cmpq %rbx, %r13
jae 0x15214
movslq 0x1c(%rsp), %rax
leaq 0x1(%r13), %rcx
cmpq %rax, %r13
movq %rcx, %r13
jl 0x151c8
leaq 0x10(%rsp), %rdi
callq 0x7c6ae
leaq 0x40(%rsp), %rdi
callq 0x1a36c
movq %r14, %rax
addq $0x488, %rsp            # imm = 0x488
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x15273
movq %rax, %rbx
movl $0x10, %esi
movq %r14, %rdi
jmp 0x1526c
jmp 0x15273
jmp 0x15273
jmp 0x15254
jmp 0x15254
movq %rax, %rbx
jmp 0x1528d
jmp 0x15278
jmp 0x15278
jmp 0x15278
jmp 0x15278
movq %rax, %rbx
movl $0x48, %esi
movq %r15, %rdi
callq 0xe460
jmp 0x15283
movq %rax, %rbx
jmp 0x15283
movq %rax, %rbx
movq %rsp, %rdi
callq 0x7c6ae
leaq 0x10(%rsp), %rdi
callq 0x7c6ae
leaq 0x40(%rsp), %rdi
callq 0x1a36c
movq %rbx, %rdi
callq 0xe7f0