// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::MergeCoincidentVertices(double)
void R3Mesh::
MergeCoincidentVertices(RNLength epsilon)
{
  // Compute epsilon
  if (epsilon < 0.0) epsilon = 0.0001 * bbox.DiagonalLength();

  // Allocate grid 
  const int NUM_GRID_CELLS = 32;
  RNArray<R3MeshVertex *> ***grid = new RNArray<R3MeshVertex *> **[NUM_GRID_CELLS];
  for (int i = 0; i < NUM_GRID_CELLS; i++) {
    grid[i] = new RNArray<R3MeshVertex *> *[NUM_GRID_CELLS];
    for (int j = 0; j < NUM_GRID_CELLS; j++) {
      grid[i][j] = new RNArray<R3MeshVertex *> [NUM_GRID_CELLS];
    }
  }
  
  // Load all vertices into a regular grid
  for (int i = 0; i < vertices.NEntries(); i++) {
    R3MeshVertex *v = vertices[i];
    const R3Point& p = v->position;
    int ix = (int) (NUM_GRID_CELLS * (p.X() - bbox.XMin()) / bbox.XLength());
    int iy = (int) (NUM_GRID_CELLS * (p.Y() - bbox.YMin()) / bbox.YLength());
    int iz = (int) (NUM_GRID_CELLS * (p.Z() - bbox.ZMin()) / bbox.ZLength());
    if (ix < 0) ix = 0; else if (ix > NUM_GRID_CELLS-1) ix = NUM_GRID_CELLS-1;
    if (iy < 0) iy = 0; else if (iy > NUM_GRID_CELLS-1) iy = NUM_GRID_CELLS-1;
    if (iz < 0) iz = 0; else if (iz > NUM_GRID_CELLS-1) iz = NUM_GRID_CELLS-1;
    grid[ix][iy][iz].Insert(v);
  }

  // Merge coincident vertices in same grid cell
  for (int ix = 0; ix < NUM_GRID_CELLS; ix++) {
    for (int iy = 0; iy < NUM_GRID_CELLS; iy++) {
      for (int iz = 0; iz < NUM_GRID_CELLS; iz++) {
        // Consider all pairs of vertices in same cell
        for (int j = 0; j < grid[ix][iy][iz].NEntries(); j++) {
          R3MeshVertex *v1 = grid[ix][iy][iz].Kth(j);
          for (int k = j+1; k < grid[ix][iy][iz].NEntries(); k++) {
            R3MeshVertex *v2 = grid[ix][iy][iz].Kth(k);
            // Check if vertices are coincident
            if (R3Contains(v1->position, v2->position)) {
              // Merge coincident vertices
              MergeVertex(v1, v2);
            }
          }
        }
      }
    }
  }

  // Delete grid
  for (int i = 0; i < NUM_GRID_CELLS; i++) {
    for (int j = 0; j < NUM_GRID_CELLS; j++) {
      delete [] grid[i][j];
    }
    delete [] grid[i];
  }
  delete [] grid;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdi, %rbx
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
jbe 0x1548b
leaq 0xf8(%rbx), %rdi
callq 0x27928
movq %rbx, 0x18(%rsp)
movl $0x100, %edi            # imm = 0x100
callq 0xe030
movq %rax, (%rsp)
xorl %ebx, %ebx
movl $0x100, %edi            # imm = 0x100
callq 0xe030
movq %rax, %r12
movq (%rsp), %rax
movq %rbx, 0x8(%rsp)
movq %r12, (%rax,%rbx,8)
xorl %ebp, %ebp
movl $0x208, %edi            # imm = 0x208
callq 0xe030
movq %rax, %r15
movq $0x20, (%rax)
leaq 0x8(%rax), %rbx
movq %rbx, %r13
xorl %r14d, %r14d
movq %r13, %rdi
callq 0x6f80c
addq $-0x10, %r14
addq $0x10, %r13
cmpq $-0x200, %r14           # imm = 0xFE00
jne 0x154da
movq %rbx, (%r12,%rbp,8)
incq %rbp
cmpq $0x20, %rbp
jne 0x154bc
movq 0x8(%rsp), %rbx
incq %rbx
cmpq $0x20, %rbx
jne 0x154a0
movq 0x18(%rsp), %r14
cmpl $0x0, 0x14(%r14)
jle 0x1561e
xorl %ebx, %ebx
movsd 0x8cce8(%rip), %xmm3    # 0xa2210
xorl %r15d, %r15d
movq 0x8(%r14), %rax
movq (%rax,%r15,8), %rsi
movsd 0x100(%r14), %xmm0
movsd 0x18(%rsi), %xmm1
subsd %xmm0, %xmm1
mulsd %xmm3, %xmm1
movsd 0x118(%r14), %xmm2
subsd %xmm0, %xmm2
divsd %xmm2, %xmm1
cvttsd2si %xmm1, %eax
movl $0x1f, %ecx
cmpl %ecx, %eax
jl 0x1556c
movl $0x1f, %eax
movsd 0x20(%rsi), %xmm0
movsd 0x108(%r14), %xmm1
subsd %xmm1, %xmm0
mulsd %xmm3, %xmm0
movsd 0x120(%r14), %xmm2
subsd %xmm1, %xmm2
divsd %xmm2, %xmm0
cvttsd2si %xmm0, %edx
testl %eax, %eax
cmovlel %ebx, %eax
cmpl %ecx, %edx
jl 0x155a5
movl $0x1f, %edx
movsd 0x28(%rsi), %xmm0
movsd 0x110(%r14), %xmm1
subsd %xmm1, %xmm0
mulsd %xmm3, %xmm0
movsd 0x128(%r14), %xmm2
subsd %xmm1, %xmm2
divsd %xmm2, %xmm0
cvttsd2si %xmm0, %r8d
testl %edx, %edx
cmovlel %ebx, %edx
cmpl %ecx, %r8d
jl 0x155e1
movl $0x1f, %r8d
testl %r8d, %r8d
cmovlel %ebx, %r8d
movq (%rsp), %rcx
movq (%rcx,%rax,8), %rax
movq (%rax,%rdx,8), %rax
shlq $0x4, %r8
leaq (%rax,%r8), %rdi
movl 0xc(%rax,%r8), %edx
callq 0x6f8a2
incq %r15
movslq 0x14(%r14), %rax
cmpq %rax, %r15
movsd 0x8cbf8(%rip), %xmm3    # 0xa2210
jl 0x1552b
xorl %ecx, %ecx
movq (%rsp), %rax
movq %rcx, 0x20(%rsp)
movq (%rax,%rcx,8), %rax
movq %rax, 0x8(%rsp)
xorl %ebx, %ebx
xorl %r14d, %r14d
movq 0x8(%rsp), %rax
movq (%rax,%rbx,8), %rax
movq %r14, 0x28(%rsp)
shlq $0x4, %r14
movl 0xc(%rax,%r14), %edx
testl %edx, %edx
jle 0x156f1
leaq (%rax,%r14), %rcx
movl $0x1, %esi
movq %rsi, 0x10(%rsp)
xorl %esi, %esi
leaq 0x1(%rsi), %rdi
movslq %edx, %rdx
movq %rdi, 0x30(%rsp)
cmpq %rdx, %rdi
jge 0x156cc
movq (%rcx), %rcx
movq (%rcx,%rsi,8), %r15
addq %r14, %rax
leaq 0x18(%r15), %r12
movq 0x10(%rsp), %rbp
movq (%rax), %rax
movq (%rax,%rbp,8), %r13
leaq 0x18(%r13), %rsi
movq %r12, %rdi
callq 0x4652b
testl %eax, %eax
je 0x156b5
movq 0x18(%rsp), %rdi
movq (%rdi), %rax
movq %r15, %rsi
movq %r13, %rdx
callq *0x88(%rax)
incq %rbp
movq 0x8(%rsp), %rax
movq (%rax,%rbx,8), %rcx
leaq (%rcx,%r14), %rax
cmpl %ebp, 0xc(%rcx,%r14)
jg 0x1568a
movq 0x8(%rsp), %rax
movq (%rax,%rbx,8), %rax
leaq (%rax,%r14), %rcx
movslq 0xc(%rax,%r14), %rdx
incq 0x10(%rsp)
movq 0x30(%rsp), %rsi
cmpq %rdx, %rsi
jl 0x15666
movq 0x28(%rsp), %r14
incq %r14
cmpq $0x20, %r14
jne 0x15637
incq %rbx
cmpq $0x20, %rbx
jne 0x15634
movq 0x20(%rsp), %rcx
incq %rcx
cmpq $0x20, %rcx
jne 0x15620
xorl %ebx, %ebx
xorl %r12d, %r12d
movq (%rsp), %rax
movq (%rax,%rbx,8), %rax
movq (%rax,%r12,8), %r14
testq %r14, %r14
je 0x15774
movq -0x8(%r14), %r15
testq %r15, %r15
je 0x1575d
leaq -0x10(%r14), %r13
movq %r15, %rbp
shlq $0x4, %rbp
movq %r13, %rdi
addq %rbp, %rdi
callq 0x6f876
addq $-0x10, %rbp
jne 0x1574c
addq $-0x8, %r14
shlq $0x4, %r15
orq $0x8, %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xe8c0
incq %r12
cmpq $0x20, %r12
jne 0x15727
movq (%rsp), %rax
movq (%rax,%rbx,8), %rdi
testq %rdi, %rdi
je 0x1578f
callq 0xe5b0
incq %rbx
cmpq $0x20, %rbx
jne 0x15724
movq (%rsp), %rdi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xe5b0
movq %rax, %rbx
testq %r14, %r14
je 0x157d0
negq %r14
movq %r15, %r12
addq $-0x8, %r12
leaq (%r12,%r14), %rdi
callq 0x6f876
addq $-0x10, %r14
jne 0x157c1
movl $0x208, %esi            # imm = 0x208
movq %r15, %rdi
callq 0xe8c0
movq %rbx, %rdi
callq 0xe7e0
nop