33 #ifndef NANOFLANN_HPP_
34 #define NANOFLANN_HPP_
56 #define NANOFLANN_VERSION 0x112
60 template <
typename DistanceType,
typename IndexType =
size_t,
typename CountType =
size_t>
73 inline void init(IndexType* indices_, DistanceType* dists_)
78 dists[
capacity-1] = (std::numeric_limits<DistanceType>::max)();
81 inline CountType
size()
const
92 inline void addPoint(DistanceType dist, IndexType index)
95 for (i=
count; i>0; --i) {
96 #ifdef NANOFLANN_FIRST_MATCH
99 if (
dists[i-1]>dist) {
125 template <
typename DistanceType,
typename IndexType =
size_t>
133 inline RadiusResultSet(DistanceType radius_, std::vector<std::pair<IndexType,DistanceType> >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
140 inline void init() { m_indices_dists.clear(); }
142 inline size_t size()
const {
return m_indices_dists.size(); }
144 inline bool full()
const {
return true; }
146 inline void addPoint(DistanceType dist, IndexType index)
149 m_indices_dists.push_back(std::make_pair<IndexType,DistanceType>(index,dist));
152 inline DistanceType
worstDist()
const {
return radius; }
159 template <
typename PairType>
160 inline bool operator()(
const PairType &p1,
const PairType &p2)
const {
161 return p1.second < p2.second;
173 fwrite(&value,
sizeof(value),
count, stream);
179 size_t size = value.size();
180 fwrite(&size,
sizeof(
size_t), 1, stream);
181 fwrite(&value[0],
sizeof(T), size, stream);
187 size_t read_cnt = fread(&value,
sizeof(value),
count, stream);
188 if (read_cnt !=
count) {
189 throw std::runtime_error(
"Cannot read from file");
198 size_t read_cnt = fread(&size,
sizeof(
size_t), 1, stream);
200 throw std::runtime_error(
"Cannot read from file");
203 read_cnt = fread(&value[0],
sizeof(T), size, stream);
204 if (read_cnt!=size) {
205 throw std::runtime_error(
"Cannot read from file");
214 template<
typename T>
inline T
abs(T x) {
return (x<0) ? -x : x; }
216 template<>
inline float abs<float>(
float x) {
return fabsf(x); }
217 template<>
inline double abs<double>(
double x) {
return fabs(x); }
225 template<
class T,
class DataSource,
typename _DistanceType = T>
233 L1_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
238 const T* last = a +
size;
239 const T* lastgroup = last - 3;
243 while (a < lastgroup) {
248 result += diff0 + diff1 + diff2 + diff3;
250 if ((worst_dist>0)&&(result>worst_dist)) {
256 result +=
nanoflann::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) );
261 template <
typename U,
typename V>
273 template<
class T,
class DataSource,
typename _DistanceType = T>
281 L2_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
286 const T* last = a +
size;
287 const T* lastgroup = last - 3;
291 while (a < lastgroup) {
292 const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++);
293 const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++);
294 const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++);
295 const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++);
296 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
298 if ((worst_dist>0)&&(result>worst_dist)) {
304 const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++);
305 result += diff0 * diff0;
310 template <
typename U,
typename V>
322 template<
class T,
class DataSource,
typename _DistanceType = T>
333 return data_source.kdtree_distance(a,b_idx,size);
336 template <
typename U,
typename V>
345 template<
class T,
class DataSource>
352 template<
class T,
class DataSource>
359 template<
class T,
class DataSource>
377 leaf_max_size(_leaf_max_size), dim(dim_)
388 SearchParams(
int checks_IGNORED_ = 32,
float eps_ = 0,
bool sorted_ =
true ) :
389 eps(eps_), sorted(sorted_) {}
408 template <
typename T>
411 T* mem = (T*) ::malloc(
sizeof(T)*
count);
457 this->blocksize = blocksize;
470 while (base != NULL) {
471 void *prev = *((
void**) base);
481 void* malloc(
const size_t req_size)
492 if (size > remaining) {
494 wastedMemory += remaining;
501 void* m = ::malloc(blocksize);
503 fprintf(stderr,
"Failed to allocate memory.\n");
508 ((
void**) m)[0] = base;
514 remaining = blocksize -
sizeof(
void*) - shift;
515 loc = ((
char*)m +
sizeof(
void*) + shift);
518 loc = (
char*)loc + size;
533 template <
typename T>
536 T* mem = (T*) this->malloc(
sizeof(T)*
count);
580 template <
typename Distance,
class DatasetAdaptor,
int DIM = -1,
typename IndexType =
size_t>
650 template <
typename T,
typename DistanceType>
659 inline bool operator<(const BranchStruct<T, DistanceType>& rhs)
const
661 return mindist<rhs.mindist;
695 dataset(inputData), index_params(params),
distance(inputData)
697 m_size = dataset.kdtree_get_point_count();
698 dim = dimensionality;
701 if (params.dim>0) dim = params.dim;
703 m_leaf_max_size = params.leaf_max_size;
722 computeBoundingBox(root_bbox);
723 root_node = divideTree(0, m_size, root_bbox );
737 size_t veclen()
const
739 return static_cast<size_t>(DIM>0 ? DIM : dim);
746 size_t usedMemory()
const
748 return pool.usedMemory+pool.wastedMemory+dataset.kdtree_get_point_count()*
sizeof(IndexType);
765 template <
typename RESULTSET>
768 float epsError = 1+searchParams.
eps;
770 std::vector<DistanceType>
dists( (DIM>0 ? DIM : dim) ,0);
771 DistanceType distsq = computeInitialDistances(vec, dists);
772 searchLevel(result, vec, root_node, distsq, dists, epsError);
781 inline void knnSearch(
const ElementType *query_point,
const size_t num_closest, IndexType *out_indices,
DistanceType *out_distances_sq,
const int nChecks_IGNORED = 10)
const
784 resultSet.
init(out_indices, out_distances_sq);
803 this->findNeighbors(resultSet, query_point, searchParams);
808 return resultSet.
size();
818 m_size = dataset.kdtree_get_point_count();
819 if (vind.size()!=m_size)
822 for (
size_t i = 0; i < m_size; i++) vind[i] = i;
828 return dataset.kdtree_get_pt(idx,component);
836 save_tree(stream, tree->
child1);
839 save_tree(stream, tree->
child2);
846 tree = pool.allocate<
Node>();
849 load_tree(stream, tree->
child1);
852 load_tree(stream, tree->
child2);
859 bbox.resize((DIM>0 ? DIM : dim));
860 if (dataset.kdtree_get_bbox(bbox))
866 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
868 bbox[i].high = dataset_get(0,i);
870 const size_t N = dataset.kdtree_get_point_count();
871 for (
size_t k=1; k<N; ++k) {
872 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
873 if (dataset_get(k,i)<bbox[i].low) bbox[i].low = dataset_get(k,i);
874 if (dataset_get(k,i)>bbox[i].high) bbox[i].high = dataset_get(k,i);
895 if ( (right-left) <= m_leaf_max_size) {
897 node->
lr.left = left;
898 node->
lr.right = right;
901 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
902 bbox[i].low = dataset_get(vind[left],i);
903 bbox[i].high = dataset_get(vind[left],i);
905 for (IndexType k=left+1; k<right; ++k) {
906 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
907 if (bbox[i].low>dataset_get(vind[k],i)) bbox[i].low=dataset_get(vind[k],i);
908 if (bbox[i].high<dataset_get(vind[k],i)) bbox[i].high=dataset_get(vind[k],i);
916 middleSplit_(&vind[0]+left, right-left, idx, cutfeat, cutval, bbox);
918 node->
sub.divfeat = cutfeat;
921 left_bbox[cutfeat].high = cutval;
922 node->
child1 = divideTree(left, left+idx, left_bbox);
925 right_bbox[cutfeat].low = cutval;
926 node->
child2 = divideTree(left+idx, right, right_bbox);
928 node->
sub.divlow = left_bbox[cutfeat].high;
929 node->
sub.divhigh = right_bbox[cutfeat].low;
931 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
932 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
933 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
942 min_elem = dataset_get(ind[0],element);
943 max_elem = dataset_get(ind[0],element);
944 for (IndexType i=1; i<
count; ++i) {
946 if (val<min_elem) min_elem = val;
947 if (val>max_elem) max_elem = val;
956 cutval = (bbox[0].high+bbox[0].low)/2;
957 for (
int i=1; i<(DIM>0 ? DIM : dim); ++i) {
962 cutval = (bbox[i].high+bbox[i].low)/2;
968 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
969 cutval = (min_elem+max_elem)/2;
970 max_span = max_elem - min_elem;
974 for (
size_t i=0; i<(DIM>0 ? DIM : dim); ++i) {
978 computeMinMax(ind, count, i, min_elem, max_elem);
979 span = max_elem - min_elem;
983 cutval = (min_elem+max_elem)/2;
987 IndexType lim1, lim2;
988 planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
990 if (lim1>count/2) index = lim1;
991 else if (lim2<count/2) index = lim2;
992 else index = count/2;
1000 for (
int i=1; i<(DIM>0 ? DIM : dim); ++i) {
1002 if (span>max_span) {
1008 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1010 if (span>(1-EPS)*max_span) {
1012 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
1014 if (spread>max_spread) {
1016 max_spread = spread;
1021 DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
1023 computeMinMax(ind, count, cutfeat, min_elem, max_elem);
1025 if (split_val<min_elem) cutval = min_elem;
1026 else if (split_val>max_elem) cutval = max_elem;
1027 else cutval = split_val;
1029 IndexType lim1, lim2;
1030 planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
1032 if (lim1>count/2) index = lim1;
1033 else if (lim2<count/2) index = lim2;
1034 else index = count/2;
1047 void planeSplit(IndexType* ind,
const IndexType
count,
int cutfeat,
DistanceType cutval, IndexType& lim1, IndexType& lim2)
1051 IndexType right = count-1;
1053 while (left<=right && dataset_get(ind[left],cutfeat)<cutval) ++left;
1054 while (right && left<=right && dataset_get(ind[right],cutfeat)>=cutval) --right;
1055 if (left>right || !right)
break;
1056 std::swap(ind[left], ind[right]);
1066 while (left<=right && dataset_get(ind[left],cutfeat)<=cutval) ++left;
1067 while (right && left<=right && dataset_get(ind[right],cutfeat)>cutval) --right;
1068 if (left>right || !right)
break;
1069 std::swap(ind[left], ind[right]);
1080 for (
int i = 0; i < (DIM>0 ? DIM : dim); ++i) {
1081 if (vec[i] < root_bbox[i].low) {
1082 dists[i] =
distance.accum_dist(vec[i], root_bbox[i].low, i);
1085 if (vec[i] > root_bbox[i].high) {
1086 dists[i] =
distance.accum_dist(vec[i], root_bbox[i].high, i);
1098 template <
class RESULTSET>
1100 std::vector<DistanceType>&
dists,
const float epsError)
const
1106 for (IndexType i=node->
lr.left; i<node->lr.right; ++i) {
1107 const IndexType index = vind[i];
1109 if (dist<worst_dist) {
1110 result_set.addPoint(dist,vind[i]);
1117 int idx = node->
sub.divfeat;
1125 if ((diff1+diff2)<0) {
1126 bestChild = node->
child1;
1127 otherChild = node->
child2;
1128 cut_dist =
distance.accum_dist(val, node->
sub.divhigh, idx);
1131 bestChild = node->
child2;
1132 otherChild = node->
child1;
1133 cut_dist =
distance.accum_dist( val, node->
sub.divlow, idx);
1137 searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError);
1140 mindistsq = mindistsq + cut_dist - dst;
1141 dists[idx] = cut_dist;
1142 if (mindistsq*epsError<=result_set.worstDist()) {
1143 searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError);
1149 void saveIndex(FILE* stream)
1156 save_tree(stream, root_node);
1159 void loadIndex(FILE* stream)
1166 load_tree(stream, root_node);
1191 template <
class MatrixType,
int DIM = -1,
class Distance =
nanoflann::metric_L2,
typename IndexType =
size_t>
1195 typedef typename MatrixType::Scalar
num_t;
1196 typedef typename Distance::template traits<num_t,self_t>::distance_t
metric_t;
1204 const size_t dims = mat.cols();
1205 if (DIM>0 && static_cast<int>(dims)!=DIM)
1206 throw std::runtime_error(
"Data set dimensionality does not match the 'DIM' template argument");
1208 index->buildIndex();
1222 inline void query(
const num_t *query_point,
const size_t num_closest, IndexType *out_indices,
num_t *out_distances_sq,
const int nChecks_IGNORED = 10)
const
1225 resultSet.
init(out_indices, out_distances_sq);
1241 return m_data_matrix.rows();
1248 for (
size_t i=0; i<
size; i++) {
1249 const num_t d= p1[i]-m_data_matrix.coeff(idx_p2,i);
1257 return m_data_matrix.coeff(idx,dim);
1263 template <
class BBOX>