diff --git a/CMakeLists.txt b/CMakeLists.txt index afccbcd50f717ff531179520327f64e945c7beea..a28ea07898a683d677c05637494213b2e8cb3c3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,9 @@ endif(USE_MPI) include_directories(${PROJECT_SOURCE_DIR}/src/cpp) # require proper c++ -add_definitions( "-Wall -ansi -pedantic" ) +#add_definitions( "-Wall -ansi -pedantic" ) +# HDF5 uses long long which is not ansi +add_definitions( "-Wall" ) add_subdirectory( cmake ) add_subdirectory( src ) diff --git a/src/cpp/flann/algorithms/autotuned_index.h b/src/cpp/flann/algorithms/autotuned_index.h index 19a0d3ef61eacb7c2594cd6772d79e63ecf69660..332b32416e1d2665b6e699589878b168e5d9d5c8 100644 --- a/src/cpp/flann/algorithms/autotuned_index.h +++ b/src/cpp/flann/algorithms/autotuned_index.h @@ -290,8 +290,8 @@ private: IndexParams* params; }; - typedef pair KDTreeCostData; - typedef pair KMeansCostData; + typedef std::pair KDTreeCostData; + typedef std::pair KMeansCostData; void evaluate_kmeans(CostData& cost) @@ -396,7 +396,7 @@ private: - void optimizeKMeans( vector& costs ) + void optimizeKMeans( std::vector& costs ) { logger.info("KMEANS, Step 1: Exploring parameter space\n"); @@ -445,7 +445,7 @@ private: } - void optimizeKDTree(vector& costs) + void optimizeKDTree( std::vector& costs) { logger.info("KD-TREE, Step 1: Exploring parameter space\n"); @@ -492,10 +492,10 @@ private: */ IndexParams* estimateBuildParams() { - vector costs; + std::vector costs; int sampleSize = int(index_params.sample_fraction*dataset.rows); - int testSampleSize = min(sampleSize/10, 1000); + int testSampleSize = std::min(sampleSize/10, 1000); logger.info("Entering autotuning, dataset size: %d, sampleSize: %d, testSampleSize: %d, target precision: %g\n",dataset.rows, sampleSize, testSampleSize, index_params.target_precision); @@ -583,7 +583,7 @@ private: float speedup = 0; - int samples = min(dataset.rows/10, SAMPLE_COUNT); + int samples = std::min(dataset.rows/10, SAMPLE_COUNT); if (samples>0) { Matrix testDataset = random_sample(dataset,samples); diff --git a/src/cpp/flann/algorithms/dist.h b/src/cpp/flann/algorithms/dist.h index d62b5dc715491263872ad723acf73eed1425148c..17df25370edc47aa72141d398acfd83aef3e7cbf 100644 --- a/src/cpp/flann/algorithms/dist.h +++ b/src/cpp/flann/algorithms/dist.h @@ -33,7 +33,6 @@ #include #include -using namespace std; #include "flann/general.h" diff --git a/src/cpp/flann/algorithms/kdtree_index.h b/src/cpp/flann/algorithms/kdtree_index.h index d64f1149aee12137f312d587810b49daaeeb65eb..e77e0ad119645a006178f8a88c8c7201676aeeec 100644 --- a/src/cpp/flann/algorithms/kdtree_index.h +++ b/src/cpp/flann/algorithms/kdtree_index.h @@ -45,8 +45,6 @@ #include "flann/util/random.h" #include "flann/util/saving.h" -using namespace std; - namespace flann { @@ -225,7 +223,7 @@ public: { for (int j = vec_size; j > 0; --j) { int rnd = rand_int(j); - swap(vec[j-1], vec[rnd]); + std::swap(vec[j-1], vec[rnd]); } } @@ -390,7 +388,7 @@ private: /* Compute mean values. Only the first SAMPLE_MEAN values need to be sampled to get a good estimate. */ - int cnt = min((int)SAMPLE_MEAN+1, count); + int cnt = std::min((int)SAMPLE_MEAN+1, count); for (int j = 0; j < cnt; ++j) { ElementType* v = dataset[ind[j]]; for (size_t k=0; k 0 && v[topind[j]] > v[topind[j-1]]) { - swap(topind[j], topind[j-1]); + std::swap(topind[j], topind[j-1]); --j; } } @@ -476,7 +474,7 @@ private: while (left<=right && dataset[ind[left]][cutfeat]=cutval) --right; if (left>right) break; - swap(ind[left], ind[right]); ++left; --right; + std::swap(ind[left], ind[right]); ++left; --right; } /* If either list is empty, it means that all remaining features * are identical. Split in the middle to maintain a balanced tree. @@ -487,7 +485,7 @@ private: while (left<=right && dataset[ind[left]][cutfeat]<=cutval) ++left; while (left<=right && dataset[ind[right]][cutfeat]>cutval) --right; if (left>right) break; - swap(ind[left], ind[right]); ++left; --right; + std::swap(ind[left], ind[right]); ++left; --right; } lim2 = left; } @@ -521,7 +519,7 @@ private: int checkCount = 0; Heap* heap = new Heap(size_); - vector checked(size_,false); + std::vector checked(size_,false); /* Search once through each tree down to root. */ for (i = 0; i < numTrees; ++i) { @@ -545,7 +543,7 @@ private: * at least "mindistsq". */ void searchLevel(ResultSet& result_set, const ElementType* vec, NodePtr node, float mindistsq, int& checkCount, int maxCheck, - float epsError, Heap* heap, vector& checked) + float epsError, Heap* heap, std::vector& checked) { if (result_set.worstDist() 0; --j) { int rnd = rand_int(j); - swap(vec[j-1], vec[rnd]); + std::swap(vec[j-1], vec[rnd]); } } @@ -462,7 +459,7 @@ private: while (left<=right && dataset[ind[left]][cutfeat]=cutval) --right; if (left>right) break; - swap(ind[left], ind[right]); ++left; --right; + std::swap(ind[left], ind[right]); ++left; --right; } /* If either list is empty, it means that all remaining features * are identical. Split in the middle to maintain a balanced tree. @@ -473,7 +470,7 @@ private: while (left<=right && dataset[ind[left]][cutfeat]<=cutval) ++left; while (left<=right && dataset[ind[right]][cutfeat]>cutval) --right; if (left>right) break; - swap(ind[left], ind[right]); ++left; --right; + std::swap(ind[left], ind[right]); ++left; --right; } lim2 = left; } diff --git a/src/cpp/flann/algorithms/kmeans_index.h b/src/cpp/flann/algorithms/kmeans_index.h index de0f45bbef318de2584207062d33416c8b0e7f9d..080918f04f96cc19e1a87aa8b3ef1926214684a1 100644 --- a/src/cpp/flann/algorithms/kmeans_index.h +++ b/src/cpp/flann/algorithms/kmeans_index.h @@ -48,8 +48,6 @@ #include "flann/util/random.h" #include "flann/util/saving.h" -using namespace std; - namespace flann { @@ -382,7 +380,7 @@ class KMeansIndex : public NNIndex // Compute the new potential double newPot = 0; for (int i = 0; i < n; i++) - newPot += min( distance(dataset[indices[i]], dataset[indices[index]], dataset.cols), closestDistSq[i] ); + newPot += std::min( distance(dataset[indices[i]], dataset[indices[index]], dataset.cols), closestDistSq[i] ); // Store the best result if (bestNewPot < 0 || newPot < bestNewPot) { @@ -395,7 +393,7 @@ class KMeansIndex : public NNIndex centers[centerCount] = indices[bestNewIndex]; currentPot = bestNewPot; for (int i = 0; i < n; i++) - closestDistSq[i] = min( distance(dataset[indices[i]], dataset[indices[bestNewIndex]], dataset.cols), closestDistSq[i] ); + closestDistSq[i] = std::min( distance(dataset[indices[i]], dataset[indices[bestNewIndex]], dataset.cols), closestDistSq[i] ); } centers_length = centerCount; @@ -432,7 +430,7 @@ public: branching = params.branching; max_iter = params.iterations; if (max_iter<0) { - max_iter = numeric_limits::max(); + max_iter = (std::numeric_limits::max)(); } flann_centers_init_t centersInit = params.centers_init; @@ -741,7 +739,7 @@ private: if (indices_length < branching) { node->indices = indices; - sort(node->indices,node->indices+indices_length); + std::sort(node->indices,node->indices+indices_length); node->childs = NULL; return; } @@ -752,7 +750,7 @@ private: if (centers_lengthindices = indices; - sort(node->indices,node->indices+indices_length); + std::sort(node->indices,node->indices+indices_length); node->childs = NULL; delete [] centers_idx; return; @@ -890,8 +888,8 @@ private: float d = distance(dataset[indices[i]], ZeroIterator(), veclen_); variance += d; mean_radius += sqrt(d); - swap(indices[i],indices[end]); - swap(belongs_to[i],belongs_to[end]); + std::swap(indices[i],indices[end]); + std::swap(belongs_to[i],belongs_to[end]); end++; } } @@ -1113,7 +1111,7 @@ private: float meanVariance = root->variance*root->size; while (clusterCount::max(); + float minVariance = (std::numeric_limits::max)(); int splitIndex = -1; for (int i=0;i* index = new Index(Matrix(dataset,rows,cols), SavedIndexParams(filename), d); return index; } - catch(runtime_error& e) { + catch(std::runtime_error& e) { logger.error("Caught exception: %s\n",e.what()); return NULL; } @@ -332,7 +331,7 @@ int __flann_find_nearest_neighbors(typename Distance::ElementType* dataset, int delete index; return 0; } - catch(runtime_error& e) { + catch(std::runtime_error& e) { logger.error("Caught exception: %s\n",e.what()); return -1; } @@ -420,7 +419,7 @@ int __flann_find_nearest_neighbors_index(flann_index_t index_ptr, typename Dista return 0; } - catch(runtime_error& e) { + catch(std::runtime_error& e) { logger.error("Caught exception: %s\n",e.what()); return -1; } @@ -514,7 +513,7 @@ int __flann_radius_search(flann_index_t index_ptr, return count; } - catch(runtime_error& e) { + catch(std::runtime_error& e) { logger.error("Caught exception: %s\n",e.what()); return -1; } @@ -625,7 +624,7 @@ int __flann_free_index(flann_index_t index_ptr, FLANNParameters* flann_params) return 0; } - catch(runtime_error& e) { + catch(std::runtime_error& e) { logger.error("Caught exception: %s\n",e.what()); return -1; } @@ -703,7 +702,7 @@ int __flann_compute_cluster_centers(typename Distance::ElementType* dataset, int int clusterNum = hierarchicalClustering(inputData, centers, params, d); return clusterNum; - } catch (runtime_error& e) { + } catch (std::runtime_error& e) { logger.error("Caught exception: %s\n",e.what()); return -1; } diff --git a/src/cpp/flann/flann.hpp b/src/cpp/flann/flann.hpp index d9f3b906ecb599355e3ae028f52b86179eae69a0..a1c022fc1a71aa078e76df4adbfdfebefeebc79e 100644 --- a/src/cpp/flann/flann.hpp +++ b/src/cpp/flann/flann.hpp @@ -43,6 +43,7 @@ #include "flann/nn/index_testing.h" #include "flann/util/object_factory.h" #include "flann/util/saving.h" +#include "flann/util/pair_iterator.hpp" #include "flann/algorithms/all_indices.h" @@ -85,6 +86,7 @@ struct SavedIndexParams : public IndexParams { } }; + template class Index { typedef typename Distance::ElementType ElementType; @@ -117,7 +119,7 @@ public: template -NNIndex* load_saved_index(const Matrix& dataset, const string& filename, Distance distance) +NNIndex* load_saved_index(const Matrix& dataset, const std::string& filename, Distance distance) { typedef typename Distance::ElementType ElementType; @@ -204,15 +206,29 @@ int Index::radiusSearch(const Matrix& query, Matrix& assert(query.cols==nnIndex->veclen()); assert(indices.cols==dists.cols); - RadiusResultSet resultSet(radius, indices[0], dists[0], indices.cols); - nnIndex->findNeighbors(resultSet, query[0] ,searchParams); + int n = 0; + int* indices_ptr = NULL; + DistanceType* dists_ptr = NULL; + if (indices.cols>0) { + n = indices.cols; + indices_ptr = indices[0]; + dists_ptr = dists[0]; + } + RadiusResultSet result_set(radius, indices_ptr, dists_ptr, n); + nnIndex->findNeighbors(result_set, query[0], searchParams); + size_t cnt = result_set.size(); + if (searchParams.sorted) { + std::sort(make_pair_iterator(dists_ptr, indices_ptr), + make_pair_iterator(dists_ptr+cnt, indices_ptr+cnt), + pair_iterator_compare()); + } - return resultSet.size(); + return cnt; } template -void Index::save(string filename) +void Index::save(std::string filename) { FILE* fout = fopen(filename.c_str(), "wb"); if (fout==NULL) { diff --git a/src/cpp/flann/flann_cpp.cpp b/src/cpp/flann/flann_cpp.cpp index bca4fab0726adc06c903130331aa32252d1c0fa9..29336a213f760ef5fbf6f4c246cc1f3bfc22b91a 100644 --- a/src/cpp/flann/flann_cpp.cpp +++ b/src/cpp/flann/flann_cpp.cpp @@ -39,7 +39,6 @@ // index types #include "flann/algorithms/all_indices.h" -using namespace std; #ifdef WIN32 #define EXPORTED extern "C" __declspec(dllexport) diff --git a/src/cpp/flann/general.h b/src/cpp/flann/general.h index 9b40fbe613e2a08981a82553a951dd9df876cdc8..2539ca16d0dfbadf736a8ad6b4a15d2b898589ed 100644 --- a/src/cpp/flann/general.h +++ b/src/cpp/flann/general.h @@ -155,11 +155,12 @@ typedef ObjectFactory ParamsFactory; struct SearchParams { - SearchParams(int checks_ = 32, float eps_ = 0) : - checks(checks_), eps(eps_) {}; + SearchParams(int checks_ = 32, float eps_ = 0, bool sorted_ = true ) : + checks(checks_), eps(eps_), sorted(sorted_) {}; - int checks; - float eps; + int checks; // how many leafs to visit when searching for neighbours (-1 for unlimited) + float eps; // search for eps-approximate neighbours (default: 0) + bool sorted; // only for radius search, require neighbours sorted by distance (default: true) }; } diff --git a/src/cpp/flann/nn/ground_truth.h b/src/cpp/flann/nn/ground_truth.h index 827b749c6375e4cff3173fdc0ae991acb550a762..a4f9de35570affd39a7f07341a3e9dcc3fe07558 100644 --- a/src/cpp/flann/nn/ground_truth.h +++ b/src/cpp/flann/nn/ground_truth.h @@ -67,8 +67,8 @@ void find_nearest(const Matrix& dataset, typenam int j = dcnt-1; // bubble up while (j>=1 && dists[j] -float computeDistanceRaport(const Matrix& inputData, typename Distance::ElementType* target, +typename Distance::ResultType computeDistanceRaport(const Matrix& inputData, typename Distance::ElementType* target, int* neighbors, int* groundTruth, int veclen, int n, const Distance& distance) { - float ret = 0; + typedef typename Distance::ResultType DistanceType; + + DistanceType ret = 0; for (int i=0;i& index, const Matrix& index, const Matrix& testData, const Matrix& matches, int checks, float& precision, const Distance& distance, int nn = 1, int skipMatches = 0) { + typedef typename Distance::ResultType DistanceType; + logger.info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); logger.info("---------------------------------------------------------\n"); float time = 0; - float dist = 0; + DistanceType dist = 0; precision = search_with_ground_truth(index, inputData, testData, matches, nn, checks, time, dist, distance, skipMatches); return time; @@ -142,6 +144,7 @@ float test_index_precision(NNIndex& index, const Matrix& testData, const Matrix& matches, float precision, int& checks, const Distance& distance, int nn = 1, int skipMatches = 0) { + typedef typename Distance::ResultType DistanceType; const float SEARCH_EPS = 0.001; logger.info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); @@ -152,7 +155,7 @@ float test_index_precision(NNIndex& index, const Matrix& index, const Matrix& testData, const Matrix& matches, float* precisions, int precisions_length, const Distance& distance, int nn = 1, int skipMatches = 0, float maxTime = 0) { + typedef typename Distance::ResultType DistanceType; + const float SEARCH_EPS = 0.001; // make sure precisions array is sorted - sort(precisions, precisions+precisions_length); + std::sort(precisions, precisions+precisions_length); int pindex = 0; float precision = precisions[pindex]; @@ -231,7 +236,7 @@ float test_index_precisions(NNIndex& index, const Matrix -using namespace std; namespace flann { @@ -165,11 +163,11 @@ public: if (count == 1) { count = 0; /* For size 1, no need to swap node with itself */ } - else { - swap(heap[1],heap[count]); /* Switch first node with last. */ + else { + std::swap(heap[1],heap[count]); /* Switch first node with last. */ count -= 1; heapify(1); /* Move new node 1 to right position. */ - } + } value = heap[count + 1]; return true; /* Return old last node. */ } @@ -200,7 +198,7 @@ public: /* If a child was smaller, than swap parent with it and Heapify. */ if (minloc != parent) { - swap(heap[parent],heap[minloc]); + std::swap(heap[parent],heap[minloc]); heapify(minloc); } } diff --git a/src/cpp/flann/util/logger.cpp b/src/cpp/flann/util/logger.cpp index eb0b7097336dabc9a597247d25220e7158f5ab2d..2f884649048887ebb2fbf5b1f1bf1aa526002332 100644 --- a/src/cpp/flann/util/logger.cpp +++ b/src/cpp/flann/util/logger.cpp @@ -34,7 +34,6 @@ #include #include -using namespace std; namespace flann { diff --git a/src/cpp/flann/util/logger.h b/src/cpp/flann/util/logger.h index 5a1fe2604e826912c8b63ffdc8299ae5bf782aea..01f4f1edd9fb6fcbba249394dd23631ad5c02719 100644 --- a/src/cpp/flann/util/logger.h +++ b/src/cpp/flann/util/logger.h @@ -31,11 +31,9 @@ #ifndef LOGGER_H #define LOGGER_H - #include #include "flann/general.h" -using namespace std; namespace flann { diff --git a/src/cpp/flann/util/pair_iterator.hpp b/src/cpp/flann/util/pair_iterator.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b1c9fc0cc9fbcb23cd03db86c88d33a0a3afa9a5 --- /dev/null +++ b/src/cpp/flann/util/pair_iterator.hpp @@ -0,0 +1,138 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2010 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2010 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + + +#ifndef PAIR_ITERATOR_HPP_ +#define PAIR_ITERATOR_HPP_ + +#include +#include + +/** + * This file contains a pair iterator that can be used to sort in parallel + * two arrays (or iterators), such as it sorts one array and permutes the + * second one accordingly. + */ + +namespace flann +{ + +template +class pair +{ +public: + First first; + Second second; + + pair(const First& a, const Second& b) : first(a), second(b) {} + + template + pair(const pair& x): first(x.first), second(x.second) {} + + template + pair& operator=(const pair& x) { first = x.first; second = x.second; return *this; } + + pair& operator=(const pair& x) { first = x.first; second = x.second; return *this; } +}; + +template +struct pair_iterator_traits +{ + typedef std::random_access_iterator_tag iterator_category; + typedef pair< + typename std::iterator_traits::value_type, + typename std::iterator_traits::value_type > value_type; + typedef pair< + typename std::iterator_traits::value_type&, + typename std::iterator_traits::value_type& > reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef value_type* pointer; +}; + +template +class pair_iterator +{ +public: + // public typedefs + typedef typename pair_iterator_traits::iterator_category iterator_category; + typedef typename pair_iterator_traits::value_type value_type; + typedef typename pair_iterator_traits::reference reference; + typedef typename pair_iterator_traits::difference_type difference_type; + typedef typename pair_iterator_traits::pointer pointer; + typedef pair_iterator self; + + // constructors + pair_iterator(){ }; + pair_iterator(SortIterator si, PermuteIterator pi) : si_(si), pi_(pi) { } + + // operators + self& operator++( ) { ++si_; ++pi_; return *this; } + self operator++(int) { self tmp = *this; si_++; pi_++; return tmp; } + self& operator--( ) { --si_; --pi_; return *this; } + self operator--(int) { self tmp = *this; si_--; pi_--; return tmp; } + self& operator+=(difference_type x) { si_ += x; pi_ += x; return *this; } + self& operator-=(difference_type x) {si_ -= x; pi_ -= x; return *this; } + reference operator[](difference_type n) { return reference(*(si_+n),*(si_+n)); } + reference operator*() const { return reference(*si_,*pi_); } + self operator+(difference_type y) { return self(si_+y, pi_+y); } + self operator-(difference_type y) { return self(si_-y, pi_-y); } + bool operator==(const self& y) { return si_ == y.si_; } + bool operator!=(const self& y) { return si_ != y.si_; } + bool operator<(const self& y) { return si_ < y.si_; } + difference_type operator-(const self& y) { return si_ - y.si_; } + + // friend operators + friend self operator+(difference_type x, const self& y) { return y + x; } + friend self operator-(difference_type x, const self& y) { return y - x; } +private: + SortIterator si_; + PermuteIterator pi_; +}; + +template +struct pair_iterator_compare : std::binary_function< +typename pair_iterator_traits::value_type, +typename pair_iterator_traits::value_type, +bool> +{ + typedef typename pair_iterator_traits::value_type T; + bool operator()(const T& t1, const T& t2) + { + return (t1.first < t2.first); + } +}; + +template +pair_iterator make_pair_iterator(SortIterator si, PermuteIterator pi) +{ + return pair_iterator(si, pi); +} + +} // namespace flann + +#endif /* PAIR_ITERATOR_HPP_ */ diff --git a/src/cpp/flann/util/random.h b/src/cpp/flann/util/random.h index f78dfee9ee6b7adad9e5664a524c4a222c4d1ad3..af5bbf2fbfbceb81172b043b5d22b880ae929d59 100644 --- a/src/cpp/flann/util/random.h +++ b/src/cpp/flann/util/random.h @@ -35,7 +35,6 @@ #include #include -using namespace std; namespace flann { @@ -109,7 +108,7 @@ public: // int rand = cast(int) (drand48() * n); int rnd = rand_int(i); assert(rnd >=0 && rnd < i); - swap(vals[i-1], vals[rnd]); + std::swap(vals[i-1], vals[rnd]); } counter = 0; diff --git a/src/cpp/flann/util/result_set.h b/src/cpp/flann/util/result_set.h index 29b8fe81139a52d6d13d51b5fd816596819b9499..cd6bb2e075b701ab26b0460acd608ee159587f5f 100644 --- a/src/cpp/flann/util/result_set.h +++ b/src/cpp/flann/util/result_set.h @@ -36,8 +36,6 @@ #include #include -using namespace std; - namespace flann { @@ -94,7 +92,7 @@ public: indices = indices_; dists = dists_; count = 0; - dists[capacity-1] = (numeric_limits::max) (); + dists[capacity-1] = (std::numeric_limits::max) (); } size_t size() const @@ -175,33 +173,13 @@ public: void addPoint(DistanceType dist, int index) { - if (capacity==0) { - count++; - } - else { - if (dist0 && count < capacity) { dists[count] = dist; indices[count] = index; - count++; } -// int i; -// for (i=count; i>0;--i) { -// // if ( (dists[i-1]>dist) || (dist==dists[i-1] && indices[i-1]>index) ) { -// if (dists[i-1]>dist) { -// if (i random_sample(Matrix& srcMatrix, long size, bool remove = false) dest = srcMatrix[srcMatrix.rows-i-1]; src = srcMatrix[r]; for (size_t j=0;j -#include -#include -#include -#include - - - -struct TypedIndex{ - flann_index_t index; - flann_datatype_t type; -}; - - -template -static mxArray* to_mx_array(T value) -{ - mxArray* mat = mxCreateDoubleMatrix(1,1,mxREAL); - double* ptr = mxGetPr(mat); - *ptr = value; - - return mat; -} - - -static void matlabStructToFlannStruct( const mxArray* mexParams, FLANNParameters& flannParams ) -{ - flannParams.algorithm = (flann_algorithm_t)(int)*(mxGetPr(mxGetField(mexParams, 0,"algorithm"))); - - // kdtree - flannParams.trees = (int)*(mxGetPr(mxGetField(mexParams, 0,"trees"))); - - // kmeans - flannParams.branching = (int)*(mxGetPr(mxGetField(mexParams, 0,"branching"))); - flannParams.iterations = (int)*(mxGetPr(mxGetField(mexParams, 0,"iterations"))); - flannParams.centers_init = (flann_centers_init_t)(int)*(mxGetPr(mxGetField(mexParams, 0,"centers_init"))); - flannParams.cb_index = (float)*(mxGetPr(mxGetField(mexParams, 0,"cb_index"))); - - // autotuned - flannParams.target_precision = (float)*(mxGetPr(mxGetField(mexParams, 0,"target_precision"))); - flannParams.build_weight = (float)*(mxGetPr(mxGetField(mexParams, 0,"build_weight"))); - flannParams.memory_weight = (float)*(mxGetPr(mxGetField(mexParams, 0,"memory_weight"))); - flannParams.sample_fraction = (float)*(mxGetPr(mxGetField(mexParams, 0,"sample_fraction"))); - - // misc - flannParams.log_level = (flann_log_level_t)(int)*(mxGetPr(mxGetField(mexParams, 0,"log_level"))); - flannParams.random_seed = (int)*(mxGetPr(mxGetField(mexParams, 0,"random_seed"))); - - // search - flannParams.checks = (int)*(mxGetPr(mxGetField(mexParams, 0,"checks"))); -} - -static void flannStructToMatlabStruct( const FLANNParameters& flannParams, mxArray* mexParams ) -{ - mxSetField(mexParams, 0, "algorithm", to_mx_array(flannParams.algorithm)); - mxSetField(mexParams, 0, "checks", to_mx_array(flannParams.checks)); - mxSetField(mexParams, 0, "trees", to_mx_array(flannParams.trees)); - mxSetField(mexParams, 0, "branching", to_mx_array(flannParams.branching)); - mxSetField(mexParams, 0, "iterations", to_mx_array(flannParams.iterations)); - mxSetField(mexParams, 0, "centers_init", to_mx_array(flannParams.centers_init)); - mxSetField(mexParams, 0, "cb_index", to_mx_array(flannParams.cb_index)); -} - - -static void check_allowed_type(const mxArray* datasetMat) -{ - if (!mxIsSingle(datasetMat) && - !mxIsDouble(datasetMat) && - !mxIsUint8(datasetMat) && - !mxIsInt32(datasetMat)) - { - mexErrMsgTxt("Data type must be floating point single precision, floating point double precision, " - "8 bit unsigned integer or 32 bit signed integer"); - } -} - - -/** - * Input arguments: dataset (matrix), testset (matrix), n (int), params (struct) - * Output arguments: indices(matrix), dists(matrix) - */ -static void _find_nn(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) -{ - /* Check the number of input arguments */ - if(nInArray != 4) { - mexErrMsgTxt("Incorrect number of input arguments, expecting:\n" - "dataset, testset, nearest_neighbors, params"); - } - - /* Check the number of output arguments */ - if(nOutArray > 2) { - mexErrMsgTxt("One or two outputs required."); - } - const mxArray* datasetMat = InArray[0]; - const mxArray* testsetMat = InArray[1]; - check_allowed_type(datasetMat); - check_allowed_type(testsetMat); - - int dcount = mxGetN(datasetMat); - int length = mxGetM(datasetMat); - int tcount = mxGetN(testsetMat); - - if (mxGetM(testsetMat) != length) { - mexErrMsgTxt("Dataset and testset features should have the same size."); - } - - const mxArray* nnMat = InArray[2]; - - if (mxGetM(nnMat)!=1 || mxGetN(nnMat)!=1 || !mxIsNumeric(nnMat)) { - mexErrMsgTxt("Number of nearest neighbors should be a scalar."); - } - int nn = (int)(*mxGetPr(nnMat)); - - const mxArray* pStruct = InArray[3]; - - if (!mxIsStruct(pStruct)) { - mexErrMsgTxt("Params must be a struct object."); - } - - FLANNParameters p; - matlabStructToFlannStruct(pStruct, p); - - int* result = (int*)malloc(tcount*nn*sizeof(int)); - float* dists = NULL; - double* ddists = NULL; - - /* do the search */ - if (mxIsSingle(datasetMat)) { - float* dataset = (float*) mxGetData(datasetMat); - float* testset = (float*) mxGetData(testsetMat); - dists = (float*)malloc(tcount*nn*sizeof(float)); - flann_find_nearest_neighbors_float(dataset,dcount,length,testset, tcount, result, dists, nn, &p); - } - else if (mxIsDouble(datasetMat)) { - double* dataset = (double*) mxGetData(datasetMat); - double* testset = (double*) mxGetData(testsetMat); - ddists = (double*)malloc(tcount*nn*sizeof(double)); - flann_find_nearest_neighbors_double(dataset,dcount,length,testset, tcount, result, ddists, nn, &p); - } - else if (mxIsUint8(datasetMat)) { - unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); - unsigned char* testset = (unsigned char*) mxGetData(testsetMat); - dists = (float*)malloc(tcount*nn*sizeof(float)); - flann_find_nearest_neighbors_byte(dataset,dcount,length,testset, tcount, result, dists, nn, &p); - } - else if (mxIsInt32(datasetMat)) { - int* dataset = (int*) mxGetData(datasetMat); - int* testset = (int*) mxGetData(testsetMat); - dists = (float*)malloc(tcount*nn*sizeof(float)); - flann_find_nearest_neighbors_int(dataset,dcount,length,testset, tcount, result, dists, nn, &p); - } - - /* Allocate memory for Output Matrix */ - OutArray[0] = mxCreateDoubleMatrix(nn, tcount, mxREAL); - - /* Get pointer to Output matrix and store result */ - double* pOut = mxGetPr(OutArray[0]); - for (int i=0;i 1) { - /* Allocate memory for Output Matrix */ - OutArray[1] = mxCreateDoubleMatrix(nn, tcount, mxREAL); - - /* Get pointer to Output matrix and store result*/ - double* pDists = mxGetPr(OutArray[1]); - if (dists!=NULL) { - for (int i=0;i 2) { - mexErrMsgTxt("One or two outputs required."); - } - - const mxArray* indexMat = InArray[0]; - TypedIndex* typedIndex = *(TypedIndex**)mxGetData(indexMat); - - const mxArray* testsetMat = InArray[1]; - check_allowed_type(testsetMat); - - int tcount = mxGetN(testsetMat); - - const mxArray* nnMat = InArray[2]; - - if (mxGetM(nnMat)!=1 || mxGetN(nnMat)!=1) { - mexErrMsgTxt("Number of nearest neighbors should be a scalar."); - } - int nn = (int)(*mxGetPr(nnMat)); - - int* result = (int*)malloc(tcount*nn*sizeof(int)); - float* dists = NULL; - double* ddists = NULL; - - const mxArray* pStruct = InArray[3]; - - FLANNParameters p; - matlabStructToFlannStruct(pStruct, p); - - if (mxIsSingle(testsetMat)) { - if (typedIndex->type != FLANN_FLOAT32) { - mexErrMsgTxt("Index type must match testset type"); - } - float* testset = (float*) mxGetData(testsetMat); - dists = (float*)malloc(tcount*nn*sizeof(float)); - flann_find_nearest_neighbors_index_float(typedIndex->index,testset, tcount, result, dists, nn, &p); - } - else if (mxIsDouble(testsetMat)) { - if (typedIndex->type != FLANN_FLOAT64) { - mexErrMsgTxt("Index type must match testset type"); - } - double* testset = (double*) mxGetData(testsetMat); - ddists = (double*)malloc(tcount*nn*sizeof(double)); - flann_find_nearest_neighbors_index_double(typedIndex->index,testset, tcount, result, ddists, nn, &p); - } - else if (mxIsUint8(testsetMat)) { - if (typedIndex->type != FLANN_UINT8) { - mexErrMsgTxt("Index type must match testset type"); - } - unsigned char* testset = (unsigned char*) mxGetData(testsetMat); - dists = (float*)malloc(tcount*nn*sizeof(float)); - flann_find_nearest_neighbors_index_byte(typedIndex->index,testset, tcount, result, dists, nn, &p); - } - else if (mxIsInt32(testsetMat)) { - if (typedIndex->type != FLANN_INT32) { - mexErrMsgTxt("Index type must match testset type"); - } - int* testset = (int*) mxGetData(testsetMat); - dists = (float*)malloc(tcount*nn*sizeof(float)); - flann_find_nearest_neighbors_index_int(typedIndex->index,testset, tcount, result, dists, nn, &p); - } - - /* Allocate memory for Output Matrix */ - OutArray[0] = mxCreateDoubleMatrix(nn, tcount, mxREAL); - - /* Get pointer to Output matrix and store result*/ - double* pOut = mxGetPr(OutArray[0]); - for (int i=0;i 1) { - /* Allocate memory for Output Matrix */ - OutArray[1] = mxCreateDoubleMatrix(nn, tcount, mxREAL); - - /* Get pointer to Output matrix and store result*/ - double* pDists = mxGetPr(OutArray[1]); - if (dists!=NULL) { - for (int i=0;i +#include +#include +#include +#include + + + +struct TypedIndex{ + flann_index_t index; + flann_datatype_t type; +}; + + +template +static mxArray* to_mx_array(T value) +{ + mxArray* mat = mxCreateDoubleMatrix(1,1,mxREAL); + double* ptr = mxGetPr(mat); + *ptr = value; + + return mat; +} + + +static void matlabStructToFlannStruct( const mxArray* mexParams, FLANNParameters& flannParams ) +{ + flannParams.algorithm = (flann_algorithm_t)(int)*(mxGetPr(mxGetField(mexParams, 0,"algorithm"))); + + // kdtree + flannParams.trees = (int)*(mxGetPr(mxGetField(mexParams, 0,"trees"))); + + // kmeans + flannParams.branching = (int)*(mxGetPr(mxGetField(mexParams, 0,"branching"))); + flannParams.iterations = (int)*(mxGetPr(mxGetField(mexParams, 0,"iterations"))); + flannParams.centers_init = (flann_centers_init_t)(int)*(mxGetPr(mxGetField(mexParams, 0,"centers_init"))); + flannParams.cb_index = (float)*(mxGetPr(mxGetField(mexParams, 0,"cb_index"))); + + // autotuned + flannParams.target_precision = (float)*(mxGetPr(mxGetField(mexParams, 0,"target_precision"))); + flannParams.build_weight = (float)*(mxGetPr(mxGetField(mexParams, 0,"build_weight"))); + flannParams.memory_weight = (float)*(mxGetPr(mxGetField(mexParams, 0,"memory_weight"))); + flannParams.sample_fraction = (float)*(mxGetPr(mxGetField(mexParams, 0,"sample_fraction"))); + + // misc + flannParams.log_level = (flann_log_level_t)(int)*(mxGetPr(mxGetField(mexParams, 0,"log_level"))); + flannParams.random_seed = (int)*(mxGetPr(mxGetField(mexParams, 0,"random_seed"))); + + // search + flannParams.checks = (int)*(mxGetPr(mxGetField(mexParams, 0,"checks"))); +} + +static void flannStructToMatlabStruct( const FLANNParameters& flannParams, mxArray* mexParams ) +{ + mxSetField(mexParams, 0, "algorithm", to_mx_array(flannParams.algorithm)); + mxSetField(mexParams, 0, "checks", to_mx_array(flannParams.checks)); + mxSetField(mexParams, 0, "trees", to_mx_array(flannParams.trees)); + mxSetField(mexParams, 0, "branching", to_mx_array(flannParams.branching)); + mxSetField(mexParams, 0, "iterations", to_mx_array(flannParams.iterations)); + mxSetField(mexParams, 0, "centers_init", to_mx_array(flannParams.centers_init)); + mxSetField(mexParams, 0, "cb_index", to_mx_array(flannParams.cb_index)); +} + + +static void check_allowed_type(const mxArray* datasetMat) +{ + if (!mxIsSingle(datasetMat) && + !mxIsDouble(datasetMat) && + !mxIsUint8(datasetMat) && + !mxIsInt32(datasetMat)) + { + mexErrMsgTxt("Data type must be floating point single precision, floating point double precision, " + "8 bit unsigned integer or 32 bit signed integer"); + } +} + + +/** + * Input arguments: dataset (matrix), testset (matrix), n (int), params (struct) + * Output arguments: indices(matrix), dists(matrix) + */ +static void _find_nn(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) +{ + /* Check the number of input arguments */ + if(nInArray != 4) { + mexErrMsgTxt("Incorrect number of input arguments, expecting:\n" + "dataset, testset, nearest_neighbors, params"); + } + + /* Check the number of output arguments */ + if(nOutArray > 2) { + mexErrMsgTxt("One or two outputs required."); + } + const mxArray* datasetMat = InArray[0]; + const mxArray* testsetMat = InArray[1]; + check_allowed_type(datasetMat); + check_allowed_type(testsetMat); + + int dcount = mxGetN(datasetMat); + int length = mxGetM(datasetMat); + int tcount = mxGetN(testsetMat); + + if (mxGetM(testsetMat) != length) { + mexErrMsgTxt("Dataset and testset features should have the same size."); + } + + const mxArray* nnMat = InArray[2]; + + if (mxGetM(nnMat)!=1 || mxGetN(nnMat)!=1 || !mxIsNumeric(nnMat)) { + mexErrMsgTxt("Number of nearest neighbors should be a scalar."); + } + int nn = (int)(*mxGetPr(nnMat)); + + const mxArray* pStruct = InArray[3]; + + if (!mxIsStruct(pStruct)) { + mexErrMsgTxt("Params must be a struct object."); + } + + FLANNParameters p; + matlabStructToFlannStruct(pStruct, p); + + int* result = (int*)malloc(tcount*nn*sizeof(int)); + float* dists = NULL; + double* ddists = NULL; + + /* do the search */ + if (mxIsSingle(datasetMat)) { + float* dataset = (float*) mxGetData(datasetMat); + float* testset = (float*) mxGetData(testsetMat); + dists = (float*)malloc(tcount*nn*sizeof(float)); + flann_find_nearest_neighbors_float(dataset,dcount,length,testset, tcount, result, dists, nn, &p); + } + else if (mxIsDouble(datasetMat)) { + double* dataset = (double*) mxGetData(datasetMat); + double* testset = (double*) mxGetData(testsetMat); + ddists = (double*)malloc(tcount*nn*sizeof(double)); + flann_find_nearest_neighbors_double(dataset,dcount,length,testset, tcount, result, ddists, nn, &p); + } + else if (mxIsUint8(datasetMat)) { + unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); + unsigned char* testset = (unsigned char*) mxGetData(testsetMat); + dists = (float*)malloc(tcount*nn*sizeof(float)); + flann_find_nearest_neighbors_byte(dataset,dcount,length,testset, tcount, result, dists, nn, &p); + } + else if (mxIsInt32(datasetMat)) { + int* dataset = (int*) mxGetData(datasetMat); + int* testset = (int*) mxGetData(testsetMat); + dists = (float*)malloc(tcount*nn*sizeof(float)); + flann_find_nearest_neighbors_int(dataset,dcount,length,testset, tcount, result, dists, nn, &p); + } + + /* Allocate memory for Output Matrix */ + OutArray[0] = mxCreateDoubleMatrix(nn, tcount, mxREAL); + + /* Get pointer to Output matrix and store result */ + double* pOut = mxGetPr(OutArray[0]); + for (int i=0;i 1) { + /* Allocate memory for Output Matrix */ + OutArray[1] = mxCreateDoubleMatrix(nn, tcount, mxREAL); + + /* Get pointer to Output matrix and store result*/ + double* pDists = mxGetPr(OutArray[1]); + if (dists!=NULL) { + for (int i=0;i 2) { + mexErrMsgTxt("One or two outputs required."); + } + + const mxArray* indexMat = InArray[0]; + TypedIndex* typedIndex = *(TypedIndex**)mxGetData(indexMat); + + const mxArray* testsetMat = InArray[1]; + check_allowed_type(testsetMat); + + int tcount = mxGetN(testsetMat); + + const mxArray* nnMat = InArray[2]; + + if (mxGetM(nnMat)!=1 || mxGetN(nnMat)!=1) { + mexErrMsgTxt("Number of nearest neighbors should be a scalar."); + } + int nn = (int)(*mxGetPr(nnMat)); + + int* result = (int*)malloc(tcount*nn*sizeof(int)); + float* dists = NULL; + double* ddists = NULL; + + const mxArray* pStruct = InArray[3]; + + FLANNParameters p; + matlabStructToFlannStruct(pStruct, p); + + if (mxIsSingle(testsetMat)) { + if (typedIndex->type != FLANN_FLOAT32) { + mexErrMsgTxt("Index type must match testset type"); + } + float* testset = (float*) mxGetData(testsetMat); + dists = (float*)malloc(tcount*nn*sizeof(float)); + flann_find_nearest_neighbors_index_float(typedIndex->index,testset, tcount, result, dists, nn, &p); + } + else if (mxIsDouble(testsetMat)) { + if (typedIndex->type != FLANN_FLOAT64) { + mexErrMsgTxt("Index type must match testset type"); + } + double* testset = (double*) mxGetData(testsetMat); + ddists = (double*)malloc(tcount*nn*sizeof(double)); + flann_find_nearest_neighbors_index_double(typedIndex->index,testset, tcount, result, ddists, nn, &p); + } + else if (mxIsUint8(testsetMat)) { + if (typedIndex->type != FLANN_UINT8) { + mexErrMsgTxt("Index type must match testset type"); + } + unsigned char* testset = (unsigned char*) mxGetData(testsetMat); + dists = (float*)malloc(tcount*nn*sizeof(float)); + flann_find_nearest_neighbors_index_byte(typedIndex->index,testset, tcount, result, dists, nn, &p); + } + else if (mxIsInt32(testsetMat)) { + if (typedIndex->type != FLANN_INT32) { + mexErrMsgTxt("Index type must match testset type"); + } + int* testset = (int*) mxGetData(testsetMat); + dists = (float*)malloc(tcount*nn*sizeof(float)); + flann_find_nearest_neighbors_index_int(typedIndex->index,testset, tcount, result, dists, nn, &p); + } + + /* Allocate memory for Output Matrix */ + OutArray[0] = mxCreateDoubleMatrix(nn, tcount, mxREAL); + + /* Get pointer to Output matrix and store result*/ + double* pOut = mxGetPr(OutArray[0]); + for (int i=0;i 1) { + /* Allocate memory for Output Matrix */ + OutArray[1] = mxCreateDoubleMatrix(nn, tcount, mxREAL); + + /* Get pointer to Output matrix and store result*/ + double* pDists = mxGetPr(OutArray[1]); + if (dists!=NULL) { + for (int i=0;i 3) { - mexErrMsgTxt("Incorrect number of outputs."); - } - const mxArray* datasetMat = InArray[0]; - check_allowed_type(datasetMat); - - int dcount = mxGetN(datasetMat); - int length = mxGetM(datasetMat); - - - const mxArray* pStruct = InArray[1]; - - /* get index parameters */ - FLANNParameters p; - matlabStructToFlannStruct(pStruct, p); - - float speedup = -1; - - TypedIndex* typedIndex = new TypedIndex(); - - if (mxIsSingle(datasetMat)) { - float* dataset = (float*) mxGetData(datasetMat); - typedIndex->index = flann_build_index_float(dataset,dcount,length, &speedup, &p); - typedIndex->type = FLANN_FLOAT32; - } - else if (mxIsDouble(datasetMat)) { - double* dataset = (double*) mxGetData(datasetMat); - typedIndex->index = flann_build_index_double(dataset,dcount,length, &speedup, &p); - typedIndex->type = FLANN_FLOAT64; - } - else if (mxIsUint8(datasetMat)) { - unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); - typedIndex->index = flann_build_index_byte(dataset,dcount,length, &speedup, &p); - typedIndex->type = FLANN_UINT8; - } - else if (mxIsInt32(datasetMat)) { - int* dataset = (int*) mxGetData(datasetMat); - typedIndex->index = flann_build_index_int(dataset,dcount,length, &speedup, &p); - typedIndex->type = FLANN_INT32; - } - - mxClassID classID; - if (sizeof(flann_index_t)==4) { - classID = mxUINT32_CLASS; - } - else if (sizeof(flann_index_t)==8) { - classID = mxUINT64_CLASS; - } - - /* Allocate memory for Output Matrix */ - OutArray[0] = mxCreateNumericMatrix(1, 1, classID, mxREAL); - - /* Get pointer to Output matrix and store result*/ - TypedIndex** pOut = (TypedIndex**)mxGetData(OutArray[0]); - pOut[0] = typedIndex; - - if (nOutArray > 1) { - const char *fieldnames[] = {"algorithm", "checks", "trees", "branching", "iterations", "centers_init", "cb_index"}; - OutArray[1] = mxCreateStructMatrix(1, 1, sizeof(fieldnames)/sizeof(const char*), fieldnames); - flannStructToMatlabStruct(p, OutArray[1]); - } - if (nOutArray > 2) { - OutArray[2] = mxCreateDoubleMatrix(1, 1, mxREAL); - double* pSpeedup = mxGetPr(OutArray[2]); - - *pSpeedup = speedup; - } -} - -/** + */ +static void _build_index(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) +{ + /* Check the number of input arguments */ + if(nInArray != 2) { + mexErrMsgTxt("Incorrect number of input arguments"); + } + /* Check the number of output arguments */ + if (nOutArray == 0 || nOutArray > 3) { + mexErrMsgTxt("Incorrect number of outputs."); + } + const mxArray* datasetMat = InArray[0]; + check_allowed_type(datasetMat); + + int dcount = mxGetN(datasetMat); + int length = mxGetM(datasetMat); + + + const mxArray* pStruct = InArray[1]; + + /* get index parameters */ + FLANNParameters p; + matlabStructToFlannStruct(pStruct, p); + + float speedup = -1; + + TypedIndex* typedIndex = new TypedIndex(); + + if (mxIsSingle(datasetMat)) { + float* dataset = (float*) mxGetData(datasetMat); + typedIndex->index = flann_build_index_float(dataset,dcount,length, &speedup, &p); + typedIndex->type = FLANN_FLOAT32; + } + else if (mxIsDouble(datasetMat)) { + double* dataset = (double*) mxGetData(datasetMat); + typedIndex->index = flann_build_index_double(dataset,dcount,length, &speedup, &p); + typedIndex->type = FLANN_FLOAT64; + } + else if (mxIsUint8(datasetMat)) { + unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); + typedIndex->index = flann_build_index_byte(dataset,dcount,length, &speedup, &p); + typedIndex->type = FLANN_UINT8; + } + else if (mxIsInt32(datasetMat)) { + int* dataset = (int*) mxGetData(datasetMat); + typedIndex->index = flann_build_index_int(dataset,dcount,length, &speedup, &p); + typedIndex->type = FLANN_INT32; + } + + mxClassID classID; + if (sizeof(flann_index_t)==4) { + classID = mxUINT32_CLASS; + } + else if (sizeof(flann_index_t)==8) { + classID = mxUINT64_CLASS; + } + + /* Allocate memory for Output Matrix */ + OutArray[0] = mxCreateNumericMatrix(1, 1, classID, mxREAL); + + /* Get pointer to Output matrix and store result*/ + TypedIndex** pOut = (TypedIndex**)mxGetData(OutArray[0]); + pOut[0] = typedIndex; + + if (nOutArray > 1) { + const char *fieldnames[] = {"algorithm", "checks", "trees", "branching", "iterations", "centers_init", "cb_index"}; + OutArray[1] = mxCreateStructMatrix(1, 1, sizeof(fieldnames)/sizeof(const char*), fieldnames); + flannStructToMatlabStruct(p, OutArray[1]); + } + if (nOutArray > 2) { + OutArray[2] = mxCreateDoubleMatrix(1, 1, mxREAL); + double* pSpeedup = mxGetPr(OutArray[2]); + + *pSpeedup = speedup; + } +} + +/** * Inputs: index (index pointer) - */ -static void _free_index(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) -{ - /* Check the number of input arguments */ - if(! (nInArray == 1 && (mxGetN(InArray[0])*mxGetM(InArray[0]))==1)) { - mexErrMsgTxt("Expecting a single scalar argument: the index ID"); - } - TypedIndex* typedIndex = *(TypedIndex**)mxGetData(InArray[0]); - if (typedIndex->type==FLANN_FLOAT32) { - flann_free_index_float(typedIndex->index, NULL); - } - else if (typedIndex->type==FLANN_FLOAT64) { - flann_free_index_double(typedIndex->index, NULL); - } - else if (typedIndex->type==FLANN_UINT8) { - flann_free_index_byte(typedIndex->index, NULL); - } - else if (typedIndex->type==FLANN_INT32) { - flann_free_index_int(typedIndex->index, NULL); - } - delete typedIndex; -} - -/** - * Inputs: level - */ -static void _set_log_level(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) -{ - if (nInArray != 1) { - mexErrMsgTxt("Incorrect number of input arguments: expecting log_level"); - } - - const mxArray* llMat = InArray[0]; - - if (mxGetM(llMat)!=1 || mxGetN(llMat)!=1 || !mxIsNumeric(llMat)) { - mexErrMsgTxt("Log Level should be a scalar."); - } - int log_level = (int)(*mxGetPr(llMat)); - - flann_log_verbosity(log_level); - -} - -/** - * Inputs: type (flann_distance_t), order(int) - */ -static void _set_distance_type(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) -{ - if( (nInArray != 1 && nInArray != 2)) { - mexErrMsgTxt("Incorrect number of input arguments"); - } - - const mxArray* distMat = InArray[0]; - - if (mxGetM(distMat)!=1 || mxGetN(distMat)!=1 || !mxIsNumeric(distMat)) { - mexErrMsgTxt("Distance type should be a scalar."); - } - int distance_type = (int)(*mxGetPr(distMat)); - - int order = 0; - if (nInArray==2) { - const mxArray* ordMat = InArray[1]; - if (mxGetM(ordMat)!=1 || mxGetN(ordMat)!=1 || !mxIsNumeric(ordMat)) { - mexErrMsgTxt("Distance order should be a scalar."); - } - - order = (int)(*mxGetPr(ordMat)); - } - flann_set_distance_type((flann_distance_t)distance_type, order); -} - - -/** - * Inputs: index (index pointer), filename (string) - */ -static void _save_index(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) -{ - /* Check the number of input arguments */ - if(nInArray != 2) { - mexErrMsgTxt("Incorrect number of input arguments"); - } - - const mxArray* indexMat = InArray[0]; - TypedIndex* typedIndex = *(TypedIndex**)mxGetData(indexMat); - - // get the selector - if(!mxIsChar(InArray[1])) { - mexErrMsgTxt("'filename' should be a string"); - } - char filename[128]; - mxGetString(InArray[1],filename,128); - - if (typedIndex->type==FLANN_FLOAT32) { - flann_save_index_float(typedIndex->index, filename); - } - else if (typedIndex->type==FLANN_FLOAT64) { - flann_save_index_double(typedIndex->index, filename); - } - else if (typedIndex->type==FLANN_UINT8) { - flann_save_index_byte(typedIndex->index, filename); - } - else if (typedIndex->type==FLANN_INT32) { - flann_save_index_int(typedIndex->index, filename); - } -} - - -/** - * Inputs: filename (string), matrix - */ -static void _load_index(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) -{ - if(nInArray != 2) { - mexErrMsgTxt("Incorrect number of input arguments"); - } - // get the selector - if(!mxIsChar(InArray[0])) { - mexErrMsgTxt("'filename' should be a string"); - } - char filename[128]; - mxGetString(InArray[0],filename,128); - - const mxArray* datasetMat = InArray[1]; - check_allowed_type(datasetMat); - - int dcount = mxGetN(datasetMat); - int length = mxGetM(datasetMat); - - TypedIndex* typedIndex = new TypedIndex(); - - if (mxIsSingle(datasetMat)) { - float* dataset = (float*) mxGetData(datasetMat); - typedIndex->index = flann_load_index_float(filename, dataset,dcount,length); - typedIndex->type = FLANN_FLOAT32; - } - else if (mxIsDouble(datasetMat)) { - double* dataset = (double*) mxGetData(datasetMat); - typedIndex->index = flann_load_index_double(filename, dataset,dcount,length); - typedIndex->type = FLANN_FLOAT64; - } - else if (mxIsUint8(datasetMat)) { - unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); - typedIndex->index = flann_load_index_byte(filename, dataset,dcount,length); - typedIndex->type = FLANN_UINT8; - } - else if (mxIsInt32(datasetMat)) { - int* dataset = (int*) mxGetData(datasetMat); - typedIndex->index = flann_load_index_int(filename, dataset,dcount,length); - typedIndex->type = FLANN_INT32; - } - - mxClassID classID; - if (sizeof(flann_index_t)==4) { - classID = mxUINT32_CLASS; - } - else if (sizeof(flann_index_t)==8) { - classID = mxUINT64_CLASS; - } - - /* Allocate memory for Output Matrix */ - OutArray[0] = mxCreateNumericMatrix(1, 1, classID, mxREAL); - - /* Get pointer to Output matrix and store result*/ - TypedIndex** pOut = (TypedIndex**)mxGetData(OutArray[0]); - pOut[0] = typedIndex; -} - - -struct mexFunctionEntry -{ - const char* name; - void (*function)(int, mxArray**, int, const mxArray**); -}; - -static mexFunctionEntry __functionTable[] = { - { "find_nn", &_find_nn}, - { "build_index", &_build_index}, - { "index_find_nn", &_index_find_nn}, - { "free_index", &_free_index}, - { "save_index", &_save_index}, - { "load_index", &_load_index}, - { "set_log_level", &_set_log_level}, - { "set_distance_type", &_set_distance_type}, -}; - - -static void print_selector_error() -{ - ostringstream oss; - oss << "Expecting first argument to be one of: "; - - for (int i=0;itype==FLANN_FLOAT32) { + flann_free_index_float(typedIndex->index, NULL); + } + else if (typedIndex->type==FLANN_FLOAT64) { + flann_free_index_double(typedIndex->index, NULL); + } + else if (typedIndex->type==FLANN_UINT8) { + flann_free_index_byte(typedIndex->index, NULL); + } + else if (typedIndex->type==FLANN_INT32) { + flann_free_index_int(typedIndex->index, NULL); + } + delete typedIndex; +} + +/** + * Inputs: level + */ +static void _set_log_level(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) +{ + if (nInArray != 1) { + mexErrMsgTxt("Incorrect number of input arguments: expecting log_level"); + } + + const mxArray* llMat = InArray[0]; + + if (mxGetM(llMat)!=1 || mxGetN(llMat)!=1 || !mxIsNumeric(llMat)) { + mexErrMsgTxt("Log Level should be a scalar."); + } + int log_level = (int)(*mxGetPr(llMat)); + + flann_log_verbosity(log_level); + +} + +/** + * Inputs: type (flann_distance_t), order(int) + */ +static void _set_distance_type(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) +{ + if( (nInArray != 1 && nInArray != 2)) { + mexErrMsgTxt("Incorrect number of input arguments"); + } + + const mxArray* distMat = InArray[0]; + + if (mxGetM(distMat)!=1 || mxGetN(distMat)!=1 || !mxIsNumeric(distMat)) { + mexErrMsgTxt("Distance type should be a scalar."); + } + int distance_type = (int)(*mxGetPr(distMat)); + + int order = 0; + if (nInArray==2) { + const mxArray* ordMat = InArray[1]; + if (mxGetM(ordMat)!=1 || mxGetN(ordMat)!=1 || !mxIsNumeric(ordMat)) { + mexErrMsgTxt("Distance order should be a scalar."); + } + + order = (int)(*mxGetPr(ordMat)); + } + flann_set_distance_type((flann_distance_t)distance_type, order); +} + + +/** + * Inputs: index (index pointer), filename (string) + */ +static void _save_index(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) +{ + /* Check the number of input arguments */ + if(nInArray != 2) { + mexErrMsgTxt("Incorrect number of input arguments"); + } + + const mxArray* indexMat = InArray[0]; + TypedIndex* typedIndex = *(TypedIndex**)mxGetData(indexMat); + + // get the selector + if(!mxIsChar(InArray[1])) { + mexErrMsgTxt("'filename' should be a string"); + } + char filename[128]; + mxGetString(InArray[1],filename,128); + + if (typedIndex->type==FLANN_FLOAT32) { + flann_save_index_float(typedIndex->index, filename); + } + else if (typedIndex->type==FLANN_FLOAT64) { + flann_save_index_double(typedIndex->index, filename); + } + else if (typedIndex->type==FLANN_UINT8) { + flann_save_index_byte(typedIndex->index, filename); + } + else if (typedIndex->type==FLANN_INT32) { + flann_save_index_int(typedIndex->index, filename); + } +} + + +/** + * Inputs: filename (string), matrix + */ +static void _load_index(int nOutArray, mxArray *OutArray[], int nInArray, const mxArray *InArray[]) +{ + if(nInArray != 2) { + mexErrMsgTxt("Incorrect number of input arguments"); + } + // get the selector + if(!mxIsChar(InArray[0])) { + mexErrMsgTxt("'filename' should be a string"); + } + char filename[128]; + mxGetString(InArray[0],filename,128); + + const mxArray* datasetMat = InArray[1]; + check_allowed_type(datasetMat); + + int dcount = mxGetN(datasetMat); + int length = mxGetM(datasetMat); + + TypedIndex* typedIndex = new TypedIndex(); + + if (mxIsSingle(datasetMat)) { + float* dataset = (float*) mxGetData(datasetMat); + typedIndex->index = flann_load_index_float(filename, dataset,dcount,length); + typedIndex->type = FLANN_FLOAT32; + } + else if (mxIsDouble(datasetMat)) { + double* dataset = (double*) mxGetData(datasetMat); + typedIndex->index = flann_load_index_double(filename, dataset,dcount,length); + typedIndex->type = FLANN_FLOAT64; + } + else if (mxIsUint8(datasetMat)) { + unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); + typedIndex->index = flann_load_index_byte(filename, dataset,dcount,length); + typedIndex->type = FLANN_UINT8; + } + else if (mxIsInt32(datasetMat)) { + int* dataset = (int*) mxGetData(datasetMat); + typedIndex->index = flann_load_index_int(filename, dataset,dcount,length); + typedIndex->type = FLANN_INT32; + } + + mxClassID classID; + if (sizeof(flann_index_t)==4) { + classID = mxUINT32_CLASS; + } + else if (sizeof(flann_index_t)==8) { + classID = mxUINT64_CLASS; + } + + /* Allocate memory for Output Matrix */ + OutArray[0] = mxCreateNumericMatrix(1, 1, classID, mxREAL); + + /* Get pointer to Output matrix and store result*/ + TypedIndex** pOut = (TypedIndex**)mxGetData(OutArray[0]); + pOut[0] = typedIndex; +} + + +struct mexFunctionEntry +{ + const char* name; + void (*function)(int, mxArray**, int, const mxArray**); +}; + +static mexFunctionEntry __functionTable[] = { + { "find_nn", &_find_nn}, + { "build_index", &_build_index}, + { "index_find_nn", &_index_find_nn}, + { "free_index", &_free_index}, + { "save_index", &_save_index}, + { "load_index", &_load_index}, + { "set_log_level", &_set_log_level}, + { "set_distance_type", &_set_distance_type}, +}; + + +static void print_selector_error() +{ + std::ostringstream oss; + oss << "Expecting first argument to be one of: "; + + for (int i=0;i