usearch 2.14.0 → 2.15.1
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.
- package/README.md +1 -1
- package/cpp/bench.cpp +4 -0
- package/include/usearch/index.hpp +2 -2
- package/include/usearch/index_dense.hpp +1 -1
- package/include/usearch/index_plugins.hpp +96 -48
- package/javascript/README.md +2 -1
- package/javascript/usearch.test.js +2 -2
- package/package.json +1 -1
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
package/README.md
CHANGED
package/cpp/bench.cpp
CHANGED
|
@@ -468,6 +468,7 @@ struct args_t {
|
|
|
468
468
|
|
|
469
469
|
bool big = false;
|
|
470
470
|
|
|
471
|
+
bool quantize_bf16 = false;
|
|
471
472
|
bool quantize_f16 = false;
|
|
472
473
|
bool quantize_i8 = false;
|
|
473
474
|
bool quantize_b1 = false;
|
|
@@ -500,6 +501,8 @@ struct args_t {
|
|
|
500
501
|
}
|
|
501
502
|
|
|
502
503
|
scalar_kind_t quantization() const noexcept {
|
|
504
|
+
if (quantize_bf16)
|
|
505
|
+
return scalar_kind_t::bf16_k;
|
|
503
506
|
if (quantize_f16)
|
|
504
507
|
return scalar_kind_t::f16_k;
|
|
505
508
|
if (quantize_i8)
|
|
@@ -611,6 +614,7 @@ int main(int argc, char** argv) {
|
|
|
611
614
|
(option("--rows-skip") & value("integer", args.vectors_to_skip)).doc("Number of vectors to skip"),
|
|
612
615
|
(option("--rows-take") & value("integer", args.vectors_to_take)).doc("Number of vectors to take"),
|
|
613
616
|
( //
|
|
617
|
+
option("-bf16", "--bf16quant").set(args.quantize_bf16).doc("Enable `bf16_t` quantization") |
|
|
614
618
|
option("-f16", "--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
|
|
615
619
|
option("-i8", "--i8quant").set(args.quantize_i8).doc("Enable `i8_t` quantization") |
|
|
616
620
|
option("-b1", "--b1quant").set(args.quantize_b1).doc("Enable `b1x8_t` quantization")),
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
#define UNUM_USEARCH_HPP
|
|
9
9
|
|
|
10
10
|
#define USEARCH_VERSION_MAJOR 2
|
|
11
|
-
#define USEARCH_VERSION_MINOR
|
|
12
|
-
#define USEARCH_VERSION_PATCH
|
|
11
|
+
#define USEARCH_VERSION_MINOR 15
|
|
12
|
+
#define USEARCH_VERSION_PATCH 1
|
|
13
13
|
|
|
14
14
|
// Inferring C++ version
|
|
15
15
|
// https://stackoverflow.com/a/61552074
|
|
@@ -72,25 +72,8 @@ struct uuid_t {
|
|
|
72
72
|
class f16_bits_t;
|
|
73
73
|
class bf16_bits_t;
|
|
74
74
|
|
|
75
|
-
#if !USEARCH_USE_FP16LIB
|
|
76
|
-
#if USEARCH_USE_SIMSIMD
|
|
77
|
-
using f16_native_t = simsimd_f16_t;
|
|
78
|
-
using bf16_native_t = simsimd_bf16_t;
|
|
79
|
-
#elif defined(USEARCH_DEFINED_ARM)
|
|
80
|
-
using f16_native_t = __fp16;
|
|
81
|
-
using bf16_native_t = __fp16; // No better choice on most compilers!
|
|
82
|
-
#else
|
|
83
|
-
using f16_native_t = _Float16;
|
|
84
|
-
using bf16_native_t = _Float16; // No better choice on most compilers!
|
|
85
|
-
#endif
|
|
86
|
-
using f16_t = f16_native_t;
|
|
87
|
-
using bf16_t = bf16_native_t;
|
|
88
|
-
#else
|
|
89
|
-
using f16_native_t = void;
|
|
90
|
-
using bf16_native_t = void;
|
|
91
75
|
using f16_t = f16_bits_t;
|
|
92
76
|
using bf16_t = bf16_bits_t;
|
|
93
|
-
#endif
|
|
94
77
|
|
|
95
78
|
using f64_t = double;
|
|
96
79
|
using f32_t = float;
|
|
@@ -156,12 +139,9 @@ enum class scalar_kind_t : std::uint8_t {
|
|
|
156
139
|
i8_k = 23,
|
|
157
140
|
};
|
|
158
141
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
io_uring_k,
|
|
163
|
-
};
|
|
164
|
-
|
|
142
|
+
/**
|
|
143
|
+
* @brief Maps a scalar type to its corresponding scalar_kind_t enumeration value.
|
|
144
|
+
*/
|
|
165
145
|
template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
|
|
166
146
|
if (std::is_same<scalar_at, b1x8_t>())
|
|
167
147
|
return scalar_kind_t::b1x8_k;
|
|
@@ -198,22 +178,43 @@ template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
|
|
|
198
178
|
return scalar_kind_t::unknown_k;
|
|
199
179
|
}
|
|
200
180
|
|
|
181
|
+
/**
|
|
182
|
+
* @brief Converts an angle from degrees to radians.
|
|
183
|
+
*/
|
|
201
184
|
template <typename at> at angle_to_radians(at angle) noexcept { return angle * at(3.14159265358979323846) / at(180); }
|
|
202
185
|
|
|
186
|
+
/**
|
|
187
|
+
* @brief Readability helper to compute the square of a given value.
|
|
188
|
+
*/
|
|
203
189
|
template <typename at> at square(at value) noexcept { return value * value; }
|
|
204
190
|
|
|
191
|
+
/**
|
|
192
|
+
* @brief Clamps a value between a lower and upper bound using a custom comparator. Similar to `std::clamp`.
|
|
193
|
+
* https://en.cppreference.com/w/cpp/algorithm/clamp
|
|
194
|
+
*/
|
|
205
195
|
template <typename at, typename compare_at> inline at clamp(at v, at lo, at hi, compare_at comp) noexcept {
|
|
206
196
|
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
|
|
207
197
|
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @brief Clamps a value between a lower and upper bound. Similar to `std::clamp`.
|
|
201
|
+
* https://en.cppreference.com/w/cpp/algorithm/clamp
|
|
202
|
+
*/
|
|
208
203
|
template <typename at> inline at clamp(at v, at lo, at hi) noexcept {
|
|
209
204
|
return usearch::clamp(v, lo, hi, std::less<at>{});
|
|
210
205
|
}
|
|
211
206
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
207
|
+
/**
|
|
208
|
+
* @brief Compares two strings for equality, given a length for the first string.
|
|
209
|
+
*/
|
|
210
|
+
inline bool str_equals(char const* first_begin, std::size_t first_len, char const* second_begin) noexcept {
|
|
211
|
+
std::size_t second_len = std::strlen(second_begin);
|
|
212
|
+
return first_len == second_len && std::strncmp(first_begin, second_begin, first_len) == 0;
|
|
215
213
|
}
|
|
216
214
|
|
|
215
|
+
/**
|
|
216
|
+
* @brief Returns the number of bits required to represent a scalar type.
|
|
217
|
+
*/
|
|
217
218
|
inline std::size_t bits_per_scalar(scalar_kind_t scalar_kind) noexcept {
|
|
218
219
|
switch (scalar_kind) {
|
|
219
220
|
case scalar_kind_t::uuid_k: return 128;
|
|
@@ -236,6 +237,10 @@ inline std::size_t bits_per_scalar(scalar_kind_t scalar_kind) noexcept {
|
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
239
|
|
|
240
|
+
/**
|
|
241
|
+
* @brief Returns the number of bits in a scalar word for a given scalar type.
|
|
242
|
+
* Equivalent to `bits_per_scalar` for types that are not bit-packed.
|
|
243
|
+
*/
|
|
239
244
|
inline std::size_t bits_per_scalar_word(scalar_kind_t scalar_kind) noexcept {
|
|
240
245
|
switch (scalar_kind) {
|
|
241
246
|
case scalar_kind_t::uuid_k: return 128;
|
|
@@ -258,6 +263,9 @@ inline std::size_t bits_per_scalar_word(scalar_kind_t scalar_kind) noexcept {
|
|
|
258
263
|
}
|
|
259
264
|
}
|
|
260
265
|
|
|
266
|
+
/**
|
|
267
|
+
* @brief Returns the string name of a given scalar type.
|
|
268
|
+
*/
|
|
261
269
|
inline char const* scalar_kind_name(scalar_kind_t scalar_kind) noexcept {
|
|
262
270
|
switch (scalar_kind) {
|
|
263
271
|
case scalar_kind_t::uuid_k: return "uuid";
|
|
@@ -280,6 +288,9 @@ inline char const* scalar_kind_name(scalar_kind_t scalar_kind) noexcept {
|
|
|
280
288
|
}
|
|
281
289
|
}
|
|
282
290
|
|
|
291
|
+
/**
|
|
292
|
+
* @brief Returns the string name of a given distance metric.
|
|
293
|
+
*/
|
|
283
294
|
inline char const* metric_kind_name(metric_kind_t metric) noexcept {
|
|
284
295
|
switch (metric) {
|
|
285
296
|
case metric_kind_t::unknown_k: return "unknown";
|
|
@@ -296,6 +307,10 @@ inline char const* metric_kind_name(metric_kind_t metric) noexcept {
|
|
|
296
307
|
default: return "";
|
|
297
308
|
}
|
|
298
309
|
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @brief Parses a string to identify the corresponding `scalar_kind_t` enumeration value.
|
|
313
|
+
*/
|
|
299
314
|
inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::size_t len) {
|
|
300
315
|
expected_gt<scalar_kind_t> parsed;
|
|
301
316
|
if (str_equals(name, len, "f32"))
|
|
@@ -315,10 +330,16 @@ inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::s
|
|
|
315
330
|
return parsed;
|
|
316
331
|
}
|
|
317
332
|
|
|
333
|
+
/**
|
|
334
|
+
* @brief Parses a string to identify the corresponding `scalar_kind_t` enumeration value.
|
|
335
|
+
*/
|
|
318
336
|
inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name) {
|
|
319
337
|
return scalar_kind_from_name(name, std::strlen(name));
|
|
320
338
|
}
|
|
321
339
|
|
|
340
|
+
/**
|
|
341
|
+
* @brief Parses a string to identify the corresponding `metric_kind_t` enumeration value.
|
|
342
|
+
*/
|
|
322
343
|
inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t len) {
|
|
323
344
|
expected_gt<metric_kind_t> parsed;
|
|
324
345
|
if (str_equals(name, len, "l2sq") || str_equals(name, len, "euclidean_sq")) {
|
|
@@ -344,6 +365,10 @@ inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t
|
|
|
344
365
|
"tanimoto, sorensen");
|
|
345
366
|
return parsed;
|
|
346
367
|
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* @brief Parses a string to identify the corresponding `metric_kind_t` enumeration value.
|
|
371
|
+
*/
|
|
347
372
|
inline expected_gt<metric_kind_t> metric_from_name(char const* name) {
|
|
348
373
|
return metric_from_name(name, std::strlen(name));
|
|
349
374
|
}
|
|
@@ -352,12 +377,14 @@ inline expected_gt<metric_kind_t> metric_from_name(char const* name) {
|
|
|
352
377
|
* @brief Convenience function to upcast a half-precision floating point number to a single-precision one.
|
|
353
378
|
*/
|
|
354
379
|
inline float f16_to_f32(std::uint16_t u16) noexcept {
|
|
355
|
-
#if
|
|
380
|
+
#if USEARCH_USE_FP16LIB
|
|
381
|
+
return fp16_ieee_to_fp32_value(u16);
|
|
382
|
+
#elif USEARCH_USE_SIMSIMD
|
|
383
|
+
return simsimd_uncompress_f16(u16);
|
|
384
|
+
#else
|
|
356
385
|
f16_native_t f16;
|
|
357
386
|
std::memcpy(&f16, &u16, sizeof(std::uint16_t));
|
|
358
387
|
return float(f16);
|
|
359
|
-
#else
|
|
360
|
-
return fp16_ieee_to_fp32_value(u16);
|
|
361
388
|
#endif
|
|
362
389
|
}
|
|
363
390
|
|
|
@@ -365,13 +392,15 @@ inline float f16_to_f32(std::uint16_t u16) noexcept {
|
|
|
365
392
|
* @brief Convenience function to downcast a single-precision floating point number to a half-precision one.
|
|
366
393
|
*/
|
|
367
394
|
inline std::uint16_t f32_to_f16(float f32) noexcept {
|
|
368
|
-
#if
|
|
395
|
+
#if USEARCH_USE_FP16LIB
|
|
396
|
+
return fp16_ieee_from_fp32_value(f32);
|
|
397
|
+
#elif USEARCH_USE_SIMSIMD
|
|
398
|
+
return simsimd_compress_f16(f32);
|
|
399
|
+
#else
|
|
369
400
|
f16_native_t f16 = f16_native_t(f32);
|
|
370
401
|
std::uint16_t u16;
|
|
371
402
|
std::memcpy(&u16, &f16, sizeof(std::uint16_t));
|
|
372
403
|
return u16;
|
|
373
|
-
#else
|
|
374
|
-
return fp16_ieee_from_fp32_value(f32);
|
|
375
404
|
#endif
|
|
376
405
|
}
|
|
377
406
|
|
|
@@ -380,6 +409,9 @@ inline std::uint16_t f32_to_f16(float f32) noexcept {
|
|
|
380
409
|
* https://github.com/ashvardanian/SimSIMD/blob/ff51434d90c66f916e94ff05b24530b127aa4cff/include/simsimd/types.h#L395-L410
|
|
381
410
|
*/
|
|
382
411
|
inline float bf16_to_f32(std::uint16_t u16) noexcept {
|
|
412
|
+
#if USEARCH_USE_SIMSIMD
|
|
413
|
+
return simsimd_uncompress_bf16(u16);
|
|
414
|
+
#else
|
|
383
415
|
union float_or_unsigned_int_t {
|
|
384
416
|
float f;
|
|
385
417
|
unsigned int i;
|
|
@@ -387,6 +419,7 @@ inline float bf16_to_f32(std::uint16_t u16) noexcept {
|
|
|
387
419
|
union float_or_unsigned_int_t result_union;
|
|
388
420
|
result_union.i = u16 << 16; // Zero extends the mantissa
|
|
389
421
|
return result_union.f;
|
|
422
|
+
#endif
|
|
390
423
|
}
|
|
391
424
|
|
|
392
425
|
/**
|
|
@@ -394,6 +427,9 @@ inline float bf16_to_f32(std::uint16_t u16) noexcept {
|
|
|
394
427
|
* https://github.com/ashvardanian/SimSIMD/blob/ff51434d90c66f916e94ff05b24530b127aa4cff/include/simsimd/types.h#L412-L425
|
|
395
428
|
*/
|
|
396
429
|
inline std::uint16_t f32_to_bf16(float f32) noexcept {
|
|
430
|
+
#if USEARCH_USE_SIMSIMD
|
|
431
|
+
return simsimd_compress_bf16(f32);
|
|
432
|
+
#else
|
|
397
433
|
union float_or_unsigned_int_t {
|
|
398
434
|
float f;
|
|
399
435
|
unsigned int i;
|
|
@@ -403,6 +439,7 @@ inline std::uint16_t f32_to_bf16(float f32) noexcept {
|
|
|
403
439
|
value.i >>= 16;
|
|
404
440
|
value.i &= 0xFFFF;
|
|
405
441
|
return (unsigned short)value.i;
|
|
442
|
+
#endif
|
|
406
443
|
}
|
|
407
444
|
|
|
408
445
|
/**
|
|
@@ -428,7 +465,7 @@ class f16_bits_t {
|
|
|
428
465
|
inline f16_bits_t(float v) noexcept : uint16_(f32_to_f16(v)) {}
|
|
429
466
|
inline f16_bits_t(double v) noexcept : uint16_(f32_to_f16(static_cast<float>(v))) {}
|
|
430
467
|
|
|
431
|
-
inline bool operator<(const
|
|
468
|
+
inline bool operator<(f16_bits_t const& other) const noexcept { return float(*this) < float(other); }
|
|
432
469
|
|
|
433
470
|
inline f16_bits_t operator+(f16_bits_t other) const noexcept { return {float(*this) + float(other)}; }
|
|
434
471
|
inline f16_bits_t operator-(f16_bits_t other) const noexcept { return {float(*this) - float(other)}; }
|
|
@@ -1047,6 +1084,10 @@ template <> struct cast_gt<f16_bits_t, f16_bits_t> {
|
|
|
1047
1084
|
static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
|
|
1048
1085
|
};
|
|
1049
1086
|
|
|
1087
|
+
template <> struct cast_gt<bf16_bits_t, bf16_bits_t> {
|
|
1088
|
+
static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
|
|
1089
|
+
};
|
|
1090
|
+
|
|
1050
1091
|
template <> struct cast_gt<i8_t, i8_t> {
|
|
1051
1092
|
static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
|
|
1052
1093
|
};
|
|
@@ -1119,23 +1160,23 @@ template <typename to_scalar_at> struct cast_from_i8_gt {
|
|
|
1119
1160
|
}
|
|
1120
1161
|
};
|
|
1121
1162
|
|
|
1122
|
-
template <> struct cast_gt<i8_t,
|
|
1123
|
-
template <> struct cast_gt<i8_t,
|
|
1163
|
+
template <> struct cast_gt<i8_t, f16_bits_t> : public cast_from_i8_gt<f16_t> {};
|
|
1164
|
+
template <> struct cast_gt<i8_t, bf16_bits_t> : public cast_from_i8_gt<bf16_t> {};
|
|
1124
1165
|
template <> struct cast_gt<i8_t, f32_t> : public cast_from_i8_gt<f32_t> {};
|
|
1125
1166
|
template <> struct cast_gt<i8_t, f64_t> : public cast_from_i8_gt<f64_t> {};
|
|
1126
1167
|
|
|
1127
|
-
template <> struct cast_gt<
|
|
1128
|
-
template <> struct cast_gt<
|
|
1168
|
+
template <> struct cast_gt<f16_bits_t, i8_t> : public cast_to_i8_gt<f16_t> {};
|
|
1169
|
+
template <> struct cast_gt<bf16_bits_t, i8_t> : public cast_to_i8_gt<bf16_t> {};
|
|
1129
1170
|
template <> struct cast_gt<f32_t, i8_t> : public cast_to_i8_gt<f32_t> {};
|
|
1130
1171
|
template <> struct cast_gt<f64_t, i8_t> : public cast_to_i8_gt<f64_t> {};
|
|
1131
1172
|
|
|
1132
|
-
template <> struct cast_gt<b1x8_t,
|
|
1133
|
-
template <> struct cast_gt<b1x8_t,
|
|
1173
|
+
template <> struct cast_gt<b1x8_t, f16_bits_t> : public cast_from_b1x8_gt<f16_t> {};
|
|
1174
|
+
template <> struct cast_gt<b1x8_t, bf16_bits_t> : public cast_from_b1x8_gt<bf16_t> {};
|
|
1134
1175
|
template <> struct cast_gt<b1x8_t, f32_t> : public cast_from_b1x8_gt<f32_t> {};
|
|
1135
1176
|
template <> struct cast_gt<b1x8_t, f64_t> : public cast_from_b1x8_gt<f64_t> {};
|
|
1136
1177
|
|
|
1137
|
-
template <> struct cast_gt<
|
|
1138
|
-
template <> struct cast_gt<
|
|
1178
|
+
template <> struct cast_gt<f16_bits_t, b1x8_t> : public cast_to_b1x8_gt<f16_t> {};
|
|
1179
|
+
template <> struct cast_gt<bf16_bits_t, b1x8_t> : public cast_to_b1x8_gt<bf16_t> {};
|
|
1139
1180
|
template <> struct cast_gt<f32_t, b1x8_t> : public cast_to_b1x8_gt<f32_t> {};
|
|
1140
1181
|
template <> struct cast_gt<f64_t, b1x8_t> : public cast_to_b1x8_gt<f64_t> {};
|
|
1141
1182
|
|
|
@@ -1426,7 +1467,10 @@ template <typename scalar_at = float, typename result_at = float> struct metric_
|
|
|
1426
1467
|
}
|
|
1427
1468
|
};
|
|
1428
1469
|
|
|
1429
|
-
|
|
1470
|
+
/**
|
|
1471
|
+
* @brief Cosine (Angular) distance for signed 8-bit integers using 16-bit intermediates.
|
|
1472
|
+
*/
|
|
1473
|
+
struct metric_cos_i8_t {
|
|
1430
1474
|
using scalar_t = i8_t;
|
|
1431
1475
|
using result_t = f32_t;
|
|
1432
1476
|
|
|
@@ -1452,7 +1496,11 @@ struct cos_i8_t {
|
|
|
1452
1496
|
}
|
|
1453
1497
|
};
|
|
1454
1498
|
|
|
1455
|
-
|
|
1499
|
+
/**
|
|
1500
|
+
* @brief Squared Euclidean (L2) distance for signed 8-bit integers using 16-bit intermediates.
|
|
1501
|
+
* Square root is avoided at the end, as it won't affect the ordering.
|
|
1502
|
+
*/
|
|
1503
|
+
struct metric_l2sq_i8_t {
|
|
1456
1504
|
using scalar_t = i8_t;
|
|
1457
1505
|
using result_t = f32_t;
|
|
1458
1506
|
|
|
@@ -1782,7 +1830,7 @@ class metric_punned_t {
|
|
|
1782
1830
|
case metric_kind_t::cos_k: {
|
|
1783
1831
|
switch (scalar_kind_) {
|
|
1784
1832
|
case scalar_kind_t::bf16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<bf16_t, f32_t>>; break;
|
|
1785
|
-
case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<
|
|
1833
|
+
case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_i8_t>; break;
|
|
1786
1834
|
case scalar_kind_t::f16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f16_t, f32_t>>; break;
|
|
1787
1835
|
case scalar_kind_t::f32_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f32_t>>; break;
|
|
1788
1836
|
case scalar_kind_t::f64_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f64_t>>; break;
|
|
@@ -1793,7 +1841,7 @@ class metric_punned_t {
|
|
|
1793
1841
|
case metric_kind_t::l2sq_k: {
|
|
1794
1842
|
switch (scalar_kind_) {
|
|
1795
1843
|
case scalar_kind_t::bf16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<bf16_t, f32_t>>; break;
|
|
1796
|
-
case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<
|
|
1844
|
+
case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_i8_t>; break;
|
|
1797
1845
|
case scalar_kind_t::f16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f16_t, f32_t>>; break;
|
|
1798
1846
|
case scalar_kind_t::f32_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f32_t>>; break;
|
|
1799
1847
|
case scalar_kind_t::f64_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f64_t>>; break;
|
|
@@ -2088,7 +2136,7 @@ class flat_hash_multi_set_gt {
|
|
|
2088
2136
|
// Allocate new memory
|
|
2089
2137
|
data_ = (char*)allocator_t{}.allocate(other.buckets_ * bytes_per_bucket());
|
|
2090
2138
|
if (!data_)
|
|
2091
|
-
|
|
2139
|
+
__usearch_raise_runtime_error("failed memory allocation");
|
|
2092
2140
|
|
|
2093
2141
|
// Copy metadata
|
|
2094
2142
|
buckets_ = other.buckets_;
|
|
@@ -2128,7 +2176,7 @@ class flat_hash_multi_set_gt {
|
|
|
2128
2176
|
// Allocate new memory
|
|
2129
2177
|
data_ = (char*)allocator_t{}.allocate(other.buckets_ * bytes_per_bucket());
|
|
2130
2178
|
if (!data_)
|
|
2131
|
-
|
|
2179
|
+
__usearch_raise_runtime_error("failed memory allocation");
|
|
2132
2180
|
|
|
2133
2181
|
// Copy metadata
|
|
2134
2182
|
buckets_ = other.buckets_;
|
|
@@ -2501,7 +2549,7 @@ class flat_hash_multi_set_gt {
|
|
|
2501
2549
|
|
|
2502
2550
|
void reserve(std::size_t capacity) {
|
|
2503
2551
|
if (!try_reserve(capacity))
|
|
2504
|
-
|
|
2552
|
+
__usearch_raise_runtime_error("failed to reserve memory");
|
|
2505
2553
|
}
|
|
2506
2554
|
|
|
2507
2555
|
bool try_emplace(element_t const& element) noexcept {
|
package/javascript/README.md
CHANGED
|
@@ -21,8 +21,9 @@ wasmer install unum/usearch
|
|
|
21
21
|
Create an index, add vectors, and perform searches with ease:
|
|
22
22
|
|
|
23
23
|
```js
|
|
24
|
+
const assert = require('node:assert');
|
|
24
25
|
const usearch = require('usearch');
|
|
25
|
-
const index = new usearch.Index({ metric: '
|
|
26
|
+
const index = new usearch.Index({ metric: 'l2sq', connectivity: 16, dimensions: 3 });
|
|
26
27
|
index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
|
|
27
28
|
const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
|
|
28
29
|
|
|
@@ -47,13 +47,13 @@ test('Batch operations', () => {
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
test("Expected results", () => {
|
|
50
|
-
|
|
50
|
+
const index = new usearch.Index({
|
|
51
51
|
metric: "l2sq",
|
|
52
52
|
connectivity: 16,
|
|
53
53
|
dimensions: 3,
|
|
54
54
|
});
|
|
55
55
|
index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
|
|
56
|
-
|
|
56
|
+
const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
|
|
57
57
|
|
|
58
58
|
assert.equal(index.size(), 1);
|
|
59
59
|
assert.deepEqual(results.keys, new BigUint64Array([42n]));
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|