// File: /workspace/github_cpp_makefile_star2_O2/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 0x144db
leaq 0xf8(%rbx), %rdi
callq 0x25158
movq %rbx, 0x8(%rsp)
movl $0x100, %edi            # imm = 0x100
callq 0xe030
movq %rax, (%rsp)
xorl %ebx, %ebx
cmpq $0x20, %rbx
je 0x14562
movl $0x100, %edi            # imm = 0x100
callq 0xe030
movq %rax, %r12
movq (%rsp), %rax
movq %rbx, 0x10(%rsp)
movq %r12, (%rax,%rbx,8)
xorl %ebp, %ebp
cmpq $0x20, %rbp
je 0x14558
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 0x6630a
addq $-0x10, %r14
addq $0x10, %r13
cmpq $-0x200, %r14           # imm = 0xFE00
jne 0x14536
movq %rbx, (%r12,%rbp,8)
incq %rbp
jmp 0x14512
movq 0x10(%rsp), %rbx
incq %rbx
jmp 0x144f0
xorl %ebx, %ebx
movsd 0x7eca4(%rip), %xmm3    # 0x93210
pushq $0x1f
popq %rbp
xorl %r15d, %r15d
movq 0x8(%rsp), %rcx
movslq 0x14(%rcx), %rax
cmpq %rax, %r15
jge 0x14657
movq 0x8(%rcx), %rax
movq (%rax,%r15,8), %rsi
movsd 0x100(%rcx), %xmm0
movsd 0x18(%rsi), %xmm1
subsd %xmm0, %xmm1
mulsd %xmm3, %xmm1
movsd 0x118(%rcx), %xmm2
subsd %xmm0, %xmm2
divsd %xmm2, %xmm1
cvttsd2si %xmm1, %eax
cmpl %ebp, %eax
jl 0x145bb
movl %ebp, %eax
movsd 0x20(%rsi), %xmm0
movq 0x8(%rsp), %rcx
movsd 0x108(%rcx), %xmm1
subsd %xmm1, %xmm0
mulsd %xmm3, %xmm0
movsd 0x120(%rcx), %xmm2
subsd %xmm1, %xmm2
divsd %xmm2, %xmm0
cvttsd2si %xmm0, %ecx
testl %eax, %eax
cmovlel %ebx, %eax
cmpl %ebp, %ecx
jl 0x145f4
movl %ebp, %ecx
movsd 0x28(%rsi), %xmm0
movq 0x8(%rsp), %rdx
movsd 0x110(%rdx), %xmm1
subsd %xmm1, %xmm0
mulsd %xmm3, %xmm0
movsd 0x128(%rdx), %xmm2
subsd %xmm1, %xmm2
divsd %xmm2, %xmm0
cvttsd2si %xmm0, %edi
testl %ecx, %ecx
cmovlel %ebx, %ecx
cmpl %ebp, %edi
jl 0x1462d
movl %ebp, %edi
testl %edi, %edi
cmovlel %ebx, %edi
movq (%rsp), %rdx
movq (%rdx,%rax,8), %rax
shlq $0x4, %rdi
addq (%rax,%rcx,8), %rdi
callq 0x22bfc
incq %r15
movsd 0x7ebbe(%rip), %xmm3    # 0x93210
jmp 0x14572
xorl %ecx, %ecx
cmpq $0x20, %rcx
je 0x1473a
xorl %ebp, %ebp
movq %rcx, 0x18(%rsp)
cmpq $0x20, %rbp
je 0x14732
xorl %r14d, %r14d
cmpq $0x20, %r14
je 0x1472a
movq (%rsp), %rax
movq (%rax,%rcx,8), %rax
movq %rax, %r15
movq (%rax,%rbp,8), %rax
movq %r14, 0x20(%rsp)
shlq $0x4, %r14
movl 0xc(%rax,%r14), %ecx
xorl %edi, %edi
pushq $0x1
popq %rbx
movslq %ecx, %rdx
cmpq %rdx, %rdi
jge 0x14718
movq (%rax,%r14), %rdx
movq %rdi, 0x30(%rsp)
movq (%rdx,%rdi,8), %rdx
movq %rdx, 0x10(%rsp)
leaq 0x18(%rdx), %r12
movq %rbx, 0x28(%rsp)
cmpl %ebx, %ecx
jle 0x14706
movq (%rax,%r14), %rax
movq (%rax,%rbx,8), %r13
leaq 0x18(%r13), %rsi
movq %r12, %rdi
callq 0x40dd7
testl %eax, %eax
je 0x146f8
movq 0x8(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rsp), %rsi
movq %r13, %rdx
callq *0x88(%rax)
incq %rbx
movq (%r15,%rbp,8), %rax
movl 0xc(%rax,%r14), %ecx
jmp 0x146c6
movq 0x30(%rsp), %rdi
incq %rdi
movq 0x28(%rsp), %rbx
incq %rbx
jmp 0x146a3
movq 0x20(%rsp), %r14
incq %r14
movq 0x18(%rsp), %rcx
jmp 0x14677
incq %rbp
jmp 0x1466a
incq %rcx
jmp 0x14659
xorl %ebx, %ebx
cmpq $0x20, %rbx
je 0x147ac
xorl %r12d, %r12d
movq (%rsp), %rax
movq (%rax,%rbx,8), %rdi
cmpq $0x20, %r12
je 0x1479d
movq (%rdi,%r12,8), %r14
testq %r14, %r14
je 0x14798
movq -0x8(%r14), %r15
testq %r15, %r15
je 0x14781
leaq -0x10(%r14), %r13
movq %r15, %rbp
shlq $0x4, %rbp
movq %r13, %rdi
addq %rbp, %rdi
callq 0x66378
addq $-0x10, %rbp
jne 0x14770
addq $-0x8, %r14
shlq $0x4, %r15
orq $0x8, %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xe8f0
incq %r12
jmp 0x14745
testq %rdi, %rdi
je 0x147a7
callq 0xe5d0
incq %rbx
jmp 0x1473c
movq (%rsp), %rdi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xe5d0
movq %rax, %rbx
testq %r14, %r14
je 0x147e4
negq %r14
movq %r15, %r12
addq $-0x8, %r12
leaq (%r12,%r14), %rdi
callq 0x66378
addq $-0x10, %r14
jne 0x147d5
movl $0x208, %esi            # imm = 0x208
movq %r15, %rdi
callq 0xe8f0
movq %rbx, %rdi
callq 0xe810
nop