// File: /workspace/github_cpp_makefile_star2_O1/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 0x154ad
leaq 0xf8(%rbx), %rdi
callq 0x27b70
movq %rbx, 0x18(%rsp)
movl $0x100, %edi            # imm = 0x100
callq 0xe030
movq %rax, %r13
xorl %ebx, %ebx
movq %rax, 0x8(%rsp)
movl $0x100, %edi            # imm = 0x100
callq 0xe030
movq %rax, (%r13,%rbx,8)
xorl %r13d, %r13d
movl $0x208, %edi            # imm = 0x208
callq 0xe030
movq %rax, %r15
movq $0x20, (%rax)
leaq 0x8(%rax), %rbp
movq %rbp, %r12
xorl %r14d, %r14d
movq %r12, %rdi
callq 0x705ec
addq $-0x10, %r14
addq $0x10, %r12
cmpq $-0x200, %r14           # imm = 0xFE00
jne 0x154f6
movq 0x8(%rsp), %rax
movq (%rax,%rbx,8), %rax
movq %rbp, (%rax,%r13,8)
incq %r13
cmpq $0x20, %r13
jne 0x154d8
incq %rbx
cmpq $0x20, %rbx
movq 0x8(%rsp), %r13
jne 0x154c6
movq 0x18(%rsp), %r14
cmpl $0x0, 0x14(%r14)
jle 0x15640
xorl %ebx, %ebx
movsd 0x8ccc3(%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 0x15591
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 0x155ca
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 0x15606
movl $0x1f, %r8d
testl %r8d, %r8d
cmovlel %ebx, %r8d
movq (%r13,%rax,8), %rax
movq (%rax,%rdx,8), %rax
shlq $0x4, %r8
leaq (%rax,%r8), %rdi
movl 0xc(%rax,%r8), %edx
callq 0x70682
incq %r15
movslq 0x14(%r14), %rax
cmpq %rax, %r15
movsd 0x8cbd6(%rip), %xmm3    # 0xa2210
jl 0x15550
xorl %ebx, %ebx
xorl %r15d, %r15d
xorl %r14d, %r14d
movq (%r13,%rbx,8), %rax
movq (%rax,%r15,8), %rax
movq %r14, 0x20(%rsp)
shlq $0x4, %r14
cmpl $0x0, 0xc(%rax,%r14)
jle 0x15716
addq %r14, %rax
movl $0x1, %ecx
movq %rcx, 0x10(%rsp)
xorl %edx, %edx
leaq 0x1(%rdx), %r9
movq (%r13,%rbx,8), %rcx
movq (%rcx,%r15,8), %rcx
movslq 0xc(%rcx,%r14), %rsi
movq %r9, 0x28(%rsp)
cmpq %rsi, %r9
jge 0x156f2
movq (%rax), %rax
movq (%rax,%rdx,8), %rax
addq %r14, %rcx
movq %rax, 0x30(%rsp)
leaq 0x18(%rax), %r12
movq 0x10(%rsp), %rbp
movq (%rcx), %rax
movq (%rax,%rbp,8), %r13
leaq 0x18(%r13), %rsi
movq %r12, %rdi
callq 0x46e1b
testl %eax, %eax
je 0x156d6
movq 0x18(%rsp), %rdi
movq (%rdi), %rax
movq 0x30(%rsp), %rsi
movq %r13, %rdx
callq *0x88(%rax)
incq %rbp
movq 0x8(%rsp), %r13
movq (%r13,%rbx,8), %rax
movq (%rax,%r15,8), %rax
leaq (%rax,%r14), %rcx
cmpl %ebp, 0xc(%rax,%r14)
jg 0x156a9
movq (%r13,%rbx,8), %rax
movq (%rax,%r15,8), %rax
movslq 0xc(%rax,%r14), %rcx
addq %r14, %rax
incq 0x10(%rsp)
movq 0x28(%rsp), %rdx
cmpq %rcx, %rdx
jl 0x15675
movq 0x20(%rsp), %r14
incq %r14
cmpq $0x20, %r14
jne 0x15648
incq %r15
cmpq $0x20, %r15
jne 0x15645
incq %rbx
cmpq $0x20, %rbx
jne 0x15642
xorl %ebx, %ebx
xorl %r12d, %r12d
movq (%r13,%rbx,8), %rax
movq (%rax,%r12,8), %r14
testq %r14, %r14
je 0x15796
movq -0x8(%r14), %r15
testq %r15, %r15
je 0x1577a
leaq -0x10(%r14), %r13
movq %r15, %rbp
shlq $0x4, %rbp
movq %r13, %rdi
addq %rbp, %rdi
callq 0x70656
addq $-0x10, %rbp
jne 0x15769
addq $-0x8, %r14
shlq $0x4, %r15
orq $0x8, %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xe8c0
movq 0x8(%rsp), %r13
incq %r12
cmpq $0x20, %r12
jne 0x15747
movq (%r13,%rbx,8), %rdi
testq %rdi, %rdi
je 0x157ae
callq 0xe5b0
incq %rbx
cmpq $0x20, %rbx
jne 0x15744
movq %r13, %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 0x157ee
negq %r14
movq %r15, %r12
addq $-0x8, %r12
leaq (%r12,%r14), %rdi
callq 0x70656
addq $-0x10, %r14
jne 0x157df
movl $0x208, %esi            # imm = 0x208
movq %r15, %rdi
callq 0xe8c0
movq %rbx, %rdi
callq 0xe7e0
nop