kdtree.c
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00008 All rights reserved.
00009 
00010 This file is part of the VLFeat library and is made available under
00011 the terms of the BSD license (see the COPYING file).
00012 */
00013 
00089 #include "kdtree.h"
00090 #include "generic.h"
00091 #include "random.h"
00092 #include "mathop.h"
00093 #include <stdlib.h>
00094 
00095 #if defined(_OPENMP)
00096 #include <omp.h>
00097 #endif
00098 
00099 #define VL_HEAP_prefix     vl_kdforest_search_heap
00100 #define VL_HEAP_type       VlKDForestSearchState
00101 #define VL_HEAP_cmp(v,x,y) (v[x].distanceLowerBound - v[y].distanceLowerBound)
00102 #include "heap-def.h"
00103 
00104 #define VL_HEAP_prefix     vl_kdtree_split_heap
00105 #define VL_HEAP_type       VlKDTreeSplitDimension
00106 #define VL_HEAP_cmp(v,x,y) (v[x].variance - v[y].variance)
00107 #include "heap-def.h"
00108 
00109 #define VL_HEAP_prefix     vl_kdforest_neighbor_heap
00110 #define VL_HEAP_type       VlKDForestNeighbor
00111 #define VL_HEAP_cmp(v,x,y) (v[y].distance - v[x].distance)
00112 #include "heap-def.h"
00113 
00119 static vl_uindex
00120 vl_kdtree_node_new (VlKDTree * tree, vl_uindex parentIndex)
00121 {
00122   VlKDTreeNode * node = NULL ;
00123   vl_uindex nodeIndex = tree->numUsedNodes ;
00124   tree -> numUsedNodes += 1 ;
00125 
00126   assert (tree->numUsedNodes <= tree->numAllocatedNodes) ;
00127 
00128   node = tree->nodes + nodeIndex ;
00129   node -> parent = parentIndex ;
00130   node -> lowerChild = 0 ;
00131   node -> upperChild = 0 ;
00132   node -> splitDimension = 0 ;
00133   node -> splitThreshold = 0 ;
00134   return nodeIndex ;
00135 }
00136 
00142 VL_INLINE int
00143 vl_kdtree_compare_index_entries (void const * a,
00144                                  void const * b)
00145 {
00146   double delta =
00147     ((VlKDTreeDataIndexEntry const*)a) -> value -
00148     ((VlKDTreeDataIndexEntry const*)b) -> value ;
00149   if (delta < 0) return -1 ;
00150   if (delta > 0) return +1 ;
00151   return 0 ;
00152 }
00153 
00165 static void
00166 vl_kdtree_build_recursively
00167 (VlKDForest * forest,
00168  VlKDTree * tree, vl_uindex nodeIndex,
00169  vl_uindex dataBegin, vl_uindex dataEnd,
00170  unsigned int depth)
00171 {
00172   vl_uindex d, i, medianIndex, splitIndex ;
00173   VlKDTreeNode * node = tree->nodes + nodeIndex ;
00174   VlKDTreeSplitDimension * splitDimension ;
00175 
00176   /* base case: there is only one data point */
00177   if (dataEnd - dataBegin <= 1) {
00178     if (tree->depth < depth) tree->depth = depth ;
00179     node->lowerChild = - dataBegin - 1;
00180     node->upperChild = - dataEnd - 1 ;
00181     return ;
00182   }
00183 
00184   /* compute the dimension with largest variance > 0 */
00185   forest->splitHeapNumNodes = 0 ;
00186   for (d = 0 ; d < forest->dimension ; ++ d) {
00187     double mean = 0 ; /* unnormalized */
00188     double secondMoment = 0 ;
00189     double variance = 0 ;
00190     vl_size numSamples = VL_KDTREE_VARIANCE_EST_NUM_SAMPLES;
00191     vl_bool useAllData = VL_FALSE;
00192 
00193     if(dataEnd - dataBegin <= VL_KDTREE_VARIANCE_EST_NUM_SAMPLES) {
00194       useAllData = VL_TRUE;
00195       numSamples = dataEnd - dataBegin;
00196     }
00197 
00198     for (i = 0; i < numSamples ; ++ i) {
00199       vl_uint32 sampleIndex;
00200       vl_index di;
00201       double datum ;
00202 
00203       if(useAllData == VL_TRUE) {
00204         sampleIndex = (vl_uint32)i;
00205       } else {
00206         sampleIndex = (vl_rand_uint32(forest->rand) % VL_KDTREE_VARIANCE_EST_NUM_SAMPLES);
00207       }
00208       sampleIndex += dataBegin;
00209 
00210       di = tree->dataIndex[sampleIndex].index ;
00211 
00212       switch(forest->dataType) {
00213         case VL_TYPE_FLOAT: datum = ((float const*)forest->data)
00214           [di * forest->dimension + d] ;
00215           break ;
00216         case VL_TYPE_DOUBLE: datum = ((double const*)forest->data)
00217           [di * forest->dimension + d] ;
00218           break ;
00219         default:
00220           abort() ;
00221       }
00222       mean += datum ;
00223       secondMoment += datum * datum ;
00224     }
00225 
00226     mean /= numSamples ;
00227     secondMoment /= numSamples ;
00228     variance = secondMoment - mean * mean ;
00229 
00230     if (variance <= 0) continue ;
00231 
00232     /* keep splitHeapSize most varying dimensions */
00233     if (forest->splitHeapNumNodes < forest->splitHeapSize) {
00234       VlKDTreeSplitDimension * splitDimension
00235         = forest->splitHeapArray + forest->splitHeapNumNodes ;
00236       splitDimension->dimension = (unsigned int)d ;
00237       splitDimension->mean = mean ;
00238       splitDimension->variance = variance ;
00239       vl_kdtree_split_heap_push (forest->splitHeapArray, &forest->splitHeapNumNodes) ;
00240     } else {
00241       VlKDTreeSplitDimension * splitDimension = forest->splitHeapArray + 0 ;
00242       if (splitDimension->variance < variance) {
00243         splitDimension->dimension = (unsigned int)d ;
00244         splitDimension->mean = mean ;
00245         splitDimension->variance = variance ;
00246         vl_kdtree_split_heap_update (forest->splitHeapArray, forest->splitHeapNumNodes, 0) ;
00247       }
00248     }
00249   }
00250 
00251   /* additional base case: the maximum variance is equal to 0 (overlapping points) */
00252   if (forest->splitHeapNumNodes == 0) {
00253     node->lowerChild = - dataBegin - 1 ;
00254     node->upperChild = - dataEnd - 1 ;
00255     return ;
00256   }
00257 
00258   /* toss a dice to decide the splitting dimension (variance > 0) */
00259   splitDimension = forest->splitHeapArray
00260   + (vl_rand_uint32(forest->rand) % VL_MIN(forest->splitHeapSize, forest->splitHeapNumNodes)) ;
00261 
00262   node->splitDimension = splitDimension->dimension ;
00263 
00264   /* sort data along largest variance dimension */
00265   for (i = dataBegin ; i < dataEnd ; ++ i) {
00266     vl_index di = tree->dataIndex[i].index ;
00267     double datum ;
00268     switch (forest->dataType) {
00269       case VL_TYPE_FLOAT: datum = ((float const*)forest->data)
00270         [di * forest->dimension + splitDimension->dimension] ;
00271         break ;
00272       case VL_TYPE_DOUBLE: datum = ((double const*)forest->data)
00273         [di * forest->dimension + splitDimension->dimension] ;
00274         break ;
00275       default:
00276         abort() ;
00277     }
00278     tree->dataIndex [i] .value = datum ;
00279   }
00280   qsort (tree->dataIndex + dataBegin,
00281          dataEnd - dataBegin,
00282          sizeof (VlKDTreeDataIndexEntry),
00283          vl_kdtree_compare_index_entries) ;
00284 
00285   /* determine split threshold */
00286   switch (forest->thresholdingMethod) {
00287     case VL_KDTREE_MEAN :
00288       node->splitThreshold = splitDimension->mean ;
00289       for (splitIndex = dataBegin ;
00290            splitIndex < dataEnd && tree->dataIndex[splitIndex].value <= node->splitThreshold ;
00291            ++ splitIndex) ;
00292       splitIndex -= 1 ;
00293       /* If the mean does not provide a proper partition, fall back to
00294        * median. This usually happens if all points have the same
00295        * value and the zero variance test fails for numerical accuracy
00296        * reasons. In this case, also due to numerical accuracy, the
00297        * mean value can be smaller, equal, or larger than all
00298        * points. */
00299       if (dataBegin <= splitIndex && splitIndex + 1 < dataEnd) break ;
00300 
00301     case VL_KDTREE_MEDIAN :
00302       medianIndex = (dataBegin + dataEnd - 1) / 2 ;
00303       splitIndex = medianIndex ;
00304       node -> splitThreshold = tree->dataIndex[medianIndex].value ;
00305       break ;
00306 
00307     default:
00308       abort() ;
00309   }
00310 
00311   /* divide subparts */
00312   node->lowerChild = vl_kdtree_node_new (tree, nodeIndex) ;
00313   vl_kdtree_build_recursively (forest, tree, node->lowerChild, dataBegin, splitIndex + 1, depth + 1) ;
00314 
00315   node->upperChild = vl_kdtree_node_new (tree, nodeIndex) ;
00316   vl_kdtree_build_recursively (forest, tree, node->upperChild, splitIndex + 1, dataEnd, depth + 1) ;
00317 }
00318 
00331 VlKDForest *
00332 vl_kdforest_new (vl_type dataType,
00333                  vl_size dimension, vl_size numTrees, VlVectorComparisonType distance)
00334 {
00335   VlKDForest * self = vl_calloc (sizeof(VlKDForest), 1) ;
00336 
00337   assert(dataType == VL_TYPE_FLOAT || dataType == VL_TYPE_DOUBLE) ;
00338   assert(dimension >= 1) ;
00339   assert(numTrees >= 1) ;
00340 
00341   self -> rand = vl_get_rand () ;
00342   self -> dataType = dataType ;
00343   self -> numData = 0 ;
00344   self -> data = 0 ;
00345   self -> dimension = dimension ;
00346   self -> numTrees = numTrees ;
00347   self -> trees = 0 ;
00348   self -> thresholdingMethod = VL_KDTREE_MEDIAN ;
00349   self -> splitHeapSize = VL_MIN(numTrees, VL_KDTREE_SPLIT_HEAP_SIZE) ;
00350   self -> splitHeapNumNodes = 0 ;
00351   self -> distance = distance;
00352   self -> maxNumNodes = 0 ;
00353   self -> numSearchers = 0 ;
00354   self -> headSearcher = 0 ;
00355 
00356   switch (self->dataType) {
00357     case VL_TYPE_FLOAT:
00358       self -> distanceFunction = (void(*)(void))
00359       vl_get_vector_comparison_function_f (distance) ;
00360       break;
00361     case VL_TYPE_DOUBLE :
00362       self -> distanceFunction = (void(*)(void))
00363       vl_get_vector_comparison_function_d (distance) ;
00364       break ;
00365     default :
00366       abort() ;
00367   }
00368 
00369   return self ;
00370 }
00371 
00387 VlKDForestSearcher *
00388 vl_kdforest_new_searcher (VlKDForest * kdforest)
00389 {
00390   VlKDForestSearcher * self = vl_calloc(sizeof(VlKDForestSearcher), 1);
00391   if(kdforest->numSearchers == 0) {
00392     kdforest->headSearcher = self;
00393     self->previous = NULL;
00394     self->next = NULL;
00395   } else {
00396     VlKDForestSearcher * lastSearcher = kdforest->headSearcher;
00397     while (1) {
00398       if(lastSearcher->next) {
00399         lastSearcher = lastSearcher->next;
00400       } else {
00401         lastSearcher->next = self;
00402         self->previous = lastSearcher;
00403         self->next = NULL;
00404         break;
00405       }
00406     }
00407   }
00408 
00409   kdforest->numSearchers++;
00410 
00411   self->forest = kdforest;
00412   self->searchHeapArray = vl_malloc (sizeof(VlKDForestSearchState) * kdforest->maxNumNodes) ;
00413   self->searchIdBook = vl_calloc (sizeof(vl_uindex), kdforest->numData) ;
00414   return self ;
00415 }
00416 
00422 void
00423 vl_kdforestsearcher_delete (VlKDForestSearcher * self)
00424 {
00425   if (self->previous && self->next) {
00426     self->previous->next = self->next;
00427     self->next->previous = self->previous;
00428   } else if (self->previous && !self->next) {
00429     self->previous->next = NULL;
00430   } else if (!self->previous && self->next) {
00431     self->next->previous = NULL;
00432     self->forest->headSearcher = self->next;
00433   } else {
00434     self->forest->headSearcher = NULL;
00435   }
00436   self->forest->numSearchers -- ;
00437   vl_free(self->searchHeapArray) ;
00438   vl_free(self->searchIdBook) ;
00439   vl_free(self) ;
00440 }
00441 
00442 VlKDForestSearcher *
00443 vl_kdforest_get_searcher (VlKDForest const * self, vl_uindex pos)
00444 {
00445   VlKDForestSearcher * lastSearcher = self->headSearcher ;
00446   vl_uindex i ;
00447 
00448   for(i = 0; (i < pos) & (lastSearcher != NULL) ; ++i) {
00449     lastSearcher = lastSearcher->next ;
00450   }
00451   return lastSearcher ;
00452 }
00453 
00460 void
00461 vl_kdforest_delete (VlKDForest * self)
00462 {
00463   vl_uindex ti ;
00464   VlKDForestSearcher * searcher ;
00465 
00466   while ((searcher = vl_kdforest_get_searcher(self, 0))) {
00467     vl_kdforestsearcher_delete(searcher) ;
00468   }
00469 
00470   if (self->trees) {
00471     for (ti = 0 ; ti < self->numTrees ; ++ ti) {
00472       if (self->trees[ti]) {
00473         if (self->trees[ti]->nodes) vl_free (self->trees[ti]->nodes) ;
00474         if (self->trees[ti]->dataIndex) vl_free (self->trees[ti]->dataIndex) ;
00475         vl_free (self->trees[ti]) ;
00476       }
00477     }
00478     vl_free (self->trees) ;
00479   }
00480   vl_free (self) ;
00481 }
00482 
00490 static void
00491 vl_kdtree_calc_bounds_recursively (VlKDTree * tree,
00492                                    vl_uindex nodeIndex, double * searchBounds)
00493 {
00494   VlKDTreeNode * node = tree->nodes + nodeIndex ;
00495   vl_uindex i = node->splitDimension ;
00496   double t = node->splitThreshold ;
00497 
00498   node->lowerBound = searchBounds [2 * i + 0] ;
00499   node->upperBound = searchBounds [2 * i + 1] ;
00500 
00501   //VL_PRINT("%f %f\n",node->lowerBound,node->upperBound);
00502 
00503   if (node->lowerChild > 0) {
00504     searchBounds [2 * i + 1] = t ;
00505     vl_kdtree_calc_bounds_recursively (tree, node->lowerChild, searchBounds) ;
00506     searchBounds [2 * i + 1] = node->upperBound ;
00507   }
00508   if (node->upperChild > 0) {
00509     searchBounds [2 * i + 0] = t ;
00510     vl_kdtree_calc_bounds_recursively (tree, node->upperChild, searchBounds) ;
00511     searchBounds [2 * i + 0] = node->lowerBound ;
00512   }
00513 }
00514 
00529 void
00530 vl_kdforest_build (VlKDForest * self, vl_size numData, void const * data)
00531 {
00532   vl_uindex di, ti ;
00533   vl_size maxNumNodes ;
00534   double * searchBounds;
00535 
00536   assert(data) ;
00537   assert(numData >= 1) ;
00538 
00539   /* need to check: if alredy built, clean first */
00540   self->data = data ;
00541   self->numData = numData ;
00542   self->trees = vl_malloc (sizeof(VlKDTree*) * self->numTrees) ;
00543   maxNumNodes = 0 ;
00544 
00545   for (ti = 0 ; ti < self->numTrees ; ++ ti) {
00546     self->trees[ti] = vl_malloc (sizeof(VlKDTree)) ;
00547     self->trees[ti]->dataIndex = vl_malloc (sizeof(VlKDTreeDataIndexEntry) * self->numData) ;
00548     for (di = 0 ; di < self->numData ; ++ di) {
00549       self->trees[ti]->dataIndex[di].index = di ;
00550     }
00551     self->trees[ti]->numUsedNodes = 0 ;
00552     /* num. nodes of a complete binary tree with numData leaves */
00553     self->trees[ti]->numAllocatedNodes = 2 * self->numData - 1 ;
00554     self->trees[ti]->nodes = vl_malloc (sizeof(VlKDTreeNode) * self->trees[ti]->numAllocatedNodes) ;
00555     self->trees[ti]->depth = 0 ;
00556     vl_kdtree_build_recursively (self, self->trees[ti],
00557                                  vl_kdtree_node_new(self->trees[ti], 0), 0,
00558                                  self->numData, 0) ;
00559     maxNumNodes += self->trees[ti]->numUsedNodes ;
00560   }
00561 
00562   searchBounds = vl_malloc(sizeof(double) * 2 * self->dimension);
00563 
00564   for (ti = 0 ; ti < self->numTrees ; ++ ti) {
00565     double * iter = searchBounds  ;
00566     double * end = iter + 2 * self->dimension ;
00567     while (iter < end) {
00568       *iter++ = - VL_INFINITY_F ;
00569       *iter++ = + VL_INFINITY_F ;
00570     }
00571 
00572     vl_kdtree_calc_bounds_recursively (self->trees[ti], 0, searchBounds) ;
00573   }
00574 
00575   vl_free(searchBounds);
00576   self -> maxNumNodes = maxNumNodes;
00577 }
00578 
00579 
00584 vl_uindex
00585 vl_kdforest_query_recursively (VlKDForestSearcher * searcher,
00586                                VlKDTree * tree,
00587                                vl_uindex nodeIndex,
00588                                VlKDForestNeighbor * neighbors,
00589                                vl_size numNeighbors,
00590                                vl_size * numAddedNeighbors,
00591                                double dist,
00592                                void const * query)
00593 {
00594 
00595   VlKDTreeNode const * node = tree->nodes + nodeIndex ;
00596   vl_uindex i = node->splitDimension ;
00597   vl_index nextChild, saveChild ;
00598   double delta, saveDist ;
00599   double x ;
00600   double x1 = node->lowerBound ;
00601   double x2 = node->splitThreshold ;
00602   double x3 = node->upperBound ;
00603   VlKDForestSearchState * searchState ;
00604 
00605   searcher->searchNumRecursions ++ ;
00606 
00607   switch (searcher->forest->dataType) {
00608     case VL_TYPE_FLOAT :
00609       x = ((float const*) query)[i] ;
00610       break ;
00611     case VL_TYPE_DOUBLE :
00612       x = ((double const*) query)[i] ;
00613       break ;
00614     default :
00615       abort() ;
00616   }
00617 
00618   /* base case: this is a leaf node */
00619   if (node->lowerChild < 0) {
00620 
00621     vl_index begin = - node->lowerChild - 1 ;
00622     vl_index end   = - node->upperChild - 1 ;
00623     vl_index iter ;
00624 
00625     for (iter = begin ;
00626          iter < end &&
00627          (searcher->forest->searchMaxNumComparisons == 0 ||
00628           searcher->searchNumComparisons < searcher->forest->searchMaxNumComparisons) ;
00629          ++ iter) {
00630 
00631       vl_index di = tree->dataIndex [iter].index ;
00632 
00633       /* multiple KDTrees share the database points and we must avoid
00634        * adding the same point twice */
00635       if (searcher->searchIdBook[di] == searcher->searchId) continue ;
00636       searcher->searchIdBook[di] = searcher->searchId ;
00637 
00638       /* compare the query to this point */
00639       switch (searcher->forest->dataType) {
00640         case VL_TYPE_FLOAT:
00641           dist = ((VlFloatVectorComparisonFunction)searcher->forest->distanceFunction)
00642                  (searcher->forest->dimension,
00643                   ((float const *)query),
00644                   ((float const*)searcher->forest->data) + di * searcher->forest->dimension) ;
00645           break ;
00646         case VL_TYPE_DOUBLE:
00647           dist = ((VlDoubleVectorComparisonFunction)searcher->forest->distanceFunction)
00648                  (searcher->forest->dimension,
00649                   ((double const *)query),
00650                   ((double const*)searcher->forest->data) + di * searcher->forest->dimension) ;
00651           break ;
00652         default:
00653           abort() ;
00654       }
00655       searcher->searchNumComparisons += 1 ;
00656 
00657       /* see if it should be added to the result set */
00658       if (*numAddedNeighbors < numNeighbors) {
00659         VlKDForestNeighbor * newNeighbor = neighbors + *numAddedNeighbors ;
00660         newNeighbor->index = di ;
00661         newNeighbor->distance = dist ;
00662         vl_kdforest_neighbor_heap_push (neighbors, numAddedNeighbors) ;
00663       } else {
00664         VlKDForestNeighbor * largestNeighbor = neighbors + 0 ;
00665         if (largestNeighbor->distance > dist) {
00666           largestNeighbor->index = di ;
00667           largestNeighbor->distance = dist ;
00668           vl_kdforest_neighbor_heap_update (neighbors, *numAddedNeighbors, 0) ;
00669         }
00670       }
00671     } /* next data point */
00672 
00673 
00674     return nodeIndex ;
00675   }
00676 
00677 #if 0
00678   assert (x1 <= x2 && x2 <= x3) ;
00679   assert (node->lowerChild >= 0) ;
00680   assert (node->upperChild >= 0) ;
00681 #endif
00682 
00683   /*
00684    *   x1  x2 x3
00685    * x (---|---]
00686    *   (--x|---]
00687    *   (---|x--]
00688    *   (---|---] x
00689    */
00690 
00691   delta = x - x2 ;
00692   saveDist = dist + delta*delta ;
00693 
00694   if (x <= x2) {
00695     nextChild = node->lowerChild ;
00696     saveChild = node->upperChild ;
00697     if (x <= x1) {
00698       delta = x - x1 ;
00699       saveDist -= delta*delta ;
00700     }
00701   } else {
00702     nextChild = node->upperChild ;
00703     saveChild = node->lowerChild ;
00704     if (x > x3) {
00705       delta = x - x3 ;
00706       saveDist -= delta*delta ;
00707     }
00708   }
00709 
00710   if (*numAddedNeighbors < numNeighbors || neighbors[0].distance > saveDist) {
00711     searchState = searcher->searchHeapArray + searcher->searchHeapNumNodes ;
00712     searchState->tree = tree ;
00713     searchState->nodeIndex = saveChild ;
00714     searchState->distanceLowerBound = saveDist ;
00715     vl_kdforest_search_heap_push (searcher->searchHeapArray ,
00716                                   &searcher->searchHeapNumNodes) ;
00717   }
00718 
00719   return vl_kdforest_query_recursively (searcher,
00720                                         tree,
00721                                         nextChild,
00722                                         neighbors,
00723                                         numNeighbors,
00724                                         numAddedNeighbors,
00725                                         dist,
00726                                         query) ;
00727 }
00728 
00743 vl_size
00744 vl_kdforest_query (VlKDForest * self,
00745                    VlKDForestNeighbor * neighbors,
00746                    vl_size numNeighbors,
00747                    void const * query)
00748 {
00749   VlKDForestSearcher * searcher = vl_kdforest_get_searcher(self, 0) ;
00750   if (searcher == NULL) {
00751     searcher = vl_kdforest_new_searcher(self) ;
00752   }
00753   return vl_kdforestsearcher_query(searcher,
00754                                    neighbors,
00755                                    numNeighbors,
00756                                    query) ;
00757 }
00758 
00773 vl_size
00774 vl_kdforestsearcher_query (VlKDForestSearcher * self,
00775                            VlKDForestNeighbor * neighbors,
00776                            vl_size numNeighbors,
00777                            void const * query)
00778 {
00779 
00780   vl_uindex i, ti ;
00781   vl_bool exactSearch = self->forest->searchMaxNumComparisons == 0 ;
00782 
00783   VlKDForestSearchState * searchState  ;
00784   vl_size numAddedNeighbors = 0 ;
00785 
00786   assert (neighbors) ;
00787   assert (numNeighbors > 0) ;
00788   assert (query) ;
00789 
00790   /* this number is used to differentiate a query from the next */
00791   self -> searchId += 1 ;
00792   self -> searchNumRecursions = 0 ;
00793 
00794   self->searchNumComparisons = 0 ;
00795   self->searchNumSimplifications = 0 ;
00796 
00797   /* put the root node into the search heap */
00798   self->searchHeapNumNodes = 0 ;
00799   for (ti = 0 ; ti < self->forest->numTrees ; ++ ti) {
00800     searchState = self->searchHeapArray + self->searchHeapNumNodes ;
00801     searchState -> tree = self->forest->trees[ti] ;
00802     searchState -> nodeIndex = 0 ;
00803     searchState -> distanceLowerBound = 0 ;
00804 
00805     vl_kdforest_search_heap_push (self->searchHeapArray, &self->searchHeapNumNodes) ;
00806   }
00807 
00808   /* branch and bound */
00809   while (exactSearch || self->searchNumComparisons < self->forest->searchMaxNumComparisons)
00810   {
00811     /* pop the next optimal search node */
00812     VlKDForestSearchState * searchState ;
00813 
00814     /* break if search space completed */
00815     if (self->searchHeapNumNodes == 0) {
00816       break ;
00817     }
00818     searchState = self->searchHeapArray +
00819                   vl_kdforest_search_heap_pop (self->searchHeapArray, &self->searchHeapNumNodes) ;
00820     /* break if no better solution may exist */
00821     if (numAddedNeighbors == numNeighbors &&
00822         neighbors[0].distance < searchState->distanceLowerBound) {
00823       self->searchNumSimplifications ++ ;
00824       break ;
00825     }
00826     vl_kdforest_query_recursively (self,
00827                                    searchState->tree,
00828                                    searchState->nodeIndex,
00829                                    neighbors,
00830                                    numNeighbors,
00831                                    &numAddedNeighbors,
00832                                    searchState->distanceLowerBound,
00833                                    query) ;
00834   }
00835 
00836   /* sort neighbors by increasing distance */
00837   for (i = numAddedNeighbors ; i < numNeighbors ; ++ i) {
00838     neighbors[i].index = -1 ;
00839     neighbors[i].distance = VL_NAN_F ;
00840   }
00841 
00842   while (numAddedNeighbors) {
00843     vl_kdforest_neighbor_heap_pop (neighbors, &numAddedNeighbors) ;
00844   }
00845 
00846   return self->searchNumComparisons ;
00847 }
00848 
00869 vl_size
00870 vl_kdforest_query_with_array (VlKDForest * self,
00871                               vl_uint32 * indexes,
00872                               vl_size numNeighbors,
00873                               vl_size numQueries,
00874                               void * distances,
00875                               void const * queries)
00876 {
00877   vl_size numComparisons = 0;
00878   vl_type dataType = vl_kdforest_get_data_type(self) ;
00879   vl_size dimension = vl_kdforest_get_data_dimension(self) ;
00880 
00881 #ifdef _OPENMP
00882 #pragma omp parallel default(shared) num_threads(vl_get_max_threads())
00883 #endif
00884   {
00885     vl_index qi ;
00886     vl_size thisNumComparisons = 0 ;
00887     VlKDForestSearcher * searcher ;
00888     VlKDForestNeighbor * neighbors ;
00889 
00890 #ifdef _OPENMP
00891 #pragma omp critical
00892 #endif
00893     {
00894       searcher = vl_kdforest_new_searcher(self) ;
00895       neighbors = vl_calloc (sizeof(VlKDForestNeighbor), numNeighbors) ;
00896     }
00897 
00898 #ifdef _OPENMP
00899 #pragma omp for
00900 #endif
00901     for(qi = 0 ; qi < (signed)numQueries; ++ qi) {
00902       switch (dataType) {
00903         case VL_TYPE_FLOAT: {
00904           vl_size ni;
00905           thisNumComparisons += vl_kdforestsearcher_query (searcher, neighbors, numNeighbors,
00906                                                            (float const *) (queries) + qi * dimension) ;
00907           for (ni = 0 ; ni < numNeighbors ; ++ni) {
00908             indexes [qi*numNeighbors + ni] = (vl_uint32) neighbors[ni].index ;
00909             if (distances){
00910               *((float*)distances + qi*numNeighbors + ni) = neighbors[ni].distance ;
00911             }
00912           }
00913           break ;
00914         }
00915         case VL_TYPE_DOUBLE: {
00916           vl_size ni;
00917           thisNumComparisons += vl_kdforestsearcher_query (searcher, neighbors, numNeighbors,
00918                                                            (double const *) (queries) + qi * dimension) ;
00919           for (ni = 0 ; ni < numNeighbors ; ++ni) {
00920             indexes [qi*numNeighbors + ni] = (vl_uint32) neighbors[ni].index ;
00921             if (distances){
00922               *((double*)distances + qi*numNeighbors + ni) = neighbors[ni].distance ;
00923             }
00924           }
00925           break ;
00926         }
00927         default:
00928           abort() ;
00929       }
00930     }
00931 
00932 #ifdef _OPENMP
00933 #pragma omp critical
00934 #endif
00935     {
00936       numComparisons += thisNumComparisons ;
00937       vl_kdforestsearcher_delete (searcher) ;
00938       vl_free (neighbors) ;
00939     }
00940   }
00941   return numComparisons ;
00942 }
00943 
00951 vl_size
00952 vl_kdforest_get_num_nodes_of_tree (VlKDForest const * self, vl_uindex treeIndex)
00953 {
00954   assert (treeIndex < self->numTrees) ;
00955   return self->trees[treeIndex]->numUsedNodes ;
00956 }
00957 
00965 vl_size
00966 vl_kdforest_get_depth_of_tree (VlKDForest const * self, vl_uindex treeIndex)
00967 {
00968   assert (treeIndex < self->numTrees) ;
00969   return self->trees[treeIndex]->depth ;
00970 }
00971 
00979 vl_size
00980 vl_kdforest_get_num_trees (VlKDForest const * self)
00981 {
00982   return self->numTrees ;
00983 }
00984 
00997 void
00998 vl_kdforest_set_max_num_comparisons (VlKDForest * self, vl_size n)
00999 {
01000   self->searchMaxNumComparisons = n ;
01001 }
01002 
01012 vl_size
01013 vl_kdforest_get_max_num_comparisons (VlKDForest * self)
01014 {
01015   return self->searchMaxNumComparisons ;
01016 }
01017 
01026  void
01027 vl_kdforest_set_thresholding_method (VlKDForest * self, VlKDTreeThresholdingMethod method)
01028 {
01029   assert(method == VL_KDTREE_MEDIAN || method == VL_KDTREE_MEAN) ;
01030   self->thresholdingMethod = method ;
01031 }
01032 
01042  VlKDTreeThresholdingMethod
01043 vl_kdforest_get_thresholding_method (VlKDForest const * self)
01044 {
01045   return self->thresholdingMethod ;
01046 }
01047 
01054  vl_size
01055 vl_kdforest_get_data_dimension (VlKDForest const * self)
01056 {
01057   return self->dimension ;
01058 }
01059 
01066 vl_type
01067 vl_kdforest_get_data_type (VlKDForest const * self)
01068 {
01069   return self->dataType ;
01070 }
01071 
01078 VlKDForest *
01079 vl_kdforestsearcher_get_forest (VlKDForestSearcher const * self)
01080 {
01081   return self->forest;
01082 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51