usearch 1.3.0 → 2.0.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.
- package/.github/workflows/prerelease.yml +45 -0
- package/.github/workflows/release.yml +76 -1
- package/.github/workflows/update_version.sh +1 -0
- package/.gitignore +11 -1
- package/.vscode/settings.json +5 -1
- package/Cargo.toml +1 -1
- package/README.md +15 -8
- package/c/lib.cpp +3 -3
- package/conanfile.py +1 -1
- package/csharp/.editorconfig +361 -0
- package/csharp/Cloud.Unum.USearch.sln +34 -0
- package/csharp/DEV_SETUP.md +51 -0
- package/csharp/Directory.Build.props +29 -0
- package/csharp/README.md +77 -0
- package/csharp/build_and_test.cmd +31 -0
- package/csharp/build_and_test.sh +30 -0
- package/csharp/eng/build_lib.sh +65 -0
- package/csharp/eng/clean.sh +12 -0
- package/csharp/nuget/NUGET.md +11 -0
- package/csharp/nuget/nuget-package.props +33 -0
- package/csharp/pack.sh +56 -0
- package/csharp/src/Cloud.Unum.USearch.Tests/Cloud.Unum.USearch.Tests.csproj +39 -0
- package/csharp/src/Cloud.Unum.USearch.Tests/InitTests.cs +306 -0
- package/csharp/src/Cloud.Unum.USearch.Tests/Usings.cs +1 -0
- package/include/usearch/index_dense.hpp +8 -8
- package/include/usearch/index_plugins.hpp +56 -49
- package/package.json +1 -1
- package/python/lib.cpp +6 -6
- package/rust/lib.cpp +27 -15
- package/rust/lib.hpp +9 -0
- package/rust/lib.rs +10 -0
- package/wasmer.toml +1 -1
|
@@ -54,8 +54,8 @@ struct uuid_t {
|
|
|
54
54
|
std::uint8_t octets[16];
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
class i8_bits_t;
|
|
58
57
|
class f16_bits_t;
|
|
58
|
+
class i8_converted_t;
|
|
59
59
|
|
|
60
60
|
#if USEARCH_USE_NATIVE_F16
|
|
61
61
|
#if defined(USEARCH_DEFINED_ARM)
|
|
@@ -149,7 +149,7 @@ template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
|
|
|
149
149
|
return scalar_kind_t::f32_k;
|
|
150
150
|
if (std::is_same<scalar_at, f16_t>())
|
|
151
151
|
return scalar_kind_t::f16_k;
|
|
152
|
-
if (std::is_same<scalar_at,
|
|
152
|
+
if (std::is_same<scalar_at, i8_t>())
|
|
153
153
|
return scalar_kind_t::i8_k;
|
|
154
154
|
if (std::is_same<scalar_at, u64_t>())
|
|
155
155
|
return scalar_kind_t::u64_k;
|
|
@@ -364,7 +364,7 @@ class f16_bits_t {
|
|
|
364
364
|
inline operator float() const noexcept { return f16_to_f32(uint16_); }
|
|
365
365
|
inline explicit operator bool() const noexcept { return f16_to_f32(uint16_) > 0.5f; }
|
|
366
366
|
|
|
367
|
-
inline f16_bits_t(
|
|
367
|
+
inline f16_bits_t(i8_converted_t) noexcept;
|
|
368
368
|
inline f16_bits_t(bool v) noexcept : uint16_(f32_to_f16(v)) {}
|
|
369
369
|
inline f16_bits_t(float v) noexcept : uint16_(f32_to_f16(v)) {}
|
|
370
370
|
inline f16_bits_t(double v) noexcept : uint16_(f32_to_f16(v)) {}
|
|
@@ -403,45 +403,6 @@ class f16_bits_t {
|
|
|
403
403
|
}
|
|
404
404
|
};
|
|
405
405
|
|
|
406
|
-
/**
|
|
407
|
-
* @brief Numeric type for uniformly-distributed floating point
|
|
408
|
-
* values within [-1,1] range, quantized to integers [-100,100].
|
|
409
|
-
*/
|
|
410
|
-
class i8_bits_t {
|
|
411
|
-
std::int8_t int8_{};
|
|
412
|
-
|
|
413
|
-
public:
|
|
414
|
-
constexpr static float divisor_k = 100.f;
|
|
415
|
-
constexpr static std::int8_t min_k = -100;
|
|
416
|
-
constexpr static std::int8_t max_k = 100;
|
|
417
|
-
|
|
418
|
-
inline i8_bits_t() noexcept : int8_(0) {}
|
|
419
|
-
inline i8_bits_t(bool v) noexcept : int8_(v ? max_k : 0) {}
|
|
420
|
-
|
|
421
|
-
inline i8_bits_t(i8_bits_t&&) = default;
|
|
422
|
-
inline i8_bits_t& operator=(i8_bits_t&&) = default;
|
|
423
|
-
inline i8_bits_t(i8_bits_t const&) = default;
|
|
424
|
-
inline i8_bits_t& operator=(i8_bits_t const&) = default;
|
|
425
|
-
|
|
426
|
-
inline operator float() const noexcept { return float(int8_) / divisor_k; }
|
|
427
|
-
inline operator f16_t() const noexcept { return float(int8_) / divisor_k; }
|
|
428
|
-
inline operator double() const noexcept { return double(int8_) / divisor_k; }
|
|
429
|
-
inline explicit operator bool() const noexcept { return int8_ > (max_k / 2); }
|
|
430
|
-
inline explicit operator std::int8_t() const noexcept { return int8_; }
|
|
431
|
-
inline explicit operator std::int16_t() const noexcept { return int8_; }
|
|
432
|
-
inline explicit operator std::int32_t() const noexcept { return int8_; }
|
|
433
|
-
inline explicit operator std::int64_t() const noexcept { return int8_; }
|
|
434
|
-
|
|
435
|
-
inline i8_bits_t(f16_t v)
|
|
436
|
-
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
|
|
437
|
-
inline i8_bits_t(float v)
|
|
438
|
-
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
|
|
439
|
-
inline i8_bits_t(double v)
|
|
440
|
-
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
inline f16_bits_t::f16_bits_t(i8_bits_t v) noexcept : f16_bits_t(float(v)) {}
|
|
444
|
-
|
|
445
406
|
/**
|
|
446
407
|
* @brief An STL-based executor or a "thread-pool" for parallel execution.
|
|
447
408
|
* Isn't efficient for small batches, as it recreates the threads on every call.
|
|
@@ -953,7 +914,7 @@ template <> struct cast_gt<f16_bits_t, f16_bits_t> {
|
|
|
953
914
|
bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
|
|
954
915
|
};
|
|
955
916
|
|
|
956
|
-
template <> struct cast_gt<
|
|
917
|
+
template <> struct cast_gt<i8_t, i8_t> {
|
|
957
918
|
bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
|
|
958
919
|
};
|
|
959
920
|
|
|
@@ -981,6 +942,53 @@ template <typename to_scalar_at> struct cast_gt<b1x8_t, to_scalar_at> {
|
|
|
981
942
|
}
|
|
982
943
|
};
|
|
983
944
|
|
|
945
|
+
/**
|
|
946
|
+
* @brief Numeric type for uniformly-distributed floating point
|
|
947
|
+
* values within [-1,1] range, quantized to integers [-100,100].
|
|
948
|
+
*/
|
|
949
|
+
class i8_converted_t {
|
|
950
|
+
std::int8_t int8_{};
|
|
951
|
+
|
|
952
|
+
public:
|
|
953
|
+
constexpr static float divisor_k = 100.f;
|
|
954
|
+
constexpr static std::int8_t min_k = -100;
|
|
955
|
+
constexpr static std::int8_t max_k = 100;
|
|
956
|
+
|
|
957
|
+
inline i8_converted_t() noexcept : int8_(0) {}
|
|
958
|
+
inline i8_converted_t(bool v) noexcept : int8_(v ? max_k : 0) {}
|
|
959
|
+
|
|
960
|
+
inline i8_converted_t(i8_converted_t&&) = default;
|
|
961
|
+
inline i8_converted_t& operator=(i8_converted_t&&) = default;
|
|
962
|
+
inline i8_converted_t(i8_converted_t const&) = default;
|
|
963
|
+
inline i8_converted_t& operator=(i8_converted_t const&) = default;
|
|
964
|
+
|
|
965
|
+
inline operator float() const noexcept { return float(int8_) / divisor_k; }
|
|
966
|
+
inline operator f16_t() const noexcept { return float(int8_) / divisor_k; }
|
|
967
|
+
inline operator double() const noexcept { return double(int8_) / divisor_k; }
|
|
968
|
+
inline explicit operator bool() const noexcept { return int8_ > (max_k / 2); }
|
|
969
|
+
inline explicit operator std::int8_t() const noexcept { return int8_; }
|
|
970
|
+
inline explicit operator std::int16_t() const noexcept { return int8_; }
|
|
971
|
+
inline explicit operator std::int32_t() const noexcept { return int8_; }
|
|
972
|
+
inline explicit operator std::int64_t() const noexcept { return int8_; }
|
|
973
|
+
|
|
974
|
+
inline i8_converted_t(f16_t v)
|
|
975
|
+
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
|
|
976
|
+
inline i8_converted_t(float v)
|
|
977
|
+
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
|
|
978
|
+
inline i8_converted_t(double v)
|
|
979
|
+
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
f16_bits_t::f16_bits_t(i8_converted_t v) noexcept : uint16_(f32_to_f16(v)) {}
|
|
983
|
+
|
|
984
|
+
template <> struct cast_gt<i8_t, f16_t> : public cast_gt<i8_converted_t, f16_t> {};
|
|
985
|
+
template <> struct cast_gt<i8_t, f32_t> : public cast_gt<i8_converted_t, f32_t> {};
|
|
986
|
+
template <> struct cast_gt<i8_t, f64_t> : public cast_gt<i8_converted_t, f64_t> {};
|
|
987
|
+
|
|
988
|
+
template <> struct cast_gt<f16_t, i8_t> : public cast_gt<f16_t, i8_converted_t> {};
|
|
989
|
+
template <> struct cast_gt<f32_t, i8_t> : public cast_gt<f32_t, i8_converted_t> {};
|
|
990
|
+
template <> struct cast_gt<f64_t, i8_t> : public cast_gt<f64_t, i8_converted_t> {};
|
|
991
|
+
|
|
984
992
|
/**
|
|
985
993
|
* @brief Inner (Dot) Product distance.
|
|
986
994
|
*/
|
|
@@ -1205,10 +1213,10 @@ template <typename scalar_at = float, typename result_at = float> struct metric_
|
|
|
1205
1213
|
};
|
|
1206
1214
|
|
|
1207
1215
|
struct cos_i8_t {
|
|
1208
|
-
using scalar_t =
|
|
1216
|
+
using scalar_t = i8_t;
|
|
1209
1217
|
using result_t = f32_t;
|
|
1210
1218
|
|
|
1211
|
-
inline result_t operator()(
|
|
1219
|
+
inline result_t operator()(i8_t const* a, i8_t const* b, std::size_t dim) const noexcept {
|
|
1212
1220
|
std::int32_t ab{}, a2{}, b2{};
|
|
1213
1221
|
#if USEARCH_USE_OPENMP
|
|
1214
1222
|
#pragma omp simd reduction(+ : ab, a2, b2)
|
|
@@ -1229,10 +1237,10 @@ struct cos_i8_t {
|
|
|
1229
1237
|
};
|
|
1230
1238
|
|
|
1231
1239
|
struct l2sq_i8_t {
|
|
1232
|
-
using scalar_t =
|
|
1240
|
+
using scalar_t = i8_t;
|
|
1233
1241
|
using result_t = f32_t;
|
|
1234
1242
|
|
|
1235
|
-
inline result_t operator()(
|
|
1243
|
+
inline result_t operator()(i8_t const* a, i8_t const* b, std::size_t dim) const noexcept {
|
|
1236
1244
|
std::int32_t ab_deltas_sq{};
|
|
1237
1245
|
#if USEARCH_USE_OPENMP
|
|
1238
1246
|
#pragma omp simd reduction(+ : ab_deltas_sq)
|
|
@@ -1431,7 +1439,6 @@ class metric_punned_t {
|
|
|
1431
1439
|
static metric_punned_t haversine_metric_(scalar_kind_t scalar_kind) {
|
|
1432
1440
|
std::size_t bytes_per_vector = 2u * bits_per_scalar(scalar_kind) / CHAR_BIT;
|
|
1433
1441
|
switch (scalar_kind) {
|
|
1434
|
-
case scalar_kind_t::i8_k: return {to_stl_<metric_haversine_gt<i8_bits_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::i8_k, isa_kind_t::auto_k};
|
|
1435
1442
|
case scalar_kind_t::f16_k: return {to_stl_<metric_haversine_gt<f16_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::f16_k, isa_kind_t::auto_k};
|
|
1436
1443
|
case scalar_kind_t::f32_k: return {to_stl_<metric_haversine_gt<f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::f32_k, isa_kind_t::auto_k};
|
|
1437
1444
|
case scalar_kind_t::f64_k: return {to_stl_<metric_haversine_gt<f64_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::f64_k, isa_kind_t::auto_k};
|
|
@@ -1441,7 +1448,7 @@ class metric_punned_t {
|
|
|
1441
1448
|
|
|
1442
1449
|
static metric_punned_t pearson_metric_(std::size_t bytes_per_vector, scalar_kind_t scalar_kind) {
|
|
1443
1450
|
switch (scalar_kind) {
|
|
1444
|
-
case scalar_kind_t::i8_k: return {to_stl_<metric_pearson_gt<
|
|
1451
|
+
case scalar_kind_t::i8_k: return {to_stl_<metric_pearson_gt<i8_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::i8_k, isa_kind_t::auto_k};
|
|
1445
1452
|
case scalar_kind_t::f16_k: return {to_stl_<metric_pearson_gt<f16_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::f16_k, isa_kind_t::auto_k};
|
|
1446
1453
|
case scalar_kind_t::f32_k: return {to_stl_<metric_pearson_gt<f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::f32_k, isa_kind_t::auto_k};
|
|
1447
1454
|
case scalar_kind_t::f64_k: return {to_stl_<metric_pearson_gt<f64_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::f64_k, isa_kind_t::auto_k};
|
package/package.json
CHANGED
package/python/lib.cpp
CHANGED
|
@@ -144,7 +144,7 @@ metric_t wrap_user_defined_metric(
|
|
|
144
144
|
case scalar_kind_t::b1x8_k:
|
|
145
145
|
return wrap_typed_user_defined_metric<b1x8_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
|
|
146
146
|
case scalar_kind_t::i8_k:
|
|
147
|
-
return wrap_typed_user_defined_metric<
|
|
147
|
+
return wrap_typed_user_defined_metric<i8_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
|
|
148
148
|
case scalar_kind_t::f16_k:
|
|
149
149
|
return wrap_typed_user_defined_metric<f16_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
|
|
150
150
|
case scalar_kind_t::f32_k:
|
|
@@ -273,7 +273,7 @@ static void add_many_to_index( //
|
|
|
273
273
|
// clang-format off
|
|
274
274
|
switch (numpy_string_to_kind(vectors_info.format)) {
|
|
275
275
|
case scalar_kind_t::b1x8_k: add_typed_to_index<b1x8_t>(index, keys_info, vectors_info, force_copy, threads); break;
|
|
276
|
-
case scalar_kind_t::i8_k: add_typed_to_index<
|
|
276
|
+
case scalar_kind_t::i8_k: add_typed_to_index<i8_t>(index, keys_info, vectors_info, force_copy, threads); break;
|
|
277
277
|
case scalar_kind_t::f16_k: add_typed_to_index<f16_t>(index, keys_info, vectors_info, force_copy, threads); break;
|
|
278
278
|
case scalar_kind_t::f32_k: add_typed_to_index<f32_t>(index, keys_info, vectors_info, force_copy, threads); break;
|
|
279
279
|
case scalar_kind_t::f64_k: add_typed_to_index<f64_t>(index, keys_info, vectors_info, force_copy, threads); break;
|
|
@@ -442,7 +442,7 @@ static py::tuple search_many_in_index( //
|
|
|
442
442
|
// clang-format off
|
|
443
443
|
switch (numpy_string_to_kind(vectors_info.format)) {
|
|
444
444
|
case scalar_kind_t::b1x8_k: search_typed<b1x8_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
|
|
445
|
-
case scalar_kind_t::i8_k: search_typed<
|
|
445
|
+
case scalar_kind_t::i8_k: search_typed<i8_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
|
|
446
446
|
case scalar_kind_t::f16_k: search_typed<f16_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
|
|
447
447
|
case scalar_kind_t::f32_k: search_typed<f32_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
|
|
448
448
|
case scalar_kind_t::f64_k: search_typed<f64_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
|
|
@@ -561,7 +561,7 @@ static py::tuple search_many_brute_force( //
|
|
|
561
561
|
// clang-format off
|
|
562
562
|
switch (dataset_kind) {
|
|
563
563
|
case scalar_kind_t::b1x8_k: search_typed_brute_force<b1x8_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
|
|
564
|
-
case scalar_kind_t::i8_k: search_typed_brute_force<
|
|
564
|
+
case scalar_kind_t::i8_k: search_typed_brute_force<i8_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
|
|
565
565
|
case scalar_kind_t::f16_k: search_typed_brute_force<f16_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
|
|
566
566
|
case scalar_kind_t::f32_k: search_typed_brute_force<f32_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
|
|
567
567
|
case scalar_kind_t::f64_k: search_typed_brute_force<f64_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
|
|
@@ -638,7 +638,7 @@ static py::tuple cluster_vectors( //
|
|
|
638
638
|
// clang-format off
|
|
639
639
|
switch (numpy_string_to_kind(queries_info.format)) {
|
|
640
640
|
case scalar_kind_t::b1x8_k: cluster_result = index.cluster(queries_begin.as<b1x8_t const>(), queries_end.as<b1x8_t const>(), config, keys_ptr, distances_ptr, executor); break;
|
|
641
|
-
case scalar_kind_t::i8_k: cluster_result = index.cluster(queries_begin.as<
|
|
641
|
+
case scalar_kind_t::i8_k: cluster_result = index.cluster(queries_begin.as<i8_t const>(), queries_end.as<i8_t const>(), config, keys_ptr, distances_ptr, executor); break;
|
|
642
642
|
case scalar_kind_t::f16_k: cluster_result = index.cluster(queries_begin.as<f16_t const>(), queries_end.as<f16_t const>(), config, keys_ptr, distances_ptr, executor); break;
|
|
643
643
|
case scalar_kind_t::f32_k: cluster_result = index.cluster(queries_begin.as<f32_t const>(), queries_end.as<f32_t const>(), config, keys_ptr, distances_ptr, executor); break;
|
|
644
644
|
case scalar_kind_t::f64_k: cluster_result = index.cluster(queries_begin.as<f64_t const>(), queries_end.as<f64_t const>(), config, keys_ptr, distances_ptr, executor); break;
|
|
@@ -876,7 +876,7 @@ template <typename index_at> py::tuple get_many(index_at const& index, py::buffe
|
|
|
876
876
|
else if (scalar_kind == scalar_kind_t::f16_k)
|
|
877
877
|
return get_typed_vectors_for_keys<f16_t, std::uint16_t>(index, keys);
|
|
878
878
|
else if (scalar_kind == scalar_kind_t::i8_k)
|
|
879
|
-
return get_typed_vectors_for_keys<
|
|
879
|
+
return get_typed_vectors_for_keys<i8_t, std::int8_t>(index, keys);
|
|
880
880
|
else if (scalar_kind == scalar_kind_t::b1x8_k)
|
|
881
881
|
return get_typed_vectors_for_keys<b1x8_t, std::uint8_t>(index, keys);
|
|
882
882
|
else
|
package/rust/lib.cpp
CHANGED
|
@@ -9,9 +9,35 @@ using add_result_t = typename index_t::add_result_t;
|
|
|
9
9
|
using search_result_t = typename index_t::search_result_t;
|
|
10
10
|
using labeling_result_t = typename index_t::labeling_result_t;
|
|
11
11
|
|
|
12
|
+
template <typename scalar_at> Matches search_(index_dense_t& index, scalar_at const* vec, size_t count) {
|
|
13
|
+
Matches matches;
|
|
14
|
+
matches.keys.reserve(count);
|
|
15
|
+
matches.distances.reserve(count);
|
|
16
|
+
for (size_t i = 0; i != count; ++i)
|
|
17
|
+
matches.keys.push_back(0), matches.distances.push_back(0);
|
|
18
|
+
search_result_t result = index.search(vec, count);
|
|
19
|
+
result.error.raise();
|
|
20
|
+
count = result.dump_to(matches.keys.data(), matches.distances.data());
|
|
21
|
+
matches.keys.truncate(count);
|
|
22
|
+
matches.distances.truncate(count);
|
|
23
|
+
return matches;
|
|
24
|
+
}
|
|
25
|
+
|
|
12
26
|
Index::Index(std::unique_ptr<index_t> index) : index_(std::move(index)) {}
|
|
13
27
|
|
|
14
|
-
|
|
28
|
+
// clang-format off
|
|
29
|
+
void Index::add(key_t key, rust::Slice<float const> vec) const { index_->add(key, vec.data()).error.raise(); }
|
|
30
|
+
void Index::add_i8(key_t key, rust::Slice<int8_t const> vec) const { index_->add(key, vec.data()).error.raise(); }
|
|
31
|
+
void Index::add_f16(key_t key, rust::Slice<uint16_t const> vec) const { index_->add(key, (f16_t const*)vec.data()).error.raise(); }
|
|
32
|
+
void Index::add_f32(key_t key, rust::Slice<float const> vec) const { index_->add(key, vec.data()).error.raise(); }
|
|
33
|
+
void Index::add_f64(key_t key, rust::Slice<double const> vec) const { index_->add(key, vec.data()).error.raise(); }
|
|
34
|
+
|
|
35
|
+
Matches Index::search(rust::Slice<float const> vec, size_t count) const { return search_(*index_, vec.data(), count); }
|
|
36
|
+
Matches Index::search_i8(rust::Slice<int8_t const> vec, size_t count) const { return search_(*index_, vec.data(), count); }
|
|
37
|
+
Matches Index::search_f16(rust::Slice<uint16_t const> vec, size_t count) const { return search_(*index_, (f16_t const*)vec.data(), count); }
|
|
38
|
+
Matches Index::search_f32(rust::Slice<float const> vec, size_t count) const { return search_(*index_, vec.data(), count); }
|
|
39
|
+
Matches Index::search_f64(rust::Slice<double const> vec, size_t count) const { return search_(*index_, vec.data(), count); }
|
|
40
|
+
// clang-format on
|
|
15
41
|
|
|
16
42
|
bool Index::remove(key_t key) const {
|
|
17
43
|
labeling_result_t result = index_->remove(key);
|
|
@@ -27,20 +53,6 @@ bool Index::rename(key_t from, key_t to) const {
|
|
|
27
53
|
|
|
28
54
|
bool Index::contains(key_t key) const { return index_->contains(key); }
|
|
29
55
|
|
|
30
|
-
Matches Index::search(rust::Slice<float const> vector, size_t count) const {
|
|
31
|
-
Matches matches;
|
|
32
|
-
matches.keys.reserve(count);
|
|
33
|
-
matches.distances.reserve(count);
|
|
34
|
-
for (size_t i = 0; i != count; ++i)
|
|
35
|
-
matches.keys.push_back(0), matches.distances.push_back(0);
|
|
36
|
-
search_result_t result = index_->search(vector.data(), count);
|
|
37
|
-
result.error.raise();
|
|
38
|
-
count = result.dump_to(matches.keys.data(), matches.distances.data());
|
|
39
|
-
matches.keys.truncate(count);
|
|
40
|
-
matches.distances.truncate(count);
|
|
41
|
-
return matches;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
56
|
void Index::reserve(size_t capacity) const { index_->reserve(capacity); }
|
|
45
57
|
|
|
46
58
|
size_t Index::dimensions() const { return index_->dimensions(); }
|
package/rust/lib.hpp
CHANGED
|
@@ -22,7 +22,16 @@ class Index {
|
|
|
22
22
|
void reserve(size_t) const;
|
|
23
23
|
|
|
24
24
|
void add(key_t key, rust::Slice<float const> vector) const;
|
|
25
|
+
void add_i8(key_t key, rust::Slice<int8_t const> vector) const;
|
|
26
|
+
void add_f16(key_t key, rust::Slice<uint16_t const> vector) const;
|
|
27
|
+
void add_f32(key_t key, rust::Slice<float const> vector) const;
|
|
28
|
+
void add_f64(key_t key, rust::Slice<double const> vector) const;
|
|
29
|
+
|
|
25
30
|
Matches search(rust::Slice<float const> vector, size_t count) const;
|
|
31
|
+
Matches search_i8(rust::Slice<int8_t const> vector, size_t count) const;
|
|
32
|
+
Matches search_f16(rust::Slice<uint16_t const> vector, size_t count) const;
|
|
33
|
+
Matches search_f32(rust::Slice<float const> vector, size_t count) const;
|
|
34
|
+
Matches search_f64(rust::Slice<double const> vector, size_t count) const;
|
|
26
35
|
|
|
27
36
|
bool remove(key_t key) const;
|
|
28
37
|
bool contains(key_t key) const;
|
package/rust/lib.rs
CHANGED
|
@@ -83,6 +83,11 @@ pub mod ffi {
|
|
|
83
83
|
/// * `vector` - A slice containing the vector data.
|
|
84
84
|
pub fn add(self: &Index, key: u64, vector: &[f32]) -> Result<()>;
|
|
85
85
|
|
|
86
|
+
pub fn add_i8(self: &Index, key: u64, vector: &[i8]) -> Result<()>;
|
|
87
|
+
pub fn add_f16(self: &Index, key: u64, vector: &[u16]) -> Result<()>;
|
|
88
|
+
pub fn add_f32(self: &Index, key: u64, vector: &[f32]) -> Result<()>;
|
|
89
|
+
pub fn add_f64(self: &Index, key: u64, vector: &[f64]) -> Result<()>;
|
|
90
|
+
|
|
86
91
|
/// Performs k-Approximate Nearest Neighbors (kANN) Search for closest vectors to the provided query.
|
|
87
92
|
///
|
|
88
93
|
/// # Arguments
|
|
@@ -95,6 +100,11 @@ pub mod ffi {
|
|
|
95
100
|
/// A `Result` containing the matches found.
|
|
96
101
|
pub fn search(self: &Index, query: &[f32], count: usize) -> Result<Matches>;
|
|
97
102
|
|
|
103
|
+
pub fn search_i8(self: &Index, query: &[i8], count: usize) -> Result<Matches>;
|
|
104
|
+
pub fn search_f16(self: &Index, query: &[u16], count: usize) -> Result<Matches>;
|
|
105
|
+
pub fn search_f32(self: &Index, query: &[f32], count: usize) -> Result<Matches>;
|
|
106
|
+
pub fn search_f64(self: &Index, query: &[f64], count: usize) -> Result<Matches>;
|
|
107
|
+
|
|
98
108
|
/// Removes the vector associated with the given key from the index.
|
|
99
109
|
///
|
|
100
110
|
/// # Arguments
|