66#include " VecSim/memory/vecsim_malloc.h"
77#include " VecSim/utils/vecsim_stl.h"
88#include " VecSim/utils/vec_utils.h"
9+ #include " VecSim/utils/vecsim_results_container.h"
910#include " VecSim/query_result_struct.h"
1011#include " VecSim/vec_sim_common.h"
1112#include " VecSim/vec_sim_index.h"
@@ -119,11 +120,10 @@ class HNSWIndex : public VecSimIndexAbstract<DistType> {
119120 tag_t visited_tag,
120121 vecsim_stl::abstract_priority_queue<DistType, Identifier> &top_candidates,
121122 candidatesMaxHeap<DistType> &candidates_set, DistType lowerBound) const ;
122- inline void processCandidate_RangeSearch (idType curNodeId, const void *data_point, size_t layer,
123- double epsilon, tag_t visited_tag,
124- VecSimQueryResult **top_candidates,
125- candidatesMaxHeap<DistType> &candidate_set,
126- DistType lowerBound, double radius) const ;
123+ inline void processCandidate_RangeSearch (
124+ idType curNodeId, const void *data_point, size_t layer, double epsilon, tag_t visited_tag,
125+ std::unique_ptr<vecsim_stl::abstract_results_container> &top_candidates,
126+ candidatesMaxHeap<DistType> &candidate_set, DistType lowerBound, double radius) const ;
127127 candidatesMaxHeap<DistType> searchLayer (idType ep_id, const void *data_point, size_t layer,
128128 size_t ef) const ;
129129 candidatesLabelsMaxHeap<DistType> *
@@ -192,6 +192,8 @@ class HNSWIndex : public VecSimIndexAbstract<DistType> {
192192
193193protected:
194194 // inline label to id setters that need to be implemented by derived class
195+ virtual inline std::unique_ptr<vecsim_stl::abstract_results_container>
196+ getNewResultsContainer (size_t cap) const = 0 ;
195197 virtual inline void replaceIdOfLabel (labelType label, idType new_id, idType old_id) = 0;
196198 virtual inline void setVectorId (labelType label, idType id) = 0;
197199 virtual inline void resizeLabelLookup (size_t new_max_elements) = 0;
@@ -453,8 +455,8 @@ DistType HNSWIndex<DataType, DistType>::processCandidate(
453455template <typename DataType, typename DistType>
454456void HNSWIndex<DataType, DistType>::processCandidate_RangeSearch(
455457 idType curNodeId, const void *query_data, size_t layer, double epsilon, tag_t visited_tag,
456- VecSimQueryResult **results, candidatesMaxHeap<DistType > &candidate_set, DistType dyn_range ,
457- double radius) const {
458+ std::unique_ptr<vecsim_stl::abstract_results_container > &results ,
459+ candidatesMaxHeap<DistType> &candidate_set, DistType dyn_range, double radius) const {
458460
459461#ifdef ENABLE_PARALLELIZATION
460462 std::unique_lock<std::mutex> lock (link_list_locks_[curNodeId]);
@@ -488,10 +490,7 @@ void HNSWIndex<DataType, DistType>::processCandidate_RangeSearch(
488490
489491 // If the new candidate is in the requested radius, add it to the results set.
490492 if (candidate_dist <= radius_) {
491- auto new_result = VecSimQueryResult{};
492- VecSimQueryResult_SetId (new_result, getExternalLabel (candidate_id));
493- VecSimQueryResult_SetScore (new_result, candidate_dist);
494- *results = array_append (*results, new_result);
493+ results->emplace (getExternalLabel (candidate_id), candidate_dist);
495494 }
496495 }
497496 }
@@ -1415,7 +1414,8 @@ VecSimQueryResult *HNSWIndex<DataType, DistType>::searchRangeBottomLayer_WithTim
14151414 idType ep_id, const void *data_point, double epsilon, double radius, void *timeoutCtx,
14161415 VecSimQueryResult_Code *rc) const {
14171416
1418- auto *results = array_new<VecSimQueryResult>(10 ); // arbitrary initial cap.
1417+ *rc = VecSim_QueryResult_OK;
1418+ auto res_container = getNewResultsContainer (10 ); // arbitrary initial cap.
14191419
14201420#ifdef ENABLE_PARALLELIZATION
14211421 this ->visited_nodes_handler =
@@ -1431,10 +1431,7 @@ VecSimQueryResult *HNSWIndex<DataType, DistType>::searchRangeBottomLayer_WithTim
14311431
14321432 if (ep_dist <= radius) {
14331433 // Entry-point is within the radius - add it to the results.
1434- auto new_result = VecSimQueryResult{};
1435- VecSimQueryResult_SetId (new_result, getExternalLabel (ep_id));
1436- VecSimQueryResult_SetScore (new_result, ep_dist);
1437- results = array_append (results, new_result);
1434+ res_container->emplace (getExternalLabel (ep_id), ep_dist);
14381435 dynamic_range = radius; // to ensure that dyn_range >= radius.
14391436 }
14401437
@@ -1453,7 +1450,7 @@ VecSimQueryResult *HNSWIndex<DataType, DistType>::searchRangeBottomLayer_WithTim
14531450 }
14541451 if (__builtin_expect (VecSimIndexAbstract<DistType>::timeoutCallback (timeoutCtx), 0 )) {
14551452 *rc = VecSim_QueryResult_TimedOut;
1456- return results ;
1453+ break ;
14571454 }
14581455 candidate_set.pop ();
14591456
@@ -1468,15 +1465,14 @@ VecSimQueryResult *HNSWIndex<DataType, DistType>::searchRangeBottomLayer_WithTim
14681465 // requested radius.
14691466 // Here we send the radius as double to match the function arguments type.
14701467 processCandidate_RangeSearch (curr_el_pair.second , data_point, 0 , epsilon, visited_tag,
1471- &results , candidate_set, dynamic_range_search_boundaries,
1468+ res_container , candidate_set, dynamic_range_search_boundaries,
14721469 radius);
14731470 }
1471+
14741472#ifdef ENABLE_PARALLELIZATION
14751473 visited_nodes_handler_pool->returnVisitedNodesHandlerToPool (this ->visited_nodes_handler );
14761474#endif
1477-
1478- *rc = VecSim_QueryResult_OK;
1479- return results;
1475+ return res_container->get_results ();
14801476}
14811477
14821478template <typename DataType, typename DistType>
0 commit comments