hnswlib 0.6.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,329 +3,324 @@
3
3
 
4
4
  namespace hnswlib {
5
5
 
6
- static float
7
- L2Sqr(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
8
- float *pVect1 = (float *) pVect1v;
9
- float *pVect2 = (float *) pVect2v;
10
- size_t qty = *((size_t *) qty_ptr);
11
-
12
- float res = 0;
13
- for (size_t i = 0; i < qty; i++) {
14
- float t = *pVect1 - *pVect2;
15
- pVect1++;
16
- pVect2++;
17
- res += t * t;
18
- }
19
- return (res);
6
+ static float
7
+ L2Sqr(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
8
+ float *pVect1 = (float *) pVect1v;
9
+ float *pVect2 = (float *) pVect2v;
10
+ size_t qty = *((size_t *) qty_ptr);
11
+
12
+ float res = 0;
13
+ for (size_t i = 0; i < qty; i++) {
14
+ float t = *pVect1 - *pVect2;
15
+ pVect1++;
16
+ pVect2++;
17
+ res += t * t;
20
18
  }
19
+ return (res);
20
+ }
21
21
 
22
22
  #if defined(USE_AVX512)
23
23
 
24
- // Favor using AVX512 if available.
25
- static float
26
- L2SqrSIMD16ExtAVX512(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
27
- float *pVect1 = (float *) pVect1v;
28
- float *pVect2 = (float *) pVect2v;
29
- size_t qty = *((size_t *) qty_ptr);
30
- float PORTABLE_ALIGN64 TmpRes[16];
31
- size_t qty16 = qty >> 4;
32
-
33
- const float *pEnd1 = pVect1 + (qty16 << 4);
34
-
35
- __m512 diff, v1, v2;
36
- __m512 sum = _mm512_set1_ps(0);
37
-
38
- while (pVect1 < pEnd1) {
39
- v1 = _mm512_loadu_ps(pVect1);
40
- pVect1 += 16;
41
- v2 = _mm512_loadu_ps(pVect2);
42
- pVect2 += 16;
43
- diff = _mm512_sub_ps(v1, v2);
44
- // sum = _mm512_fmadd_ps(diff, diff, sum);
45
- sum = _mm512_add_ps(sum, _mm512_mul_ps(diff, diff));
46
- }
24
+ // Favor using AVX512 if available.
25
+ static float
26
+ L2SqrSIMD16ExtAVX512(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
27
+ float *pVect1 = (float *) pVect1v;
28
+ float *pVect2 = (float *) pVect2v;
29
+ size_t qty = *((size_t *) qty_ptr);
30
+ float PORTABLE_ALIGN64 TmpRes[16];
31
+ size_t qty16 = qty >> 4;
32
+
33
+ const float *pEnd1 = pVect1 + (qty16 << 4);
34
+
35
+ __m512 diff, v1, v2;
36
+ __m512 sum = _mm512_set1_ps(0);
37
+
38
+ while (pVect1 < pEnd1) {
39
+ v1 = _mm512_loadu_ps(pVect1);
40
+ pVect1 += 16;
41
+ v2 = _mm512_loadu_ps(pVect2);
42
+ pVect2 += 16;
43
+ diff = _mm512_sub_ps(v1, v2);
44
+ // sum = _mm512_fmadd_ps(diff, diff, sum);
45
+ sum = _mm512_add_ps(sum, _mm512_mul_ps(diff, diff));
46
+ }
47
47
 
48
- _mm512_store_ps(TmpRes, sum);
49
- float res = TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3] + TmpRes[4] + TmpRes[5] + TmpRes[6] +
50
- TmpRes[7] + TmpRes[8] + TmpRes[9] + TmpRes[10] + TmpRes[11] + TmpRes[12] +
51
- TmpRes[13] + TmpRes[14] + TmpRes[15];
48
+ _mm512_store_ps(TmpRes, sum);
49
+ float res = TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3] + TmpRes[4] + TmpRes[5] + TmpRes[6] +
50
+ TmpRes[7] + TmpRes[8] + TmpRes[9] + TmpRes[10] + TmpRes[11] + TmpRes[12] +
51
+ TmpRes[13] + TmpRes[14] + TmpRes[15];
52
52
 
53
- return (res);
53
+ return (res);
54
54
  }
55
55
  #endif
56
56
 
57
57
  #if defined(USE_AVX)
58
58
 
59
- // Favor using AVX if available.
60
- static float
61
- L2SqrSIMD16ExtAVX(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
62
- float *pVect1 = (float *) pVect1v;
63
- float *pVect2 = (float *) pVect2v;
64
- size_t qty = *((size_t *) qty_ptr);
65
- float PORTABLE_ALIGN32 TmpRes[8];
66
- size_t qty16 = qty >> 4;
67
-
68
- const float *pEnd1 = pVect1 + (qty16 << 4);
69
-
70
- __m256 diff, v1, v2;
71
- __m256 sum = _mm256_set1_ps(0);
72
-
73
- while (pVect1 < pEnd1) {
74
- v1 = _mm256_loadu_ps(pVect1);
75
- pVect1 += 8;
76
- v2 = _mm256_loadu_ps(pVect2);
77
- pVect2 += 8;
78
- diff = _mm256_sub_ps(v1, v2);
79
- sum = _mm256_add_ps(sum, _mm256_mul_ps(diff, diff));
80
-
81
- v1 = _mm256_loadu_ps(pVect1);
82
- pVect1 += 8;
83
- v2 = _mm256_loadu_ps(pVect2);
84
- pVect2 += 8;
85
- diff = _mm256_sub_ps(v1, v2);
86
- sum = _mm256_add_ps(sum, _mm256_mul_ps(diff, diff));
87
- }
88
-
89
- _mm256_store_ps(TmpRes, sum);
90
- return TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3] + TmpRes[4] + TmpRes[5] + TmpRes[6] + TmpRes[7];
59
+ // Favor using AVX if available.
60
+ static float
61
+ L2SqrSIMD16ExtAVX(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
62
+ float *pVect1 = (float *) pVect1v;
63
+ float *pVect2 = (float *) pVect2v;
64
+ size_t qty = *((size_t *) qty_ptr);
65
+ float PORTABLE_ALIGN32 TmpRes[8];
66
+ size_t qty16 = qty >> 4;
67
+
68
+ const float *pEnd1 = pVect1 + (qty16 << 4);
69
+
70
+ __m256 diff, v1, v2;
71
+ __m256 sum = _mm256_set1_ps(0);
72
+
73
+ while (pVect1 < pEnd1) {
74
+ v1 = _mm256_loadu_ps(pVect1);
75
+ pVect1 += 8;
76
+ v2 = _mm256_loadu_ps(pVect2);
77
+ pVect2 += 8;
78
+ diff = _mm256_sub_ps(v1, v2);
79
+ sum = _mm256_add_ps(sum, _mm256_mul_ps(diff, diff));
80
+
81
+ v1 = _mm256_loadu_ps(pVect1);
82
+ pVect1 += 8;
83
+ v2 = _mm256_loadu_ps(pVect2);
84
+ pVect2 += 8;
85
+ diff = _mm256_sub_ps(v1, v2);
86
+ sum = _mm256_add_ps(sum, _mm256_mul_ps(diff, diff));
91
87
  }
92
88
 
89
+ _mm256_store_ps(TmpRes, sum);
90
+ return TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3] + TmpRes[4] + TmpRes[5] + TmpRes[6] + TmpRes[7];
91
+ }
92
+
93
93
  #endif
94
94
 
95
95
  #if defined(USE_SSE)
96
96
 
97
- static float
98
- L2SqrSIMD16ExtSSE(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
99
- float *pVect1 = (float *) pVect1v;
100
- float *pVect2 = (float *) pVect2v;
101
- size_t qty = *((size_t *) qty_ptr);
102
- float PORTABLE_ALIGN32 TmpRes[8];
103
- size_t qty16 = qty >> 4;
104
-
105
- const float *pEnd1 = pVect1 + (qty16 << 4);
106
-
107
- __m128 diff, v1, v2;
108
- __m128 sum = _mm_set1_ps(0);
109
-
110
- while (pVect1 < pEnd1) {
111
- //_mm_prefetch((char*)(pVect2 + 16), _MM_HINT_T0);
112
- v1 = _mm_loadu_ps(pVect1);
113
- pVect1 += 4;
114
- v2 = _mm_loadu_ps(pVect2);
115
- pVect2 += 4;
116
- diff = _mm_sub_ps(v1, v2);
117
- sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
118
-
119
- v1 = _mm_loadu_ps(pVect1);
120
- pVect1 += 4;
121
- v2 = _mm_loadu_ps(pVect2);
122
- pVect2 += 4;
123
- diff = _mm_sub_ps(v1, v2);
124
- sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
125
-
126
- v1 = _mm_loadu_ps(pVect1);
127
- pVect1 += 4;
128
- v2 = _mm_loadu_ps(pVect2);
129
- pVect2 += 4;
130
- diff = _mm_sub_ps(v1, v2);
131
- sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
132
-
133
- v1 = _mm_loadu_ps(pVect1);
134
- pVect1 += 4;
135
- v2 = _mm_loadu_ps(pVect2);
136
- pVect2 += 4;
137
- diff = _mm_sub_ps(v1, v2);
138
- sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
139
- }
140
-
141
- _mm_store_ps(TmpRes, sum);
142
- return TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3];
97
+ static float
98
+ L2SqrSIMD16ExtSSE(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
99
+ float *pVect1 = (float *) pVect1v;
100
+ float *pVect2 = (float *) pVect2v;
101
+ size_t qty = *((size_t *) qty_ptr);
102
+ float PORTABLE_ALIGN32 TmpRes[8];
103
+ size_t qty16 = qty >> 4;
104
+
105
+ const float *pEnd1 = pVect1 + (qty16 << 4);
106
+
107
+ __m128 diff, v1, v2;
108
+ __m128 sum = _mm_set1_ps(0);
109
+
110
+ while (pVect1 < pEnd1) {
111
+ //_mm_prefetch((char*)(pVect2 + 16), _MM_HINT_T0);
112
+ v1 = _mm_loadu_ps(pVect1);
113
+ pVect1 += 4;
114
+ v2 = _mm_loadu_ps(pVect2);
115
+ pVect2 += 4;
116
+ diff = _mm_sub_ps(v1, v2);
117
+ sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
118
+
119
+ v1 = _mm_loadu_ps(pVect1);
120
+ pVect1 += 4;
121
+ v2 = _mm_loadu_ps(pVect2);
122
+ pVect2 += 4;
123
+ diff = _mm_sub_ps(v1, v2);
124
+ sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
125
+
126
+ v1 = _mm_loadu_ps(pVect1);
127
+ pVect1 += 4;
128
+ v2 = _mm_loadu_ps(pVect2);
129
+ pVect2 += 4;
130
+ diff = _mm_sub_ps(v1, v2);
131
+ sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
132
+
133
+ v1 = _mm_loadu_ps(pVect1);
134
+ pVect1 += 4;
135
+ v2 = _mm_loadu_ps(pVect2);
136
+ pVect2 += 4;
137
+ diff = _mm_sub_ps(v1, v2);
138
+ sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
143
139
  }
140
+
141
+ _mm_store_ps(TmpRes, sum);
142
+ return TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3];
143
+ }
144
144
  #endif
145
145
 
146
146
  #if defined(USE_SSE) || defined(USE_AVX) || defined(USE_AVX512)
147
- DISTFUNC<float> L2SqrSIMD16Ext = L2SqrSIMD16ExtSSE;
148
-
149
- static float
150
- L2SqrSIMD16ExtResiduals(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
151
- size_t qty = *((size_t *) qty_ptr);
152
- size_t qty16 = qty >> 4 << 4;
153
- float res = L2SqrSIMD16Ext(pVect1v, pVect2v, &qty16);
154
- float *pVect1 = (float *) pVect1v + qty16;
155
- float *pVect2 = (float *) pVect2v + qty16;
156
-
157
- size_t qty_left = qty - qty16;
158
- float res_tail = L2Sqr(pVect1, pVect2, &qty_left);
159
- return (res + res_tail);
160
- }
147
+ static DISTFUNC<float> L2SqrSIMD16Ext = L2SqrSIMD16ExtSSE;
148
+
149
+ static float
150
+ L2SqrSIMD16ExtResiduals(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
151
+ size_t qty = *((size_t *) qty_ptr);
152
+ size_t qty16 = qty >> 4 << 4;
153
+ float res = L2SqrSIMD16Ext(pVect1v, pVect2v, &qty16);
154
+ float *pVect1 = (float *) pVect1v + qty16;
155
+ float *pVect2 = (float *) pVect2v + qty16;
156
+
157
+ size_t qty_left = qty - qty16;
158
+ float res_tail = L2Sqr(pVect1, pVect2, &qty_left);
159
+ return (res + res_tail);
160
+ }
161
161
  #endif
162
162
 
163
163
 
164
164
  #if defined(USE_SSE)
165
- static float
166
- L2SqrSIMD4Ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
167
- float PORTABLE_ALIGN32 TmpRes[8];
168
- float *pVect1 = (float *) pVect1v;
169
- float *pVect2 = (float *) pVect2v;
170
- size_t qty = *((size_t *) qty_ptr);
165
+ static float
166
+ L2SqrSIMD4Ext(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
167
+ float PORTABLE_ALIGN32 TmpRes[8];
168
+ float *pVect1 = (float *) pVect1v;
169
+ float *pVect2 = (float *) pVect2v;
170
+ size_t qty = *((size_t *) qty_ptr);
171
171
 
172
172
 
173
- size_t qty4 = qty >> 2;
173
+ size_t qty4 = qty >> 2;
174
174
 
175
- const float *pEnd1 = pVect1 + (qty4 << 2);
175
+ const float *pEnd1 = pVect1 + (qty4 << 2);
176
176
 
177
- __m128 diff, v1, v2;
178
- __m128 sum = _mm_set1_ps(0);
177
+ __m128 diff, v1, v2;
178
+ __m128 sum = _mm_set1_ps(0);
179
179
 
180
- while (pVect1 < pEnd1) {
181
- v1 = _mm_loadu_ps(pVect1);
182
- pVect1 += 4;
183
- v2 = _mm_loadu_ps(pVect2);
184
- pVect2 += 4;
185
- diff = _mm_sub_ps(v1, v2);
186
- sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
187
- }
188
- _mm_store_ps(TmpRes, sum);
189
- return TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3];
180
+ while (pVect1 < pEnd1) {
181
+ v1 = _mm_loadu_ps(pVect1);
182
+ pVect1 += 4;
183
+ v2 = _mm_loadu_ps(pVect2);
184
+ pVect2 += 4;
185
+ diff = _mm_sub_ps(v1, v2);
186
+ sum = _mm_add_ps(sum, _mm_mul_ps(diff, diff));
190
187
  }
188
+ _mm_store_ps(TmpRes, sum);
189
+ return TmpRes[0] + TmpRes[1] + TmpRes[2] + TmpRes[3];
190
+ }
191
191
 
192
- static float
193
- L2SqrSIMD4ExtResiduals(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
194
- size_t qty = *((size_t *) qty_ptr);
195
- size_t qty4 = qty >> 2 << 2;
192
+ static float
193
+ L2SqrSIMD4ExtResiduals(const void *pVect1v, const void *pVect2v, const void *qty_ptr) {
194
+ size_t qty = *((size_t *) qty_ptr);
195
+ size_t qty4 = qty >> 2 << 2;
196
196
 
197
- float res = L2SqrSIMD4Ext(pVect1v, pVect2v, &qty4);
198
- size_t qty_left = qty - qty4;
197
+ float res = L2SqrSIMD4Ext(pVect1v, pVect2v, &qty4);
198
+ size_t qty_left = qty - qty4;
199
199
 
200
- float *pVect1 = (float *) pVect1v + qty4;
201
- float *pVect2 = (float *) pVect2v + qty4;
202
- float res_tail = L2Sqr(pVect1, pVect2, &qty_left);
200
+ float *pVect1 = (float *) pVect1v + qty4;
201
+ float *pVect2 = (float *) pVect2v + qty4;
202
+ float res_tail = L2Sqr(pVect1, pVect2, &qty_left);
203
203
 
204
- return (res + res_tail);
205
- }
204
+ return (res + res_tail);
205
+ }
206
206
  #endif
207
207
 
208
- class L2Space : public SpaceInterface<float> {
209
-
210
- DISTFUNC<float> fstdistfunc_;
211
- size_t data_size_;
212
- size_t dim_;
213
- public:
214
- L2Space() : data_size_(0), dim_(0) { }
215
- L2Space(size_t dim) {
216
- fstdistfunc_ = L2Sqr;
217
- #if defined(USE_SSE) || defined(USE_AVX) || defined(USE_AVX512)
218
- #if defined(USE_AVX512)
219
- if (AVX512Capable())
220
- L2SqrSIMD16Ext = L2SqrSIMD16ExtAVX512;
221
- else if (AVXCapable())
222
- L2SqrSIMD16Ext = L2SqrSIMD16ExtAVX;
223
- #elif defined(USE_AVX)
224
- if (AVXCapable())
225
- L2SqrSIMD16Ext = L2SqrSIMD16ExtAVX;
226
- #endif
227
-
228
- if (dim % 16 == 0)
229
- fstdistfunc_ = L2SqrSIMD16Ext;
230
- else if (dim % 4 == 0)
231
- fstdistfunc_ = L2SqrSIMD4Ext;
232
- else if (dim > 16)
233
- fstdistfunc_ = L2SqrSIMD16ExtResiduals;
234
- else if (dim > 4)
235
- fstdistfunc_ = L2SqrSIMD4ExtResiduals;
208
+ class L2Space : public SpaceInterface<float> {
209
+ DISTFUNC<float> fstdistfunc_;
210
+ size_t data_size_;
211
+ size_t dim_;
212
+
213
+ public:
214
+ L2Space() : data_size_(0), dim_(0) { }
215
+
216
+ L2Space(size_t dim) {
217
+ fstdistfunc_ = L2Sqr;
218
+ #if defined(USE_SSE) || defined(USE_AVX) || defined(USE_AVX512)
219
+ #if defined(USE_AVX512)
220
+ if (AVX512Capable())
221
+ L2SqrSIMD16Ext = L2SqrSIMD16ExtAVX512;
222
+ else if (AVXCapable())
223
+ L2SqrSIMD16Ext = L2SqrSIMD16ExtAVX;
224
+ #elif defined(USE_AVX)
225
+ if (AVXCapable())
226
+ L2SqrSIMD16Ext = L2SqrSIMD16ExtAVX;
236
227
  #endif
237
- dim_ = dim;
238
- data_size_ = dim * sizeof(float);
239
- }
240
228
 
241
- size_t get_data_size() {
242
- return data_size_;
243
- }
229
+ if (dim % 16 == 0)
230
+ fstdistfunc_ = L2SqrSIMD16Ext;
231
+ else if (dim % 4 == 0)
232
+ fstdistfunc_ = L2SqrSIMD4Ext;
233
+ else if (dim > 16)
234
+ fstdistfunc_ = L2SqrSIMD16ExtResiduals;
235
+ else if (dim > 4)
236
+ fstdistfunc_ = L2SqrSIMD4ExtResiduals;
237
+ #endif
238
+ dim_ = dim;
239
+ data_size_ = dim * sizeof(float);
240
+ }
244
241
 
245
- DISTFUNC<float> get_dist_func() {
246
- return fstdistfunc_;
247
- }
242
+ size_t get_data_size() {
243
+ return data_size_;
244
+ }
248
245
 
249
- void *get_dist_func_param() {
250
- return &dim_;
251
- }
246
+ DISTFUNC<float> get_dist_func() {
247
+ return fstdistfunc_;
248
+ }
252
249
 
253
- ~L2Space() {}
254
- };
255
-
256
- static int
257
- L2SqrI4x(const void *__restrict pVect1, const void *__restrict pVect2, const void *__restrict qty_ptr) {
258
-
259
- size_t qty = *((size_t *) qty_ptr);
260
- int res = 0;
261
- unsigned char *a = (unsigned char *) pVect1;
262
- unsigned char *b = (unsigned char *) pVect2;
263
-
264
- qty = qty >> 2;
265
- for (size_t i = 0; i < qty; i++) {
266
-
267
- res += ((*a) - (*b)) * ((*a) - (*b));
268
- a++;
269
- b++;
270
- res += ((*a) - (*b)) * ((*a) - (*b));
271
- a++;
272
- b++;
273
- res += ((*a) - (*b)) * ((*a) - (*b));
274
- a++;
275
- b++;
276
- res += ((*a) - (*b)) * ((*a) - (*b));
277
- a++;
278
- b++;
279
- }
280
- return (res);
250
+ void *get_dist_func_param() {
251
+ return &dim_;
281
252
  }
282
253
 
283
- static int L2SqrI(const void* __restrict pVect1, const void* __restrict pVect2, const void* __restrict qty_ptr) {
284
- size_t qty = *((size_t*)qty_ptr);
285
- int res = 0;
286
- unsigned char* a = (unsigned char*)pVect1;
287
- unsigned char* b = (unsigned char*)pVect2;
288
-
289
- for(size_t i = 0; i < qty; i++)
290
- {
291
- res += ((*a) - (*b)) * ((*a) - (*b));
292
- a++;
293
- b++;
294
- }
295
- return (res);
254
+ ~L2Space() {}
255
+ };
256
+
257
+ static int
258
+ L2SqrI4x(const void *__restrict pVect1, const void *__restrict pVect2, const void *__restrict qty_ptr) {
259
+ size_t qty = *((size_t *) qty_ptr);
260
+ int res = 0;
261
+ unsigned char *a = (unsigned char *) pVect1;
262
+ unsigned char *b = (unsigned char *) pVect2;
263
+
264
+ qty = qty >> 2;
265
+ for (size_t i = 0; i < qty; i++) {
266
+ res += ((*a) - (*b)) * ((*a) - (*b));
267
+ a++;
268
+ b++;
269
+ res += ((*a) - (*b)) * ((*a) - (*b));
270
+ a++;
271
+ b++;
272
+ res += ((*a) - (*b)) * ((*a) - (*b));
273
+ a++;
274
+ b++;
275
+ res += ((*a) - (*b)) * ((*a) - (*b));
276
+ a++;
277
+ b++;
296
278
  }
279
+ return (res);
280
+ }
297
281
 
298
- class L2SpaceI : public SpaceInterface<int> {
299
-
300
- DISTFUNC<int> fstdistfunc_;
301
- size_t data_size_;
302
- size_t dim_;
303
- public:
304
- L2SpaceI(size_t dim) {
305
- if(dim % 4 == 0) {
306
- fstdistfunc_ = L2SqrI4x;
307
- }
308
- else {
309
- fstdistfunc_ = L2SqrI;
310
- }
311
- dim_ = dim;
312
- data_size_ = dim * sizeof(unsigned char);
313
- }
282
+ static int L2SqrI(const void* __restrict pVect1, const void* __restrict pVect2, const void* __restrict qty_ptr) {
283
+ size_t qty = *((size_t*)qty_ptr);
284
+ int res = 0;
285
+ unsigned char* a = (unsigned char*)pVect1;
286
+ unsigned char* b = (unsigned char*)pVect2;
314
287
 
315
- size_t get_data_size() {
316
- return data_size_;
317
- }
288
+ for (size_t i = 0; i < qty; i++) {
289
+ res += ((*a) - (*b)) * ((*a) - (*b));
290
+ a++;
291
+ b++;
292
+ }
293
+ return (res);
294
+ }
318
295
 
319
- DISTFUNC<int> get_dist_func() {
320
- return fstdistfunc_;
296
+ class L2SpaceI : public SpaceInterface<int> {
297
+ DISTFUNC<int> fstdistfunc_;
298
+ size_t data_size_;
299
+ size_t dim_;
300
+
301
+ public:
302
+ L2SpaceI(size_t dim) {
303
+ if (dim % 4 == 0) {
304
+ fstdistfunc_ = L2SqrI4x;
305
+ } else {
306
+ fstdistfunc_ = L2SqrI;
321
307
  }
308
+ dim_ = dim;
309
+ data_size_ = dim * sizeof(unsigned char);
310
+ }
322
311
 
323
- void *get_dist_func_param() {
324
- return &dim_;
325
- }
312
+ size_t get_data_size() {
313
+ return data_size_;
314
+ }
326
315
 
327
- ~L2SpaceI() {}
328
- };
316
+ DISTFUNC<int> get_dist_func() {
317
+ return fstdistfunc_;
318
+ }
329
319
 
320
+ void *get_dist_func_param() {
321
+ return &dim_;
322
+ }
330
323
 
331
- }
324
+ ~L2SpaceI() {}
325
+ };
326
+ } // namespace hnswlib