knncolle_hnsw
knncolle bindings for HNSW
Loading...
Searching...
No Matches
distances.hpp
Go to the documentation of this file.
1#ifndef KNNCOLLE_HNSW_DISTANCES_HPP
2#define KNNCOLLE_HNSW_DISTANCES_HPP
3
4#include <functional>
5#include <cstddef>
6#include <type_traits>
7
13namespace knncolle_hnsw {
14
22enum class DistanceNormalizeMethod : char { SQRT, CUSTOM, NONE };
23
30template<typename Distance_, typename HnswData_ = float>
35 std::function<hnswlib::SpaceInterface<HnswData_>*(std::size_t)> create;
36
41
46 std::function<Distance_(Distance_)> custom_normalize;
47};
48
54template<typename HnswData_ = float>
55class ManhattanDistance final : public hnswlib::SpaceInterface<HnswData_> {
56private:
57 std::size_t my_data_size;
58 std::size_t my_dim;
59
60public:
64 ManhattanDistance(std::size_t dim) : my_data_size(dim * sizeof(HnswData_)), my_dim(dim) {}
65
69public:
70 std::size_t get_data_size() {
71 return my_data_size;
72 }
73
74 hnswlib::DISTFUNC<HnswData_> get_dist_func() {
75 return L1;
76 }
77
78 void * get_dist_func_param() {
79 return &my_dim;
80 }
81
82private:
83 static HnswData_ L1(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
84 const HnswData_* pVect1 = static_cast<const HnswData_*>(pVect1v);
85 const HnswData_* pVect2 = static_cast<const HnswData_*>(pVect2v);
86 std::size_t qty = *((size_t *) qty_ptr);
87 HnswData_ res = 0;
88 for (; qty > 0; --qty, ++pVect1, ++pVect2) {
89 res += std::abs(*pVect1 - *pVect2);
90 }
91 return res;
92 }
96};
97
103template<typename HnswData_ = float>
104class SquaredEuclideanDistance final : public hnswlib::SpaceInterface<HnswData_> {
105private:
106 std::size_t my_data_size;
107 std::size_t my_dim;
108
109public:
113 SquaredEuclideanDistance(std::size_t dim) : my_data_size(dim * sizeof(HnswData_)), my_dim(dim) {}
114
118public:
119 std::size_t get_data_size() {
120 return my_data_size;
121 }
122
123 hnswlib::DISTFUNC<HnswData_> get_dist_func() {
124 return L2;
125 }
126
127 void * get_dist_func_param() {
128 return &my_dim;
129 }
130
131private:
132 static HnswData_ L2(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
133 const HnswData_* pVect1 = static_cast<const HnswData_*>(pVect1v);
134 const HnswData_* pVect2 = static_cast<const HnswData_*>(pVect2v);
135 std::size_t qty = *((size_t *) qty_ptr);
136 HnswData_ res = 0;
137 for (; qty > 0; --qty, ++pVect1, ++pVect2) {
138 auto delta = *pVect1 - *pVect2;
139 res += delta * delta;
140 }
141 return res;
142 }
146};
147
154template<typename Distance_, typename HnswData_ = float>
157 output.create = [](std::size_t dim) -> hnswlib::SpaceInterface<HnswData_>* {
158 if constexpr(std::is_same<HnswData_, float>::value) {
159 return static_cast<hnswlib::SpaceInterface<HnswData_>*>(new hnswlib::L2Space(dim));
160 } else {
161 return static_cast<hnswlib::SpaceInterface<HnswData_>*>(new SquaredEuclideanDistance<HnswData_>(dim));
162 }
163 };
164 output.normalize_method = DistanceNormalizeMethod::SQRT;
165 return output;
166}
167
173template<typename Distance_, typename HnswData_ = float>
176 output.create = [](std::size_t dim) -> hnswlib::SpaceInterface<HnswData_>* {
177 return static_cast<hnswlib::SpaceInterface<HnswData_>*>(new knncolle_hnsw::ManhattanDistance<HnswData_>(dim));
178 };
179 output.normalize_method = DistanceNormalizeMethod::NONE;
180 return output;
181}
182
186// Preserved for back-compatibility.
187template<typename HnswData_ = float, typename Distance_ = double>
188DistanceConfig<Distance_, HnswData_> makeEuclideanDistanceConfig() {
190}
191
192template<typename HnswData_ = float, typename Distance_ = double>
193DistanceConfig<Distance_, HnswData_> makeManhattanDistanceConfig() {
195}
211template<typename HnswData_>
212const char* get_distance_name(const hnswlib::SpaceInterface<HnswData_>* distance) {
213 if (dynamic_cast<const hnswlib::L2Space*>(distance) != NULL) {
214 return "l2";
215 } else if (dynamic_cast<const SquaredEuclideanDistance<HnswData_>*>(distance) != NULL) {
216 return "squared_euclidean";
217 } else if (dynamic_cast<const ManhattanDistance<HnswData_>*>(distance) != NULL) {
218 return "manhattan";
219 } else {
220 return "unknown";
221 }
222}
223
224}
225
226#endif
Manhattan distance.
Definition distances.hpp:55
ManhattanDistance(std::size_t dim)
Definition distances.hpp:64
Squared Euclidean distance.
Definition distances.hpp:104
SquaredEuclideanDistance(std::size_t dim)
Definition distances.hpp:113
knncolle bindings for HNSW search.
Definition distances.hpp:13
DistanceNormalizeMethod
Definition distances.hpp:22
DistanceConfig< Distance_, HnswData_ > configure_euclidean_distance()
Definition distances.hpp:155
const char * get_distance_name(const hnswlib::SpaceInterface< HnswData_ > *distance)
Definition distances.hpp:212
DistanceConfig< Distance_, HnswData_ > configure_manhattan_distance()
Definition distances.hpp:174
Distance configuration for the HNSW index.
Definition distances.hpp:31
DistanceNormalizeMethod normalize_method
Definition distances.hpp:40
std::function< hnswlib::SpaceInterface< HnswData_ > *(std::size_t)> create
Definition distances.hpp:35
std::function< Distance_(Distance_)> custom_normalize
Definition distances.hpp:46