// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Grid.cpp
// Function: gaps::R3Grid::ConnectedComponents(double, int, int*, int*, int*)
int R3Grid::
ConnectedComponents(RNScalar isolevel, int max_components, int *seeds, int *sizes, int *grid_components)
{
  // Allocate array of component identifiers
  int *components = grid_components;
  if (!grid_components) {
    components = new int [ grid_size ];
    assert(components);
  }

  // Initialize array of components
  for (int i = 0; i < grid_size; i++) 
    components[i] = -1;

  // Find connected components
  int ncomponents = 0;
  int next_seed = 0;
  while (TRUE){
    // Find unmarked seed
    int seed = next_seed;
    while (seed < grid_size) { 
      if ((components[seed] < 0) && (grid_values[seed] > isolevel)) break;
      seed++;
    }

    // Check if found a seed
    if (seed >= grid_size) break;

    // Flood fill marking all grid entries 6-connected to seed
    int x, y, z, neighbor;
    int size = 0;
    RNArray<RNScalar *> stack;
    stack.Insert(&grid_values[seed]);
    components[seed] = ncomponents;
    while (!stack.IsEmpty()) {
      // Pop top of stack
      RNScalar *c = stack.Tail();
      stack.RemoveTail();

      // Add grid entry to component
      int index = c - grid_values;
      assert(index >= 0);
      assert(index < grid_size);
      assert(components[index] == ncomponents);
      assert(grid_values[index] > isolevel);

      // Add neighbors to stack
      IndexToIndices(index, x, y, z);
      if (x > 0) {
        IndicesToIndex(x-1, y, z, neighbor);
        if ((components[neighbor] < 0) && (grid_values[neighbor] > isolevel)) {
          components[neighbor] = ncomponents;
          stack.Insert(&grid_values[neighbor]);
        }
      }
      if (x < XResolution()-1) {
        IndicesToIndex(x+1, y, z, neighbor);
        if ((components[neighbor] < 0) && (grid_values[neighbor] > isolevel)) {
          components[neighbor] = ncomponents;
          stack.Insert(&grid_values[neighbor]);
        }
      }
      if (y > 0) {
        IndicesToIndex(x, y-1, z, neighbor);
        if ((components[neighbor] < 0) && (grid_values[neighbor] > isolevel)) {
          components[neighbor] = ncomponents;
          stack.Insert(&grid_values[neighbor]);
        }
      }
      if (y < YResolution()-1) {
        IndicesToIndex(x, y+1, z, neighbor);
        if ((components[neighbor] < 0) && (grid_values[neighbor] > isolevel)) { 
          components[neighbor] = ncomponents;
          stack.Insert(&grid_values[neighbor]);
        }
      }
      if (z > 0) {
        IndicesToIndex(x, y, z-1, neighbor);
        if ((components[neighbor] < 0) && (grid_values[neighbor] > isolevel)) {
          components[neighbor] = ncomponents;
          stack.Insert(&grid_values[neighbor]);
        }
      }
      if (z < ZResolution()-1) {
        IndicesToIndex(x, y, z+1, neighbor);
        if ((components[neighbor] < 0) && (grid_values[neighbor] > isolevel)) {
          components[neighbor] = ncomponents;
          stack.Insert(&grid_values[neighbor]);
        }
      }

      // Increment component_size
      size++;
    }

    // Update output variables
    if (ncomponents < max_components) {
      if (seeds) seeds[ncomponents] = seed;
      if (sizes) sizes[ncomponents] = size;
    }

    // Increment the number of components
    ncomponents++;
  }


  // Delete components
  if (!grid_components) delete [] components;

  // Return number of connected components found
  return ncomponents;
}

// Assembly:
subq $0xd8, %rsp
movq %rdi, 0xd0(%rsp)
movsd %xmm0, 0xc8(%rsp)
movl %esi, 0xc4(%rsp)
movq %rdx, 0xb8(%rsp)
movq %rcx, 0xb0(%rsp)
movq %r8, 0xa8(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0xa8(%rsp), %rax
movq %rax, 0xa0(%rsp)
cmpq $0x0, 0xa8(%rsp)
jne 0x68e74
movq 0x40(%rsp), %rax
movslq 0x24c(%rax), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, 0xa0(%rsp)
movl $0x0, 0x9c(%rsp)
movq 0x40(%rsp), %rcx
movl 0x9c(%rsp), %eax
cmpl 0x24c(%rcx), %eax
jge 0x68ebd
movq 0xa0(%rsp), %rax
movslq 0x9c(%rsp), %rcx
movl $0xffffffff, (%rax,%rcx,4) # imm = 0xFFFFFFFF
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x68e7f
movl $0x0, 0x98(%rsp)
movl $0x0, 0x94(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0x90(%rsp)
movq 0x40(%rsp), %rcx
movl 0x90(%rsp), %eax
cmpl 0x24c(%rcx), %eax
jge 0x68f44
movq 0xa0(%rsp), %rax
movslq 0x90(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x68f31
movq 0x40(%rsp), %rax
movq 0x230(%rax), %rax
movslq 0x90(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0xc8(%rsp), %xmm0
jbe 0x68f31
jmp 0x68f44
movl 0x90(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x90(%rsp)
jmp 0x68ee1
movq 0x40(%rsp), %rcx
movl 0x90(%rsp), %eax
cmpl 0x24c(%rcx), %eax
jl 0x68f5d
jmp 0x69585
movl $0x0, 0x7c(%rsp)
leaq 0x68(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x6bea0
movq 0x40(%rsp), %rax
movq 0x38(%rsp), %rdi
movq 0x230(%rax), %rax
movslq 0x90(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
callq 0x6beb0
jmp 0x68f98
movl 0x98(%rsp), %edx
movq 0xa0(%rsp), %rax
movslq 0x90(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
leaq 0x68(%rsp), %rdi
callq 0x36e30
movl %eax, 0x34(%rsp)
jmp 0x68fc2
movl 0x34(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x68fd7
jmp 0x6950c
leaq 0x68(%rsp), %rdi
callq 0x6bee0
movq %rax, 0x28(%rsp)
jmp 0x68fe8
movq 0x28(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0x68(%rsp), %rdi
callq 0x36e60
jmp 0x68ffe
movq 0x40(%rsp), %rdi
movq 0x50(%rsp), %rax
movq 0x230(%rdi), %rcx
subq %rcx, %rax
shrq $0x3, %rax
movl %eax, 0x4c(%rsp)
movl 0x4c(%rsp), %esi
leaq 0x8c(%rsp), %rdx
leaq 0x88(%rsp), %rcx
leaq 0x84(%rsp), %r8
callq 0x6bef0
jmp 0x6903d
cmpl $0x0, 0x8c(%rsp)
jle 0x69113
movq 0x40(%rsp), %rdi
movl 0x8c(%rsp), %esi
decl %esi
movl 0x88(%rsp), %edx
movl 0x84(%rsp), %ecx
leaq 0x80(%rsp), %r8
callq 0x6bd30
jmp 0x69076
movq 0xa0(%rsp), %rax
movslq 0x80(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x69111
movq 0x40(%rsp), %rax
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0xc8(%rsp), %xmm0
jbe 0x69111
movq 0x40(%rsp), %rax
movl 0x98(%rsp), %esi
movq 0xa0(%rsp), %rcx
movslq 0x80(%rsp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x68(%rsp), %rdi
callq 0x6beb0
jmp 0x690f2
jmp 0x69111
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x60(%rsp)
movl %eax, 0x5c(%rsp)
leaq 0x68(%rsp), %rdi
callq 0x6bf60
jmp 0x695be
jmp 0x69113
movq 0x40(%rsp), %rdi
movl 0x8c(%rsp), %eax
movl %eax, 0x20(%rsp)
callq 0x138c0
movl %eax, 0x24(%rsp)
jmp 0x6912e
movl 0x20(%rsp), %eax
movl 0x24(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x691e8
movq 0x40(%rsp), %rdi
movl 0x8c(%rsp), %esi
incl %esi
movl 0x88(%rsp), %edx
movl 0x84(%rsp), %ecx
leaq 0x80(%rsp), %r8
callq 0x6bd30
jmp 0x6916c
movq 0xa0(%rsp), %rax
movslq 0x80(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x691e6
movq 0x40(%rsp), %rax
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0xc8(%rsp), %xmm0
jbe 0x691e6
movq 0x40(%rsp), %rax
movl 0x98(%rsp), %esi
movq 0xa0(%rsp), %rcx
movslq 0x80(%rsp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x68(%rsp), %rdi
callq 0x6beb0
jmp 0x691e4
jmp 0x691e6
jmp 0x691e8
cmpl $0x0, 0x88(%rsp)
jle 0x6929d
movq 0x40(%rsp), %rdi
movl 0x8c(%rsp), %esi
movl 0x88(%rsp), %edx
decl %edx
movl 0x84(%rsp), %ecx
leaq 0x80(%rsp), %r8
callq 0x6bd30
jmp 0x69221
movq 0xa0(%rsp), %rax
movslq 0x80(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x6929b
movq 0x40(%rsp), %rax
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0xc8(%rsp), %xmm0
jbe 0x6929b
movq 0x40(%rsp), %rax
movl 0x98(%rsp), %esi
movq 0xa0(%rsp), %rcx
movslq 0x80(%rsp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x68(%rsp), %rdi
callq 0x6beb0
jmp 0x69299
jmp 0x6929b
jmp 0x6929d
movq 0x40(%rsp), %rdi
movl 0x88(%rsp), %eax
movl %eax, 0x18(%rsp)
callq 0x138e0
movl %eax, 0x1c(%rsp)
jmp 0x692b8
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x69372
movq 0x40(%rsp), %rdi
movl 0x8c(%rsp), %esi
movl 0x88(%rsp), %edx
incl %edx
movl 0x84(%rsp), %ecx
leaq 0x80(%rsp), %r8
callq 0x6bd30
jmp 0x692f6
movq 0xa0(%rsp), %rax
movslq 0x80(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x69370
movq 0x40(%rsp), %rax
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0xc8(%rsp), %xmm0
jbe 0x69370
movq 0x40(%rsp), %rax
movl 0x98(%rsp), %esi
movq 0xa0(%rsp), %rcx
movslq 0x80(%rsp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x68(%rsp), %rdi
callq 0x6beb0
jmp 0x6936e
jmp 0x69370
jmp 0x69372
cmpl $0x0, 0x84(%rsp)
jle 0x69427
movq 0x40(%rsp), %rdi
movl 0x8c(%rsp), %esi
movl 0x88(%rsp), %edx
movl 0x84(%rsp), %ecx
decl %ecx
leaq 0x80(%rsp), %r8
callq 0x6bd30
jmp 0x693ab
movq 0xa0(%rsp), %rax
movslq 0x80(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x69425
movq 0x40(%rsp), %rax
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0xc8(%rsp), %xmm0
jbe 0x69425
movq 0x40(%rsp), %rax
movl 0x98(%rsp), %esi
movq 0xa0(%rsp), %rcx
movslq 0x80(%rsp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x68(%rsp), %rdi
callq 0x6beb0
jmp 0x69423
jmp 0x69425
jmp 0x69427
movq 0x40(%rsp), %rdi
movl 0x84(%rsp), %eax
movl %eax, 0x10(%rsp)
callq 0x13900
movl %eax, 0x14(%rsp)
jmp 0x69442
movl 0x10(%rsp), %eax
movl 0x14(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x694fc
movq 0x40(%rsp), %rdi
movl 0x8c(%rsp), %esi
movl 0x88(%rsp), %edx
movl 0x84(%rsp), %ecx
incl %ecx
leaq 0x80(%rsp), %r8
callq 0x6bd30
jmp 0x69480
movq 0xa0(%rsp), %rax
movslq 0x80(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jge 0x694fa
movq 0x40(%rsp), %rax
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
ucomisd 0xc8(%rsp), %xmm0
jbe 0x694fa
movq 0x40(%rsp), %rax
movl 0x98(%rsp), %esi
movq 0xa0(%rsp), %rcx
movslq 0x80(%rsp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x230(%rax), %rax
movslq 0x80(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x68(%rsp), %rdi
callq 0x6beb0
jmp 0x694f8
jmp 0x694fa
jmp 0x694fc
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x68fb2
movl 0x98(%rsp), %eax
cmpl 0xc4(%rsp), %eax
jge 0x69565
cmpq $0x0, 0xb8(%rsp)
je 0x69541
movl 0x90(%rsp), %edx
movq 0xb8(%rsp), %rax
movslq 0x98(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
cmpq $0x0, 0xb0(%rsp)
je 0x69563
movl 0x7c(%rsp), %edx
movq 0xb0(%rsp), %rax
movslq 0x98(%rsp), %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x69565
movl 0x98(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x98(%rsp)
leaq 0x68(%rsp), %rdi
callq 0x6bf60
jmp 0x68ed3
cmpq $0x0, 0xa8(%rsp)
jne 0x695af
movq 0xa0(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x695ad
movq 0x8(%rsp), %rdi
callq 0xf670
jmp 0x695af
movl 0x98(%rsp), %eax
addq $0xd8, %rsp
retq
movq 0x60(%rsp), %rdi
callq 0xf890
nopl (%rax,%rax)