// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::MaskToLargestConnectedComponent(gaps::R3Grid*, double, double, double)
static int
MaskToLargestConnectedComponent(R3Grid *grid, RNScalar isolevel,
  RNScalar min_component_volume, RNScalar max_component_volume)
{
  // Check grid size
  if (grid->NEntries() == 0) return 0;

  // Get convenient variables
  RNScalar length_scale = grid->WorldToGridScaleFactor();
  RNScalar volume_scale = length_scale * length_scale * length_scale;
  int min_component_size = (int) (min_component_volume * volume_scale);
  int max_component_size = (int) (max_component_volume * volume_scale);
  int status = 0;

  // Allocate temporary memory for connectec components
  int *component_sizes = new int [ grid->NEntries() ];
  int *component_seeds = new int [ grid->NEntries() ];
  int *component_membership = new int [ grid->NEntries() ];

  // Compute connected component of grid
  int ncomponents = grid->ConnectedComponents(isolevel, grid->NEntries(), 
    component_seeds, component_sizes, component_membership);
  if (ncomponents > 0) {
    // Find largest connected component
    int largest_component = -1;
    int largest_component_size = 0;
    for (int i = 0; i < ncomponents; i++) {
      if ((min_component_size > 0) && (component_sizes[i] < min_component_size)) continue;
      if ((max_component_size > 0) && (component_sizes[i] > max_component_size)) continue;
      if (component_sizes[i] > largest_component_size) {
        largest_component_size = component_sizes[i];
        largest_component = i;
      }
    }

    // Zero all grid entries outside connected component
    if (largest_component >= 0) {
      status = 1;
      for (int i = 0; i < grid->NEntries(); i++) {
        if (component_membership[i] == largest_component) grid->SetGridValue(i, 1);
        else grid->SetGridValue(i, 0);
      }
    }
  }

  // Delete temporary memory
  delete [] component_sizes;
  delete [] component_seeds;
  delete [] component_membership;

  // Return status
  return status;
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0x98(%rsp)
movsd %xmm0, 0x90(%rsp)
movsd %xmm1, 0x88(%rsp)
movsd %xmm2, 0x80(%rsp)
movq 0x98(%rsp), %rdi
callq 0x43fd0
cmpl $0x0, %eax
jne 0x39fac
movl $0x0, 0xa4(%rsp)
jmp 0x3a280
movq 0x98(%rsp), %rdi
callq 0x44040
movsd %xmm0, 0x78(%rsp)
movsd 0x78(%rsp), %xmm0
mulsd 0x78(%rsp), %xmm0
mulsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x88(%rsp), %xmm0
mulsd 0x70(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x6c(%rsp)
movsd 0x80(%rsp), %xmm0
mulsd 0x70(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x68(%rsp)
movl $0x0, 0x64(%rsp)
movq 0x98(%rsp), %rdi
callq 0x43fd0
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x13030
movq %rax, 0x58(%rsp)
movq 0x98(%rsp), %rdi
callq 0x43fd0
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x13030
movq %rax, 0x50(%rsp)
movq 0x98(%rsp), %rdi
callq 0x43fd0
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x13030
movq %rax, 0x48(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x20(%rsp)
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movq 0x98(%rsp), %rdi
callq 0x43fd0
movq 0x20(%rsp), %rdi
movsd 0x28(%rsp), %xmm0
movl %eax, %esi
movq 0x50(%rsp), %rdx
movq 0x58(%rsp), %rcx
movq 0x48(%rsp), %r8
callq 0xf24d0
movl %eax, 0x44(%rsp)
cmpl $0x0, 0x44(%rsp)
jle 0x3a229
movl $0xffffffff, 0x40(%rsp) # imm = 0xFFFFFFFF
movl $0x0, 0x3c(%rsp)
movl $0x0, 0x38(%rsp)
movl 0x38(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x3a19a
cmpl $0x0, 0x6c(%rsp)
jle 0x3a143
movq 0x58(%rsp), %rax
movslq 0x38(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0x6c(%rsp), %eax
jge 0x3a143
jmp 0x3a18d
cmpl $0x0, 0x68(%rsp)
jle 0x3a15f
movq 0x58(%rsp), %rax
movslq 0x38(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0x68(%rsp), %eax
jle 0x3a15f
jmp 0x3a18d
movq 0x58(%rsp), %rax
movslq 0x38(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0x3c(%rsp), %eax
jle 0x3a18b
movq 0x58(%rsp), %rax
movslq 0x38(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0x3c(%rsp)
movl 0x38(%rsp), %eax
movl %eax, 0x40(%rsp)
jmp 0x3a18d
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x3a11d
cmpl $0x0, 0x40(%rsp)
jl 0x3a227
movl $0x1, 0x64(%rsp)
movl $0x0, 0x34(%rsp)
movl 0x34(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0x98(%rsp), %rdi
callq 0x43fd0
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x3a225
movq 0x48(%rsp), %rax
movslq 0x34(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl 0x40(%rsp), %eax
jne 0x3a202
movq 0x98(%rsp), %rdi
movl 0x34(%rsp), %esi
movsd 0x169f6d(%rip), %xmm0   # 0x1a4168
callq 0x45490
jmp 0x3a216
movq 0x98(%rsp), %rdi
movl 0x34(%rsp), %esi
xorps %xmm0, %xmm0
callq 0x45490
jmp 0x3a218
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0x3a1b5
jmp 0x3a227
jmp 0x3a229
movq 0x58(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x3a243
movq 0x10(%rsp), %rdi
callq 0x13750
movq 0x50(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x3a25d
movq 0x8(%rsp), %rdi
callq 0x13750
movq 0x48(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x3a275
movq (%rsp), %rdi
callq 0x13750
movl 0x64(%rsp), %eax
movl %eax, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
addq $0xa8, %rsp
retq
nop