// File: /workspace/github_c_makefile_star2_O0/zpole[P]IICV/vl/kdtree.c
// Function: vl_kdforest_query_recursively
vl_uindex
vl_kdforest_query_recursively (VlKDForestSearcher * searcher,
                               VlKDTree * tree,
                               vl_uindex nodeIndex,
                               VlKDForestNeighbor * neighbors,
                               vl_size numNeighbors,
                               vl_size * numAddedNeighbors,
                               double dist,
                               void const * query)
{

  VlKDTreeNode const * node = tree->nodes + nodeIndex ;
  vl_uindex i = node->splitDimension ;
  vl_index nextChild, saveChild ;
  double delta, saveDist ;
  double x ;
  double x1 = node->lowerBound ;
  double x2 = node->splitThreshold ;
  double x3 = node->upperBound ;
  VlKDForestSearchState * searchState ;

  searcher->searchNumRecursions ++ ;

  switch (searcher->forest->dataType) {
    case VL_TYPE_FLOAT :
      x = ((float const*) query)[i] ;
      break ;
    case VL_TYPE_DOUBLE :
      x = ((double const*) query)[i] ;
      break ;
    default :
      abort() ;
  }

  /* base case: this is a leaf node */
  if (node->lowerChild < 0) {

    vl_index begin = - node->lowerChild - 1 ;
    vl_index end   = - node->upperChild - 1 ;
    vl_index iter ;

    for (iter = begin ;
         iter < end &&
         (searcher->forest->searchMaxNumComparisons == 0 ||
          searcher->searchNumComparisons < searcher->forest->searchMaxNumComparisons) ;
         ++ iter) {

      vl_index di = tree->dataIndex [iter].index ;

      /* multiple KDTrees share the database points and we must avoid
       * adding the same point twice */
      if (searcher->searchIdBook[di] == searcher->searchId) continue ;
      searcher->searchIdBook[di] = searcher->searchId ;

      /* compare the query to this point */
      switch (searcher->forest->dataType) {
        case VL_TYPE_FLOAT:
          dist = ((VlFloatVectorComparisonFunction)searcher->forest->distanceFunction)
                 (searcher->forest->dimension,
                  ((float const *)query),
                  ((float const*)searcher->forest->data) + di * searcher->forest->dimension) ;
          break ;
        case VL_TYPE_DOUBLE:
          dist = ((VlDoubleVectorComparisonFunction)searcher->forest->distanceFunction)
                 (searcher->forest->dimension,
                  ((double const *)query),
                  ((double const*)searcher->forest->data) + di * searcher->forest->dimension) ;
          break ;
        default:
          abort() ;
      }
      searcher->searchNumComparisons += 1 ;

      /* see if it should be added to the result set */
      if (*numAddedNeighbors < numNeighbors) {
        VlKDForestNeighbor * newNeighbor = neighbors + *numAddedNeighbors ;
        newNeighbor->index = di ;
        newNeighbor->distance = dist ;
        vl_kdforest_neighbor_heap_push (neighbors, numAddedNeighbors) ;
      } else {
        VlKDForestNeighbor * largestNeighbor = neighbors + 0 ;
        if (largestNeighbor->distance > dist) {
          largestNeighbor->index = di ;
          largestNeighbor->distance = dist ;
          vl_kdforest_neighbor_heap_update (neighbors, *numAddedNeighbors, 0) ;
        }
      }
    } /* next data point */


    return nodeIndex ;
  }

#if 0
  assert (x1 <= x2 && x2 <= x3) ;
  assert (node->lowerChild >= 0) ;
  assert (node->upperChild >= 0) ;
#endif

  /*
   *   x1  x2 x3
   * x (---|---]
   *   (--x|---]
   *   (---|x--]
   *   (---|---] x
   */

  delta = x - x2 ;
  saveDist = dist + delta*delta ;

  if (x <= x2) {
    nextChild = node->lowerChild ;
    saveChild = node->upperChild ;
    if (x <= x1) {
      delta = x - x1 ;
      saveDist -= delta*delta ;
    }
  } else {
    nextChild = node->upperChild ;
    saveChild = node->lowerChild ;
    if (x > x3) {
      delta = x - x3 ;
      saveDist -= delta*delta ;
    }
  }

  if (*numAddedNeighbors < numNeighbors || neighbors[0].distance > saveDist) {
    searchState = searcher->searchHeapArray + searcher->searchHeapNumNodes ;
    searchState->tree = tree ;
    searchState->nodeIndex = saveChild ;
    searchState->distanceLowerBound = saveDist ;
    vl_kdforest_search_heap_push (searcher->searchHeapArray ,
                                  &searcher->searchHeapNumNodes) ;
  }

  return vl_kdforest_query_recursively (searcher,
                                        tree,
                                        nextChild,
                                        neighbors,
                                        numNeighbors,
                                        numAddedNeighbors,
                                        dist,
                                        query) ;
}

// Assembly:
subq $0xe8, %rsp
movq 0xf0(%rsp), %rax
movq %rdi, 0xd8(%rsp)
movq %rsi, 0xd0(%rsp)
movq %rdx, 0xc8(%rsp)
movq %rcx, 0xc0(%rsp)
movq %r8, 0xb8(%rsp)
movq %r9, 0xb0(%rsp)
movsd %xmm0, 0xa8(%rsp)
movq 0xd0(%rsp), %rax
movq (%rax), %rax
movq 0xc8(%rsp), %rcx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
movl 0x18(%rax), %eax
movq %rax, 0x98(%rsp)
movq 0xa0(%rsp), %rax
movsd 0x28(%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq 0xa0(%rsp), %rax
movsd 0x20(%rax), %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0xa0(%rsp), %rax
movsd 0x30(%rax), %xmm0
movsd %xmm0, 0x58(%rsp)
movq 0xd8(%rsp), %rax
movq 0x30(%rax), %rcx
incq %rcx
movq %rcx, 0x30(%rax)
movq 0xd8(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x10(%rax), %eax
movl %eax, 0x1c(%rsp)
subl $0x1, %eax
je 0x2d22e
jmp 0x2d223
movl 0x1c(%rsp), %eax
subl $0x2, %eax
je 0x2d24f
jmp 0x2d26c
movq 0xf0(%rsp), %rax
movq 0x98(%rsp), %rcx
movss (%rax,%rcx,4), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x70(%rsp)
jmp 0x2d271
movq 0xf0(%rsp), %rax
movq 0x98(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, 0x70(%rsp)
jmp 0x2d271
callq 0x90b0
movq 0xa0(%rsp), %rax
cmpq $0x0, 0x8(%rax)
jge 0x2d57f
movq 0xa0(%rsp), %rcx
xorl %eax, %eax
subq 0x8(%rcx), %rax
subq $0x1, %rax
movq %rax, 0x48(%rsp)
movq 0xa0(%rsp), %rcx
xorl %eax, %eax
subq 0x10(%rcx), %rax
subq $0x1, %rax
movq %rax, 0x40(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rcx
xorl %eax, %eax
cmpq 0x40(%rsp), %rcx
movb %al, 0x1b(%rsp)
jge 0x2d318
movq 0xd8(%rsp), %rax
movq 0x20(%rax), %rcx
movb $0x1, %al
cmpq $0x0, 0xe0(%rcx)
movb %al, 0x1a(%rsp)
je 0x2d310
movq 0xd8(%rsp), %rax
movq 0x28(%rax), %rax
movq 0xd8(%rsp), %rcx
movq 0x20(%rcx), %rcx
cmpq 0xe0(%rcx), %rax
setb %al
movb %al, 0x1a(%rsp)
movb 0x1a(%rsp), %al
movb %al, 0x1b(%rsp)
movb 0x1b(%rsp), %al
testb $0x1, %al
jne 0x2d325
jmp 0x2d56a
movq 0xd0(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x38(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rax
movq %rax, 0x30(%rsp)
movq 0xd8(%rsp), %rax
movq 0x10(%rax), %rax
movq 0x30(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq 0xd8(%rsp), %rcx
cmpq 0x48(%rcx), %rax
jne 0x2d36d
jmp 0x2d557
movq 0xd8(%rsp), %rcx
movq 0x10(%rcx), %rax
movq 0x48(%rcx), %rdx
movq 0x30(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0xd8(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x10(%rax), %eax
movl %eax, 0x14(%rsp)
subl $0x1, %eax
je 0x2d3ae
jmp 0x2d3a0
movl 0x14(%rsp), %eax
subl $0x2, %eax
je 0x2d412
jmp 0x2d472
movq 0xd8(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x30(%rax), %rax
movq 0xd8(%rsp), %rcx
movq 0x20(%rcx), %rcx
movq (%rcx), %rdi
movq 0xf0(%rsp), %rsi
movq 0xd8(%rsp), %rcx
movq 0x20(%rcx), %rcx
movq 0x18(%rcx), %rdx
movq 0x30(%rsp), %rcx
movq 0xd8(%rsp), %r8
movq 0x20(%r8), %r8
imulq (%r8), %rcx
shlq $0x2, %rcx
addq %rcx, %rdx
callq *%rax
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0xa8(%rsp)
jmp 0x2d477
movq 0xd8(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x30(%rax), %rax
movq 0xd8(%rsp), %rcx
movq 0x20(%rcx), %rcx
movq (%rcx), %rdi
movq 0xf0(%rsp), %rsi
movq 0xd8(%rsp), %rcx
movq 0x20(%rcx), %rcx
movq 0x18(%rcx), %rdx
movq 0x30(%rsp), %rcx
movq 0xd8(%rsp), %r8
movq 0x20(%r8), %r8
imulq (%r8), %rcx
shlq $0x3, %rcx
addq %rcx, %rdx
callq *%rax
movsd %xmm0, 0xa8(%rsp)
jmp 0x2d477
callq 0x90b0
movq 0xd8(%rsp), %rax
movq 0x28(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x28(%rax)
movq 0xb0(%rsp), %rax
movq (%rax), %rax
cmpq 0xb8(%rsp), %rax
jae 0x2d4f6
movq 0xc0(%rsp), %rax
movq 0xb0(%rsp), %rcx
movq (%rcx), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0x8(%rax)
movsd 0xa8(%rsp), %xmm0
movq 0x28(%rsp), %rax
movsd %xmm0, (%rax)
movq 0xc0(%rsp), %rdi
movq 0xb0(%rsp), %rsi
callq 0x2d7f0
jmp 0x2d555
movq 0xc0(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rax
movsd (%rax), %xmm0
ucomisd 0xa8(%rsp), %xmm0
jbe 0x2d553
movq 0x30(%rsp), %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x8(%rax)
movsd 0xa8(%rsp), %xmm0
movq 0x20(%rsp), %rax
movsd %xmm0, (%rax)
movq 0xc0(%rsp), %rdi
movq 0xb0(%rsp), %rax
movq (%rax), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x2d830
jmp 0x2d555
jmp 0x2d557
movq 0x38(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x38(%rsp)
jmp 0x2d2bc
movq 0xc8(%rsp), %rax
movq %rax, 0xe0(%rsp)
jmp 0x2d7d8
movsd 0x70(%rsp), %xmm0
subsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0xa8(%rsp), %xmm1
movsd 0x80(%rsp), %xmm0
movsd 0x80(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
movsd 0x70(%rsp), %xmm1
movsd 0x60(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x2d664
movq 0xa0(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x90(%rsp)
movq 0xa0(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x88(%rsp)
movsd 0x70(%rsp), %xmm1
movsd 0x68(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x2d65f
movsd 0x70(%rsp), %xmm0
subsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x80(%rsp), %xmm0
movsd 0x80(%rsp), %xmm2
movsd 0x78(%rsp), %xmm1
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
jmp 0x2d6ee
movq 0xa0(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x90(%rsp)
movq 0xa0(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x88(%rsp)
movsd 0x70(%rsp), %xmm0
ucomisd 0x58(%rsp), %xmm0
jbe 0x2d6ec
movsd 0x70(%rsp), %xmm0
subsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x80(%rsp), %xmm0
movsd 0x80(%rsp), %xmm2
movsd 0x78(%rsp), %xmm1
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
jmp 0x2d6ee
movq 0xb0(%rsp), %rax
movq (%rax), %rax
cmpq 0xb8(%rsp), %rax
jb 0x2d717
movq 0xc0(%rsp), %rax
movsd (%rax), %xmm0
ucomisd 0x78(%rsp), %xmm0
jbe 0x2d786
movq 0xd8(%rsp), %rax
movq 0x18(%rax), %rax
movq 0xd8(%rsp), %rcx
imulq $0x18, 0x40(%rcx), %rcx
addq %rcx, %rax
movq %rax, 0x50(%rsp)
movq 0xd0(%rsp), %rcx
movq 0x50(%rsp), %rax
movq %rcx, (%rax)
movq 0x88(%rsp), %rcx
movq 0x50(%rsp), %rax
movq %rcx, 0x8(%rax)
movsd 0x78(%rsp), %xmm0
movq 0x50(%rsp), %rax
movsd %xmm0, 0x10(%rax)
movq 0xd8(%rsp), %rax
movq 0x18(%rax), %rdi
movq 0xd8(%rsp), %rsi
addq $0x40, %rsi
callq 0x2d870
movq 0xd8(%rsp), %rdi
movq 0xd0(%rsp), %rsi
movq 0x90(%rsp), %rdx
movq 0xc0(%rsp), %rcx
movq 0xb8(%rsp), %r8
movq 0xb0(%rsp), %r9
movsd 0xa8(%rsp), %xmm0
movq 0xf0(%rsp), %rax
movq %rax, (%rsp)
callq 0x2d140
movq %rax, 0xe0(%rsp)
movq 0xe0(%rsp), %rax
addq $0xe8, %rsp
retq
nopl (%rax,%rax)