62 static constexpr bool same_internal_data = std::is_same<Float_, InternalData_>::value;
63 typename std::conditional<!same_internal_data, std::vector<InternalData_>,
bool>::type my_buffer, my_distances;
65 static constexpr bool same_internal_index = std::is_same<Index_, InternalIndex_>::value;
66 std::vector<InternalIndex_> my_indices;
68 int get_search_k(
int k)
const {
69 if (my_parent->my_search_mult < 0) {
72 return my_parent->my_search_mult *
static_cast<double>(k) + 0.5;
81 if constexpr(!same_internal_data) {
82 my_buffer.resize(my_parent->my_dim);
90 auto obtain_pointers(std::vector<Index_>* output_indices, std::vector<Float_>* output_distances, Index_ k) {
91 std::vector<InternalIndex_>* icopy_ptr = &my_indices;
93 if constexpr(same_internal_index) {
94 icopy_ptr = output_indices;
98 icopy_ptr->reserve(k);
100 std::vector<InternalData_>* dcopy_ptr = NULL;
101 if (output_distances) {
102 if constexpr(same_internal_data) {
103 dcopy_ptr = output_distances;
105 dcopy_ptr = &my_distances;
108 dcopy_ptr->reserve(k);
111 return std::make_pair(icopy_ptr, dcopy_ptr);
114 template<
typename Type_>
115 static void remove_self(std::vector<Type_>& vec,
size_t at) {
116 if (at < vec.size()) {
117 vec.erase(vec.begin() + at);
123 template<
typename Source_,
typename Dest_>
124 static void copy_skip_self(
const std::vector<Source_>& source, std::vector<Dest_>& dest,
size_t at) {
125 auto sIt = source.begin();
126 size_t end = source.size();
128 dest.reserve(end - 1);
131 dest.insert(dest.end(), sIt, sIt + at);
132 dest.insert(dest.end(), sIt + at + 1, source.end());
139 dest.insert(dest.end(), sIt, sIt + end - 1);
147 void search(Index_ i, Index_ k, std::vector<Index_>* output_indices, std::vector<Float_>* output_distances) {
149 auto ptrs = obtain_pointers(output_indices, output_distances, kp1);
150 auto icopy_ptr = ptrs.first;
151 auto dcopy_ptr = ptrs.second;
153 my_parent->my_index.get_nns_by_item(i, kp1, get_search_k(kp1), icopy_ptr, dcopy_ptr);
157 const auto& cur_i = *icopy_ptr;
159 InternalIndex_ icopy = i;
160 for (
size_t x = 0, end = cur_i.size(); x < end; ++x) {
161 if (cur_i[x] == icopy) {
168 if (output_indices) {
169 if constexpr(same_internal_index) {
170 remove_self(*output_indices, at);
172 copy_skip_self(my_indices, *output_indices, at);
176 if (output_distances) {
177 if constexpr(same_internal_data) {
178 remove_self(*output_distances, at);
180 copy_skip_self(my_distances, *output_distances, at);
186 void search_raw(
const InternalData_* query, Index_ k, std::vector<Index_>* output_indices, std::vector<Float_>* output_distances) {
187 auto ptrs = obtain_pointers(output_indices, output_distances, k);
188 auto icopy_ptr = ptrs.first;
189 auto dcopy_ptr = ptrs.second;
191 my_parent->my_index.get_nns_by_vector(query, k, get_search_k(k), icopy_ptr, dcopy_ptr);
193 if (output_indices) {
194 if constexpr(!same_internal_index) {
195 output_indices->clear();
196 output_indices->insert(output_indices->end(), my_indices.begin(), my_indices.end());
200 if (output_distances) {
201 if constexpr(!same_internal_data) {
202 output_distances->clear();
203 output_distances->insert(output_distances->end(), my_distances.begin(), my_distances.end());
212 void search(
const Float_* query, Index_ k, std::vector<Index_>* output_indices, std::vector<Float_>* output_distances) {
213 if constexpr(same_internal_data) {
214 search_raw(query, k, output_indices, output_distances);
216 std::copy_n(query, my_parent->my_dim, my_buffer.begin());
217 search_raw(my_buffer.data(), k, output_indices, output_distances);
242 template<
class Matrix_>
244 my_dim(data.num_dimensions()),
245 my_obs(data.num_observations()),
249 typedef typename Matrix_::data_type Data_;
250 auto work = data.create_workspace();
251 if constexpr(std::is_same<Data_, InternalData_>::value) {
252 for (Index_ i = 0; i < my_obs; ++i) {
253 auto ptr = data.get_observation(work);
254 my_index.add_item(i, ptr);
257 std::vector<InternalData_> incoming(my_dim);
258 for (Index_ i = 0; i < my_obs; ++i) {
259 auto ptr = data.get_observation(work);
260 std::copy_n(ptr, my_dim, incoming.begin());
261 my_index.add_item(i, incoming.data());
275 double my_search_mult;
276 Annoy::AnnoyIndex<InternalIndex_, InternalData_, Distance_, Annoy::Kiss64Random, Annoy::AnnoyIndexSingleThreadedBuildPolicy> my_index;
278 friend class AnnoySearcher<Distance_, Dim_, Index_, Float_, InternalIndex_, InternalData_>;
298 std::unique_ptr<knncolle::Searcher<Index_, Float_> >
initialize()
const {
299 return std::make_unique<AnnoySearcher<Distance_, Dim_, Index_, Float_, InternalIndex_, InternalData_> >(
this);
void search(Index_ i, Index_ k, std::vector< Index_ > *output_indices, std::vector< Float_ > *output_distances)
Definition knncolle_annoy.hpp:147
void search(const Float_ *query, Index_ k, std::vector< Index_ > *output_indices, std::vector< Float_ > *output_distances)
Definition knncolle_annoy.hpp:212