usearch 0.10.0 → 0.11.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/release.yml +1 -1
- package/.gitmodules +3 -0
- package/.vscode/settings.json +2 -0
- package/Cargo.toml +1 -1
- package/Package.swift +1 -0
- package/README.md +1 -1
- package/VERSION +1 -1
- package/binding.gyp +4 -3
- package/build.gradle +1 -1
- package/build.rs +1 -0
- package/conanfile.py +1 -1
- package/docs/compilation.md +6 -3
- package/include/usearch/usearch.hpp +133 -43
- package/package.json +1 -1
- package/python/lib.cpp +36 -24
- package/python/scripts/bench.py +2 -2
- package/python/scripts/test.py +1 -1
- package/python/usearch/index.py +298 -0
- package/robin-map/.codecov.yml +5 -0
- package/robin-map/.github/workflows/ci.yml +136 -0
- package/robin-map/CMakeLists.txt +86 -0
- package/robin-map/LICENSE +21 -0
- package/robin-map/README.md +483 -0
- package/robin-map/cmake/tsl-robin-mapConfig.cmake.in +9 -0
- package/robin-map/doxygen.conf +2483 -0
- package/robin-map/include/tsl/robin_growth_policy.h +406 -0
- package/robin-map/include/tsl/robin_hash.h +1639 -0
- package/robin-map/include/tsl/robin_map.h +807 -0
- package/robin-map/include/tsl/robin_set.h +660 -0
- package/robin-map/tests/CMakeLists.txt +26 -0
- package/robin-map/tests/custom_allocator_tests.cpp +138 -0
- package/robin-map/tests/main.cpp +26 -0
- package/robin-map/tests/policy_tests.cpp +97 -0
- package/robin-map/tests/robin_map_tests.cpp +1451 -0
- package/robin-map/tests/robin_set_tests.cpp +164 -0
- package/robin-map/tests/utils.h +443 -0
- package/robin-map/tsl-robin-map.natvis +78 -0
- package/setup.py +4 -2
- package/src/CMakeLists.txt +1 -0
- package/src/punned.hpp +50 -6
- package/src/test.cpp +29 -8
package/src/CMakeLists.txt
CHANGED
|
@@ -69,6 +69,7 @@ include(clipp)
|
|
|
69
69
|
set(USEARCH_PUNNED_INCLUDE_DIRS
|
|
70
70
|
"${CMAKE_CURRENT_SOURCE_DIR}/../include"
|
|
71
71
|
"${CMAKE_CURRENT_SOURCE_DIR}/../fp16/include"
|
|
72
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/../robin-map/include"
|
|
72
73
|
"${CMAKE_CURRENT_SOURCE_DIR}/../simsimd/include"
|
|
73
74
|
"${CMAKE_CURRENT_SOURCE_DIR}/"
|
|
74
75
|
)
|
package/src/punned.hpp
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
#include <stdlib.h> // `aligned_alloc`
|
|
3
3
|
|
|
4
|
-
#include <functional>
|
|
5
|
-
#include <numeric>
|
|
6
|
-
#include <
|
|
7
|
-
#include <
|
|
8
|
-
#include <
|
|
4
|
+
#include <functional> // `std::function`
|
|
5
|
+
#include <numeric> // `std::iota`
|
|
6
|
+
#include <shared_mutex> // `std::shared_mutex`
|
|
7
|
+
#include <stdexcept> // `std::invalid_argument`
|
|
8
|
+
#include <thread> // `std::thread`
|
|
9
|
+
#include <vector> // `std::vector`
|
|
9
10
|
|
|
10
11
|
#include <fp16/fp16.h>
|
|
12
|
+
#include <tsl/robin_map.h>
|
|
11
13
|
|
|
12
14
|
#include <usearch/usearch.hpp>
|
|
13
15
|
|
|
@@ -401,6 +403,8 @@ class punned_gt {
|
|
|
401
403
|
|
|
402
404
|
using member_iterator_t = typename index_t::member_iterator_t;
|
|
403
405
|
using member_citerator_t = typename index_t::member_citerator_t;
|
|
406
|
+
using member_ref_t = typename index_t::member_ref_t;
|
|
407
|
+
using member_cref_t = typename index_t::member_cref_t;
|
|
404
408
|
|
|
405
409
|
std::size_t dimensions_ = 0;
|
|
406
410
|
std::size_t casted_vector_bytes_ = 0;
|
|
@@ -414,6 +418,10 @@ class punned_gt {
|
|
|
414
418
|
cast_t from_f16{};
|
|
415
419
|
cast_t from_f32{};
|
|
416
420
|
cast_t from_f64{};
|
|
421
|
+
cast_t to_f8{};
|
|
422
|
+
cast_t to_f16{};
|
|
423
|
+
cast_t to_f32{};
|
|
424
|
+
cast_t to_f64{};
|
|
417
425
|
} casts_;
|
|
418
426
|
|
|
419
427
|
punned_stateful_metric_t root_metric_;
|
|
@@ -421,6 +429,13 @@ class punned_gt {
|
|
|
421
429
|
mutable std::vector<std::size_t> available_threads_;
|
|
422
430
|
mutable std::mutex available_threads_mutex_;
|
|
423
431
|
|
|
432
|
+
using shared_mutex_t = std::mutex; // TODO: Find an OS-compatible solution
|
|
433
|
+
using shared_lock_t = std::unique_lock<shared_mutex_t>;
|
|
434
|
+
using unique_lock_t = std::unique_lock<shared_mutex_t>;
|
|
435
|
+
|
|
436
|
+
mutable shared_mutex_t lookup_table_mutex_;
|
|
437
|
+
tsl::robin_map<label_t, id_t> lookup_table_;
|
|
438
|
+
|
|
424
439
|
public:
|
|
425
440
|
using search_results_t = typename index_t::search_results_t;
|
|
426
441
|
using add_result_t = typename index_t::add_result_t;
|
|
@@ -511,6 +526,11 @@ class punned_gt {
|
|
|
511
526
|
search_results_t search_around(label_t hint, f32_t const* vector, std::size_t wanted, search_config_t config) const { return search_around_(hint, vector, wanted, config, casts_.from_f32); }
|
|
512
527
|
search_results_t search_around(label_t hint, f64_t const* vector, std::size_t wanted, search_config_t config) const { return search_around_(hint, vector, wanted, config, casts_.from_f64); }
|
|
513
528
|
|
|
529
|
+
void reconstruct(label_t label, f8_bits_t* vector) const { return reconstruct_(label, vector, casts_.to_f8); }
|
|
530
|
+
void reconstruct(label_t label, f16_bits_t* vector) const { return reconstruct_(label, vector, casts_.to_f16); }
|
|
531
|
+
void reconstruct(label_t label, f32_t* vector) const { return reconstruct_(label, vector, casts_.to_f32); }
|
|
532
|
+
void reconstruct(label_t label, f64_t* vector) const { return reconstruct_(label, vector, casts_.to_f64); }
|
|
533
|
+
|
|
514
534
|
static punned_gt ip(std::size_t dimensions, accuracy_t accuracy = accuracy_t::f16_k, config_t config = {}) { return make_(dimensions, accuracy, ip_metric_(dimensions, accuracy), make_casts_(accuracy), config); }
|
|
515
535
|
static punned_gt l2sq(std::size_t dimensions, accuracy_t accuracy = accuracy_t::f16_k, config_t config = {}) { return make_(dimensions, accuracy, l2_metric_(dimensions, accuracy), make_casts_(accuracy), config); }
|
|
516
536
|
static punned_gt cos(std::size_t dimensions, accuracy_t accuracy = accuracy_t::f32_k, config_t config = {}) { return make_(dimensions, accuracy, cos_metric_(dimensions, accuracy), make_casts_(accuracy), config); }
|
|
@@ -589,7 +609,12 @@ class punned_gt {
|
|
|
589
609
|
if (casted)
|
|
590
610
|
vector_data = casted_data, vector_bytes = casted_vector_bytes_, config.store_vector = true;
|
|
591
611
|
|
|
592
|
-
|
|
612
|
+
add_result_t result = typed_->add(label, {vector_data, vector_bytes}, config);
|
|
613
|
+
{
|
|
614
|
+
unique_lock_t lock(lookup_table_mutex_);
|
|
615
|
+
lookup_table_.emplace(label, result.id);
|
|
616
|
+
}
|
|
617
|
+
return result;
|
|
593
618
|
}
|
|
594
619
|
|
|
595
620
|
template <typename scalar_at>
|
|
@@ -624,6 +649,21 @@ class punned_gt {
|
|
|
624
649
|
return typed_->search_around(static_cast<id_t>(hint), {vector_data, vector_bytes}, wanted, config);
|
|
625
650
|
}
|
|
626
651
|
|
|
652
|
+
id_t lookup_id_(label_t label) const {
|
|
653
|
+
shared_lock_t lock(lookup_table_mutex_);
|
|
654
|
+
return lookup_table_.at(label);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
template <typename scalar_at> void reconstruct_(label_t label, scalar_at* reconstructed, cast_t const& cast) const {
|
|
658
|
+
id_t id = lookup_id_(label);
|
|
659
|
+
member_citerator_t iterator = typed_->cbegin() + id;
|
|
660
|
+
member_cref_t member = *iterator;
|
|
661
|
+
byte_t const* casted_vector = reinterpret_cast<byte_t const*>(member.vector.data());
|
|
662
|
+
bool casted = cast(casted_vector, casted_vector_bytes_, (byte_t*)reconstructed);
|
|
663
|
+
if (!casted)
|
|
664
|
+
std::memcpy(reconstructed, casted_vector, casted_vector_bytes_);
|
|
665
|
+
}
|
|
666
|
+
|
|
627
667
|
template <typename scalar_at> add_result_t add_(label_t label, scalar_at const* vector, cast_t const& cast) {
|
|
628
668
|
thread_lock_t lock = thread_lock_();
|
|
629
669
|
add_config_t add_config;
|
|
@@ -686,6 +726,10 @@ class punned_gt {
|
|
|
686
726
|
result.from_f16 = cast_gt<f16_bits_t, to_scalar_at>{};
|
|
687
727
|
result.from_f32 = cast_gt<f32_t, to_scalar_at>{};
|
|
688
728
|
result.from_f64 = cast_gt<f64_t, to_scalar_at>{};
|
|
729
|
+
result.to_f8 = cast_gt<to_scalar_at, f8_bits_t>{};
|
|
730
|
+
result.to_f16 = cast_gt<to_scalar_at, f16_bits_t>{};
|
|
731
|
+
result.to_f32 = cast_gt<to_scalar_at, f32_t>{};
|
|
732
|
+
result.to_f64 = cast_gt<to_scalar_at, f64_t>{};
|
|
689
733
|
return result;
|
|
690
734
|
}
|
|
691
735
|
|
package/src/test.cpp
CHANGED
|
@@ -12,7 +12,7 @@ using namespace unum;
|
|
|
12
12
|
using point_id_t = std::int64_t;
|
|
13
13
|
|
|
14
14
|
template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
15
|
-
using
|
|
15
|
+
using view_t = span_gt<scalar_at const>;
|
|
16
16
|
using distance_t = typename index_at::distance_t;
|
|
17
17
|
|
|
18
18
|
scalar_at vec[3] = {10, 20, 15};
|
|
@@ -20,12 +20,12 @@ template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
|
20
20
|
scalar_at vec_b[3] = {16, 17, 18};
|
|
21
21
|
|
|
22
22
|
index.reserve(10);
|
|
23
|
-
index.add(42,
|
|
23
|
+
index.add(42, view_t{&vec[0], 3ul});
|
|
24
24
|
|
|
25
25
|
// Default approximate search
|
|
26
26
|
point_id_t matched_labels[10] = {0};
|
|
27
27
|
distance_t matched_distances[10] = {0};
|
|
28
|
-
std::size_t matched_count = index.search(
|
|
28
|
+
std::size_t matched_count = index.search(view_t{&vec[0], 3ul}, 5).dump_to(matched_labels, matched_distances);
|
|
29
29
|
|
|
30
30
|
assert(matched_count == 1);
|
|
31
31
|
assert(matched_labels[0] == 42);
|
|
@@ -34,12 +34,12 @@ template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
|
34
34
|
// Add more entries
|
|
35
35
|
search_config_t search_config;
|
|
36
36
|
search_config.exact = true;
|
|
37
|
-
index.add(43,
|
|
38
|
-
index.add(44,
|
|
37
|
+
index.add(43, view_t{&vec_a[0], 3ul});
|
|
38
|
+
index.add(44, view_t{&vec_b[0], 3ul});
|
|
39
39
|
assert(index.size() == 3);
|
|
40
40
|
|
|
41
41
|
// Perform exact search
|
|
42
|
-
matched_count = index.search(
|
|
42
|
+
matched_count = index.search(view_t{&vec[0], 3ul}, 5, search_config).dump_to(matched_labels, matched_distances);
|
|
43
43
|
|
|
44
44
|
// Validate scans
|
|
45
45
|
std::size_t count = 0;
|
|
@@ -54,14 +54,14 @@ template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
|
54
54
|
// Search again over reconstructed index
|
|
55
55
|
index.save("tmp.usearch");
|
|
56
56
|
index.load("tmp.usearch");
|
|
57
|
-
matched_count = index.search(
|
|
57
|
+
matched_count = index.search(view_t{&vec[0], 3ul}, 5).dump_to(matched_labels, matched_distances);
|
|
58
58
|
assert(matched_count == 3);
|
|
59
59
|
assert(matched_labels[0] == 42);
|
|
60
60
|
assert(std::abs(matched_distances[0]) < 0.01);
|
|
61
61
|
|
|
62
62
|
// Search again over mapped index
|
|
63
63
|
index.view("tmp.usearch");
|
|
64
|
-
matched_count = index.search(
|
|
64
|
+
matched_count = index.search(view_t{&vec[0], 3ul}, 5).dump_to(matched_labels, matched_distances);
|
|
65
65
|
assert(matched_count == 3);
|
|
66
66
|
assert(matched_labels[0] == 42);
|
|
67
67
|
assert(std::abs(matched_distances[0]) < 0.01);
|
|
@@ -70,6 +70,24 @@ template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
|
|
|
70
70
|
assert(index.stats().max_edges > 0);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
template <typename scalar_at, typename index_at> void test3d_punned(index_at&& index) {
|
|
74
|
+
using view_t = span_gt<scalar_at const>;
|
|
75
|
+
using span_t = span_gt<scalar_at>;
|
|
76
|
+
using distance_t = typename index_at::distance_t;
|
|
77
|
+
|
|
78
|
+
scalar_at vec[3] = {10, 20, 15};
|
|
79
|
+
|
|
80
|
+
index.reserve(10);
|
|
81
|
+
index.add(42, view_t{&vec[0], 3ul});
|
|
82
|
+
|
|
83
|
+
// Reconstruct
|
|
84
|
+
scalar_at vec_reconstructed[3] = {0, 0, 0};
|
|
85
|
+
index.reconstruct(42, span_t{&vec_reconstructed[0], 3ul});
|
|
86
|
+
assert(vec_reconstructed[0] == vec[0]);
|
|
87
|
+
assert(vec_reconstructed[1] == vec[1]);
|
|
88
|
+
assert(vec_reconstructed[2] == vec[2]);
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
int main(int, char**) {
|
|
74
92
|
|
|
75
93
|
test3d<float>(index_gt<cos_gt<float>, point_id_t, std::uint32_t, float>{});
|
|
@@ -84,5 +102,8 @@ int main(int, char**) {
|
|
|
84
102
|
test3d<double>(punned_small_t::cos(3));
|
|
85
103
|
test3d<double>(punned_small_t::l2sq(3));
|
|
86
104
|
|
|
105
|
+
test3d_punned<float>(punned_small_t::cos(3));
|
|
106
|
+
test3d_punned<float>(punned_small_t::l2sq(3));
|
|
107
|
+
|
|
87
108
|
return 0;
|
|
88
109
|
}
|