// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelTree.cpp
// Function: gaps::R3SurfelTree::SplitBlock(gaps::R3SurfelNode*, gaps::R3SurfelBlock*, gaps::R3SurfelConstraint const&, gaps::R3SurfelBlock**, gaps::R3SurfelBlock**)
int R3SurfelTree::
SplitBlock(R3SurfelNode *node, R3SurfelBlock *block, const R3SurfelConstraint& constraint, 
  R3SurfelBlock **blockA, R3SurfelBlock **blockB)
{
  // Just checking
  assert(node && block);
  assert(block->Node() == node);

  // Check if block is fully outside constraint
  int check = constraint.Check(block);
  if (check == R3_SURFEL_CONSTRAINT_FAIL) { 
    if (blockA) *blockA = NULL;
    if (blockB) *blockB = block;
    return 0;
  }


  // Check if block is fully inside constraint
  if (check == R3_SURFEL_CONSTRAINT_PASS) { 
    if (blockA) *blockA = block;
    if (blockB) *blockB = NULL;
    return 0;
  }

  // Read block
  database->ReadBlock(block);

  // Partition surfels according to constraint
  RNArray<const R3Surfel *> subset1, subset2;
  for (int i = 0; i < block->NSurfels(); i++) {
    const R3Surfel *surfel = block->Surfel(i);
    if (constraint.Check(block, surfel)) subset1.Insert(surfel);
    else subset2.Insert(surfel);
  }

  // Create subset blocks 
  R3SurfelBlock *block1 = NULL;
  R3SurfelBlock *block2 = NULL;
  if (!database->InsertSubsetBlocks(block, subset1, subset2, &block1, &block2) || !block1 || !block2) {
    database->ReleaseBlock(block);
    if (blockA) *blockA = block1;
    if (blockB) *blockB = block2;
    return 0;
  }

  // Update node
  node->InsertBlock(block1); 
  node->InsertBlock(block2); 
  node->RemoveBlock(block);

  // Remove old block
  block->SetDirty(FALSE);
  database->ReleaseBlock(block);
  database->RemoveAndDeleteBlock(block);

  // Return new blocks
  if (blockA) *blockA = block1;
  if (blockB) *blockB = block2;

  // Return success
  return 1;
}

// Assembly:
subq $0xb8, %rsp
movq %rdi, 0xa8(%rsp)
movq %rsi, 0xa0(%rsp)
movq %rdx, 0x98(%rsp)
movq %rcx, 0x90(%rsp)
movq %r8, 0x88(%rsp)
movq %r9, 0x80(%rsp)
movq 0xa8(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x90(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq (%rdi), %rax
callq *0x20(%rax)
movl %eax, 0x7c(%rsp)
cmpl $0x0, 0x7c(%rsp)
jne 0x657ed
cmpq $0x0, 0x88(%rsp)
je 0x657bf
movq 0x88(%rsp), %rax
movq $0x0, (%rax)
cmpq $0x0, 0x80(%rsp)
je 0x657dd
movq 0x98(%rsp), %rcx
movq 0x80(%rsp), %rax
movq %rcx, (%rax)
movl $0x0, 0xb4(%rsp)
jmp 0x65b12
cmpl $0x2, 0x7c(%rsp)
jne 0x6583c
cmpq $0x0, 0x88(%rsp)
je 0x65812
movq 0x98(%rsp), %rcx
movq 0x88(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0x80(%rsp)
je 0x6582c
movq 0x80(%rsp), %rax
movq $0x0, (%rax)
movl $0x0, 0xb4(%rsp)
jmp 0x65b12
movq 0x20(%rsp), %rax
movq 0x10(%rax), %rdi
movq 0x98(%rsp), %rsi
callq 0x31140
leaq 0x68(%rsp), %rdi
callq 0x662e0
leaq 0x58(%rsp), %rdi
callq 0x662e0
jmp 0x65868
movl $0x0, 0x48(%rsp)
movl 0x48(%rsp), %eax
movl %eax, 0x18(%rsp)
movq 0x98(%rsp), %rdi
callq 0x1c0e0
movl %eax, 0x1c(%rsp)
jmp 0x6588b
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x65952
movq 0x98(%rsp), %rdi
movl 0x48(%rsp), %esi
callq 0x43660
movq %rax, 0x10(%rsp)
jmp 0x658b3
movq 0x10(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x90(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq 0x40(%rsp), %rdx
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
movl %eax, 0xc(%rsp)
jmp 0x658e1
movl 0xc(%rsp), %eax
cmpl $0x0, %eax
je 0x6592d
movq 0x40(%rsp), %rsi
leaq 0x68(%rsp), %rdi
callq 0x662f0
jmp 0x658fb
jmp 0x65940
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
jmp 0x65b06
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x66320
jmp 0x65b06
movq 0x40(%rsp), %rsi
leaq 0x58(%rsp), %rdi
callq 0x662f0
jmp 0x6593e
jmp 0x65940
jmp 0x65942
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0x65870
movq 0x20(%rsp), %rax
movq $0x0, 0x38(%rsp)
movq $0x0, 0x30(%rsp)
movq 0x10(%rax), %rdi
movq 0x98(%rsp), %rsi
movq (%rdi), %rax
movq 0x28(%rax), %rax
leaq 0x68(%rsp), %rdx
leaq 0x58(%rsp), %rcx
leaq 0x38(%rsp), %r8
leaq 0x30(%rsp), %r9
callq *%rax
movl %eax, 0x8(%rsp)
jmp 0x65998
movl 0x8(%rsp), %eax
cmpl $0x0, %eax
je 0x659b1
cmpq $0x0, 0x38(%rsp)
je 0x659b1
cmpq $0x0, 0x30(%rsp)
jne 0x65a17
movq 0x20(%rsp), %rax
movq 0x10(%rax), %rdi
movq 0x98(%rsp), %rsi
callq 0x311c0
jmp 0x659c9
cmpq $0x0, 0x88(%rsp)
je 0x659e4
movq 0x38(%rsp), %rcx
movq 0x88(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0x80(%rsp)
je 0x659ff
movq 0x30(%rsp), %rcx
movq 0x80(%rsp), %rax
movq %rcx, (%rax)
movl $0x0, 0xb4(%rsp)
movl $0x1, 0x2c(%rsp)
jmp 0x65af0
movq 0xa0(%rsp), %rdi
movq 0x38(%rsp), %rsi
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
jmp 0x65a2f
movq 0xa0(%rsp), %rdi
movq 0x30(%rsp), %rsi
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
jmp 0x65a47
movq 0xa0(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq (%rdi), %rax
movq 0x30(%rax), %rax
callq *%rax
jmp 0x65a62
movq 0x98(%rsp), %rdi
xorl %esi, %esi
callq 0x4b240
jmp 0x65a73
movq 0x20(%rsp), %rax
movq 0x10(%rax), %rdi
movq 0x98(%rsp), %rsi
callq 0x311c0
jmp 0x65a8b
movq 0x20(%rsp), %rax
movq 0x10(%rax), %rdi
movq 0x98(%rsp), %rsi
movq (%rdi), %rax
movq 0x20(%rax), %rax
callq *%rax
jmp 0x65aa7
cmpq $0x0, 0x88(%rsp)
je 0x65ac2
movq 0x38(%rsp), %rcx
movq 0x88(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0x80(%rsp)
je 0x65add
movq 0x30(%rsp), %rcx
movq 0x80(%rsp), %rax
movq %rcx, (%rax)
movl $0x1, 0xb4(%rsp)
movl $0x1, 0x2c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x66320
leaq 0x68(%rsp), %rdi
callq 0x66320
jmp 0x65b12
leaq 0x68(%rsp), %rdi
callq 0x66320
jmp 0x65b21
movl 0xb4(%rsp), %eax
addq $0xb8, %rsp
retq
movq 0x50(%rsp), %rdi
callq 0x13970
nopl (%rax,%rax)