// File: /workspace/github_cpp_makefile_star2_O2/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, 0x18(%rsp)
movl %edx, %ebp
movq %rdi, %rbx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
callq 0x191b8
movq %r15, %rdi
callq 0x1aa74
movq %rbx, %rdi
callq 0x25642
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x13dee
sqrtsd %xmm0, %xmm0
jmp 0x13df3
callq 0xe350
movsd %xmm0, (%rsp)
leaq 0x20(%rsp), %rdi
callq 0x7132e
movl %ebp, 0x34(%rsp)
leaq 0x8(%rsp), %rdi
callq 0x7132e
movsd (%rsp), %xmm0
mulsd 0x8a23b(%rip), %xmm0    # 0x9e058
movsd %xmm0, (%rsp)
xorl %r12d, %r12d
pushq $0x1
popq %r13
leaq 0x8(%rsp), %r15
xorl %ebp, %ebp
movslq 0x14(%rbx), %rax
cmpq %rax, %rbp
jge 0x13f1f
movq 0x8(%rbx), %rax
movq (%rax,%rbp,8), %rsi
movslq 0x70(%rsi), %rcx
movq 0x450(%rsp), %rax
movsd (%rax,%rcx,8), %xmm0
ucomisd 0x8a1c2(%rip), %xmm0    # 0x9e020
jne 0x13e67
jp 0x13e67
incq %rbp
jmp 0x13e30
movl 0x14(%rsi), %ecx
testl %ecx, %ecx
cmovlel %r12d, %ecx
xorl %edx, %edx
movl %r13d, %edi
movl %r13d, %r8d
cmpq %rdx, %rcx
je 0x13eed
movq 0x8(%rsi), %r9
movq (%r9,%rdx,8), %r10
movq 0x8(%r10), %r9
cmpq %rsi, %r9
jne 0x13e92
movq 0x10(%r10), %r9
movslq 0x70(%r9), %r9
movsd (%rax,%r9,8), %xmm1
ucomisd 0x8a17c(%rip), %xmm1    # 0x9e020
jne 0x13eb0
jp 0x13eb0
movl %edi, %r10d
movl %r8d, %r9d
jmp 0x13ee2
xorl %r9d, %r9d
ucomisd %xmm0, %xmm1
seta %r9b
andl %r8d, %r9d
cmpl $0xb, %r14d
jne 0x13ec9
testl %r9d, %r9d
je 0x13e62
xorl %r10d, %r10d
ucomisd %xmm1, %xmm0
seta %r10b
andl %edi, %r10d
cmpl $0xa, %r14d
jne 0x13ee2
testl %r10d, %r10d
je 0x13e62
incq %rdx
movl %r10d, %edi
movl %r9d, %r8d
jmp 0x13e78
cmpl $0xb, %r14d
je 0x13f09
cmpl $0xa, %r14d
jne 0x13efe
movl %edi, %r8d
jmp 0x13f09
xorl %eax, %eax
orl %edi, %r8d
setne %al
movl %eax, %r8d
testl %r8d, %r8d
je 0x13e62
movq %r15, %rdi
callq 0x14bcc
jmp 0x13e62
pushq $0x1
popq %rbp
leaq 0x8(%rsp), %r15
movl 0xc(%r15), %eax
xorl %r12d, %r12d
movq %rbx, 0x38(%rsp)
movslq %eax, %rcx
cmpq %rcx, %r12
jge 0x13fc4
leaq 0x1(%r12), %rbx
movq %rbp, %r13
cmpl %r13d, %eax
jle 0x13fb4
movq 0x8(%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 0x13f97
cmpl $0xb, %r14d
jne 0x13f87
ucomisd %xmm1, %xmm0
ja 0x13f9d
jmp 0x13fab
movapd 0x8a101(%rip), %xmm2    # 0x9e090
andpd %xmm2, %xmm0
andpd %xmm2, %xmm1
ucomisd %xmm0, %xmm1
jbe 0x13fab
movq %r15, %rdi
movl %r12d, %esi
movl %r13d, %edx
callq 0x715d8
incq %r13
movl 0x14(%rsp), %eax
jmp 0x13f47
incq %rbp
movq %rbx, %r12
movq 0x38(%rsp), %rbx
jmp 0x13f33
leaq 0xd4535(%rip), %r12     # 0xe8500
incl (%r12)
leaq 0x20(%rsp), %rdi
xorl %r13d, %r13d
xorl %esi, %esi
callq 0x7154c
leaq 0x20(%rsp), %r14
xorl %ebp, %ebp
movslq 0x14(%rsp), %rax
cmpq %rax, %rbp
jge 0x140a2
movq 0x8(%rsp), %rax
movq (%rax,%rbp,8), %r15
movl 0x88(%r15), %eax
cmpl (%r12), %eax
je 0x1409a
cmpl $0x0, 0x14(%r15)
je 0x1409a
movq %r14, %rdi
movq %r15, %rsi
callq 0x14bcc
movsd 0x18(%rsp), %xmm0
ucomisd 0x8a01f(%rip), %xmm0    # 0x9e050
movl (%r12), %eax
movl %eax, 0x88(%r15)
jbe 0x1409a
movq %rbx, %rdi
movq %r15, %rsi
movsd 0x18(%rsp), %xmm0
xorl %edx, %edx
callq 0x2e39e
movl 0x14(%rbx), %ecx
movl (%r12), %edx
testl %ecx, %ecx
cmovlel %r13d, %ecx
xorl %esi, %esi
cmpq %rsi, %rcx
je 0x1408d
movq 0x8(%rbx), %rdi
movq (%rdi,%rsi,8), %rdi
cmpl %edx, 0x88(%rdi)
je 0x14088
movsd 0x18(%rsp), %xmm0
ucomisd (%rax,%rsi,8), %xmm0
jb 0x14088
movl %edx, 0x88(%rdi)
incq %rsi
jmp 0x14060
testq %rax, %rax
je 0x1409a
movq %rax, %rdi
callq 0xe5e0
incq %rbp
jmp 0x13fe5
cmpb $0x0, 0xd4c23(%rip)     # 0xe8ccc
je 0x140d6
movl 0x2c(%rsp), %r14d
leaq 0x40(%rsp), %rdi
callq 0x198c4
movapd %xmm0, %xmm1
leaq 0x8a5bd(%rip), %rdi     # 0x9e682
xorl %esi, %esi
movl %r14d, %edx
movsd (%rsp), %xmm0
movb $0x2, %al
callq 0xe070
leaq 0x8(%rsp), %rdi
callq 0x7139c
cmpb $0x0, 0xd4be5(%rip)     # 0xe8ccc
je 0x140fa
leaq 0x8a5a3(%rip), %rsi     # 0x9e693
leaq 0x40(%rsp), %rdi
callq 0x1b9aa
pushq $0x10
popq %rdi
callq 0xe460
movl 0x34(%rsp), %ebp
movq %rax, %r14
movq %rbx, %r15
movq %rax, %rdi
callq 0x7132e
movslq %ebp, %rbx
xorl %ebp, %ebp
cmpq %rbx, %rbp
jge 0x1415a
movslq 0x2c(%rsp), %rax
cmpq %rax, %rbp
jge 0x1415a
movq 0x20(%rsp), %rax
movq (%rax,%rbp,8), %r13
pushq $0x48
popq %rdi
callq 0xe460
movq %rax, %r12
movq %rax, %rdi
movq %r15, %rsi
movq %r13, %rdx
callq 0x148c6
movq %r14, %rdi
movq %r12, %rsi
callq 0x14bcc
incq %rbp
jmp 0x14119
leaq 0x20(%rsp), %rdi
callq 0x7139c
leaq 0x40(%rsp), %rdi
callq 0x1925c
movq %r14, %rax
addq $0x488, %rsp            # imm = 0x488
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x141b5
movq %rax, %rbx
pushq $0x10
popq %rsi
movq %r14, %rdi
jmp 0x141ae
jmp 0x141b5
jmp 0x141b5
jmp 0x14198
jmp 0x14198
movq %rax, %rbx
jmp 0x141d1
jmp 0x141ba
jmp 0x141ba
jmp 0x141ba
jmp 0x141ba
movq %rax, %rbx
pushq $0x48
popq %rsi
movq %r12, %rdi
callq 0xe470
jmp 0x141c7
movq %rax, %rbx
jmp 0x141c7
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x7139c
leaq 0x20(%rsp), %rdi
callq 0x7139c
leaq 0x40(%rsp), %rdi
callq 0x1925c
movq %rbx, %rdi
callq 0xe820