usearch 2.6.0 → 2.7.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/. npmignore +14 -0
- package/.cmake-format.py +19 -0
- package/.github/workflows/Dockerfile.libs +2 -2
- package/.github/workflows/prerelease.yml +85 -64
- package/.github/workflows/release.yml +24 -15
- package/.gitignore +1 -1
- package/.vscode/launch.json +47 -14
- package/.vscode/settings.json +7 -0
- package/.vscode/tasks.json +44 -8
- package/CITATION.cff +1 -1
- package/CMakeLists.txt +218 -67
- package/Cargo.toml +1 -1
- package/README.md +1 -1
- package/binding.gyp +3 -2
- package/build.gradle +19 -10
- package/c/CMakeLists.txt +21 -48
- package/c/README.md +5 -5
- package/c/lib.cpp +52 -7
- package/c/test.c +137 -94
- package/c/usearch.h +42 -0
- package/cmake/clipp.cmake +0 -1
- package/cmake/jemalloc.cmake +21 -37
- package/conanfile.py +1 -1
- package/cpp/CMakeLists.txt +14 -123
- package/cpp/README.md +26 -22
- package/cpp/bench.cpp +0 -12
- package/cpp/test.cpp +29 -1
- package/csharp/nuget/nuget-package.props +1 -1
- package/docs/compilation.md +23 -16
- package/docs/conf.py +1 -1
- package/golang/README.md +52 -51
- package/golang/lib.go +1 -1
- package/golang/lib_test.go +4 -1
- package/include/usearch/index.hpp +2 -2
- package/include/usearch/index_plugins.hpp +345 -160
- package/javascript/lib.cpp +204 -250
- package/javascript/usearch.js +440 -2
- package/javascript/usearch.test.js +37 -0
- package/package.json +10 -5
- package/python/lib.cpp +95 -224
- package/python/scripts/bench_exact.py +2 -2
- package/python/scripts/test_jit.py +2 -13
- package/python/scripts/test_sparse.py +1 -1
- package/python/scripts/test_tooling.py +15 -5
- package/rust/lib.cpp +7 -4
- package/rust/lib.hpp +2 -0
- package/rust/lib.rs +128 -8
- package/setup.py +14 -4
- package/wasm/CMakeLists.txt +4 -12
- package/wasm/lib.cpp +1 -1
- package/wasmer.toml +1 -1
- package/javascript/docs.js +0 -111
- package/javascript/test.js +0 -32
- package/javascript/usearch.d.ts +0 -110
- package/tsconfig.json +0 -8
package/cpp/CMakeLists.txt
CHANGED
|
@@ -1,123 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
|
16
|
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
|
|
17
|
-
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -g")
|
|
18
|
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=leak -fsanitize=alignment -fsanitize=undefined")
|
|
19
|
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wno-conversion -Wno-unknown-pragmas")
|
|
20
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
|
|
21
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmax-errors=1")
|
|
22
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
|
23
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
|
|
24
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftime-report")
|
|
25
|
-
|
|
26
|
-
if(${USEARCH_USE_OPENMP})
|
|
27
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
|
|
28
|
-
endif()
|
|
29
|
-
|
|
30
|
-
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
31
|
-
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
|
32
|
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
|
|
33
|
-
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -g")
|
|
34
|
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=leak -fsanitize=alignment -fsanitize=undefined")
|
|
35
|
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wfatal-errors")
|
|
36
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
|
37
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
|
|
38
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftime-trace")
|
|
39
|
-
|
|
40
|
-
if(${USEARCH_USE_OPENMP})
|
|
41
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
|
|
42
|
-
endif()
|
|
43
|
-
|
|
44
|
-
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "NVIDIA" OR CMAKE_CXX_COMPILER_ID STREQUAL "NVHPC")
|
|
45
|
-
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
|
46
|
-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr --extended-lambda")
|
|
47
|
-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode arch=compute_86,code=sm_86")
|
|
48
|
-
set_property(SOURCE bench.cpp PROPERTY LANGUAGE CUDA)
|
|
49
|
-
set_target_properties(bench PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
|
50
|
-
set_target_properties(bench PROPERTIES CUDA_ARCHITECTURES "86")
|
|
51
|
-
|
|
52
|
-
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
|
|
53
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w")
|
|
54
|
-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ferror-limit=1")
|
|
55
|
-
|
|
56
|
-
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
|
57
|
-
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DEBUG")
|
|
58
|
-
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2")
|
|
59
|
-
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /O2 /DEBUG")
|
|
60
|
-
endif()
|
|
61
|
-
|
|
62
|
-
if(APPLE)
|
|
63
|
-
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
|
64
|
-
set(CMAKE_HAVE_THREADS_LIBRARY 1)
|
|
65
|
-
set(CMAKE_USE_WIN32_THREADS_INIT 0)
|
|
66
|
-
set(CMAKE_USE_PTHREADS_INIT 1)
|
|
67
|
-
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
|
68
|
-
endif()
|
|
69
|
-
|
|
70
|
-
find_package(Threads REQUIRED)
|
|
71
|
-
|
|
72
|
-
if(${USEARCH_USE_OPENMP})
|
|
73
|
-
find_package(OpenMP REQUIRED)
|
|
74
|
-
include_directories(${OPENMP_INCLUDE_DIRS})
|
|
75
|
-
endif()
|
|
76
|
-
|
|
77
|
-
if(${USEARCH_USE_JEMALLOC})
|
|
78
|
-
include(jemalloc)
|
|
79
|
-
endif()
|
|
80
|
-
|
|
81
|
-
include(clipp)
|
|
82
|
-
|
|
83
|
-
set(USEARCH_PUNNED_INCLUDE_DIRS
|
|
84
|
-
"${CMAKE_CURRENT_SOURCE_DIR}/../include"
|
|
85
|
-
"${CMAKE_CURRENT_SOURCE_DIR}/../fp16/include"
|
|
86
|
-
"${CMAKE_CURRENT_SOURCE_DIR}/../simsimd/include"
|
|
87
|
-
"${CMAKE_CURRENT_SOURCE_DIR}/"
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
if(${USEARCH_BUILD_TEST})
|
|
91
|
-
add_executable(test test.cpp)
|
|
92
|
-
target_link_libraries(test PRIVATE Threads::Threads)
|
|
93
|
-
target_include_directories(test PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
|
|
94
|
-
set_target_properties(test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|
95
|
-
set_target_properties(test PROPERTIES CXX_STANDARD 17)
|
|
96
|
-
|
|
97
|
-
if(${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)
|
|
98
|
-
include(CTest)
|
|
99
|
-
enable_testing()
|
|
100
|
-
add_test(NAME test COMMAND test)
|
|
101
|
-
endif()
|
|
102
|
-
endif()
|
|
103
|
-
|
|
104
|
-
if(${USEARCH_BUILD_BENCHMARK})
|
|
105
|
-
add_executable(bench bench.cpp)
|
|
106
|
-
target_link_libraries(bench PRIVATE Threads::Threads)
|
|
107
|
-
target_include_directories(bench PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
|
|
108
|
-
set_target_properties(bench PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|
109
|
-
set_target_properties(bench PROPERTIES CXX_STANDARD 17)
|
|
110
|
-
|
|
111
|
-
if(${USEARCH_USE_SIMSIMD})
|
|
112
|
-
target_compile_definitions(bench PRIVATE USEARCH_USE_SIMSIMD=1)
|
|
113
|
-
endif()
|
|
114
|
-
|
|
115
|
-
if(${USEARCH_USE_OPENMP})
|
|
116
|
-
target_compile_definitions(bench PRIVATE USEARCH_USE_OPENMP=1)
|
|
117
|
-
target_link_libraries(bench PRIVATE ${OPENMP_LIBRARIES})
|
|
118
|
-
endif()
|
|
119
|
-
|
|
120
|
-
if(${USEARCH_USE_JEMALLOC})
|
|
121
|
-
target_link_libraries(bench PRIVATE ${JEMALLOC_LIBRARIES})
|
|
122
|
-
endif()
|
|
123
|
-
endif()
|
|
1
|
+
if (USEARCH_BUILD_TEST_CPP)
|
|
2
|
+
add_executable(test_cpp test.cpp)
|
|
3
|
+
setup_target(test_cpp)
|
|
4
|
+
include(CTest)
|
|
5
|
+
enable_testing()
|
|
6
|
+
add_test(NAME test_cpp COMMAND test_cpp)
|
|
7
|
+
endif ()
|
|
8
|
+
|
|
9
|
+
if (USEARCH_BUILD_BENCH_CPP)
|
|
10
|
+
include(clipp)
|
|
11
|
+
add_executable(bench_cpp bench.cpp)
|
|
12
|
+
setup_target(bench_cpp)
|
|
13
|
+
target_include_directories(bench_cpp PRIVATE ${clipp_SOURCE_DIR}/include)
|
|
14
|
+
endif ()
|
package/cpp/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## Installation
|
|
4
4
|
|
|
5
|
-
To use in a C++ project
|
|
6
|
-
Alternatively fetch it with CMake:
|
|
5
|
+
To use in a C++ project, copy the `include/usearch/*` headers into your project.
|
|
6
|
+
Alternatively, fetch it with CMake:
|
|
7
7
|
|
|
8
8
|
```cmake
|
|
9
9
|
FetchContent_Declare(usearch GIT_REPOSITORY https://github.com/unum-cloud/usearch.git)
|
|
@@ -12,13 +12,17 @@ FetchContent_MakeAvailable(usearch)
|
|
|
12
12
|
|
|
13
13
|
## Quickstart
|
|
14
14
|
|
|
15
|
-
Once included, the
|
|
16
|
-
This covers 90% of use
|
|
15
|
+
Once included, the high-level C++11 interface is as simple as it gets: `reserve()`, `add()`, `search()`, `size()`, `capacity()`, `save()`, `load()`, `view()`.
|
|
16
|
+
This covers 90% of use cases.
|
|
17
17
|
|
|
18
|
-
```
|
|
18
|
+
```cpp
|
|
19
19
|
using namespace unum::usearch;
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
metric_punned_t metric(256, metric_kind_t::l2sq_k, scalar_kind_t::f32_k);
|
|
22
|
+
|
|
23
|
+
// If you plan to store more than 4 Billion entries - use `index_dense_big_t`.
|
|
24
|
+
// Or directly instantiate the template variant you need - `index_dense_gt<key_t, internal_id_t>`.
|
|
25
|
+
index_dense_t index = index_dense_t::make(metric);
|
|
22
26
|
float vec[3] = {0.1, 0.3, 0.2};
|
|
23
27
|
|
|
24
28
|
index.reserve(10);
|
|
@@ -30,10 +34,19 @@ for (std::size_t i = 0; i != results.size(); ++i)
|
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
The `add` is thread-safe for concurrent index construction.
|
|
37
|
+
It also has an overload for different vector types, casting them under the hood.
|
|
38
|
+
The same applies to the `search`, `get`, `cluster`, and `distance_between` functions.
|
|
39
|
+
|
|
40
|
+
```cpp
|
|
41
|
+
double vec_double[3] = {0.1, 0.3, 0.2};
|
|
42
|
+
_Float16 vec_half[3] = {0.1, 0.3, 0.2};
|
|
43
|
+
index.add(43, {&vec_double[0], 3});
|
|
44
|
+
index.add(44, {&vec_half[0], 3});
|
|
45
|
+
```
|
|
33
46
|
|
|
34
47
|
## Serialization
|
|
35
48
|
|
|
36
|
-
```
|
|
49
|
+
```cpp
|
|
37
50
|
index.save("index.usearch");
|
|
38
51
|
index.load("index.usearch"); // Copying from disk
|
|
39
52
|
index.view("index.usearch"); // Memory-mapping from disk
|
|
@@ -44,23 +57,14 @@ index.view("index.usearch"); // Memory-mapping from disk
|
|
|
44
57
|
For advanced users, more compile-time abstractions are available.
|
|
45
58
|
|
|
46
59
|
```cpp
|
|
47
|
-
template <typename
|
|
48
|
-
typename key_at =
|
|
49
|
-
typename
|
|
50
|
-
typename
|
|
51
|
-
typename
|
|
60
|
+
template <typename distance_at = default_distance_t, // `float`
|
|
61
|
+
typename key_at = default_key_t, // `int64_t`, `uuid_t`
|
|
62
|
+
typename compressed_slot_at = default_slot_t, // `uint32_t`, `uint40_t`
|
|
63
|
+
typename dynamic_allocator_at = std::allocator<byte_t>, //
|
|
64
|
+
typename tape_allocator_at = dynamic_allocator_at> //
|
|
52
65
|
class index_gt;
|
|
53
66
|
```
|
|
54
67
|
|
|
55
|
-
You may want to use a custom memory allocator or a rare scalar type, but most often, you would start by defining a custom similarity measure.
|
|
56
|
-
The function object should have the following signature to support different-length vectors.
|
|
57
|
-
|
|
58
|
-
```cpp
|
|
59
|
-
struct custom_metric_t {
|
|
60
|
-
T operator()(T const* a, T const* b, std::size_t a_length, std::size_t b_length) const;
|
|
61
|
-
};
|
|
62
|
-
```
|
|
63
|
-
|
|
64
68
|
The following distances are pre-packaged:
|
|
65
69
|
|
|
66
70
|
- `metric_cos_gt<scalar_t>` for "Cosine" or "Angular" distance.
|
|
@@ -81,7 +85,7 @@ Instead of spawning additional threads within USearch, we focus on the thread sa
|
|
|
81
85
|
```cpp
|
|
82
86
|
#pragma omp parallel for
|
|
83
87
|
for (std::size_t i = 0; i < n; ++i)
|
|
84
|
-
native.add(key, span_t{vector, dims}
|
|
88
|
+
native.add(key, span_t{vector, dims});
|
|
85
89
|
```
|
|
86
90
|
|
|
87
91
|
During initialization, we allocate enough temporary memory for all the cores on the machine.
|
package/cpp/bench.cpp
CHANGED
|
@@ -135,18 +135,6 @@ struct alignas(32) persisted_matrix_gt {
|
|
|
135
135
|
std::size_t size_bytes() const noexcept { return rows * row_size_bytes(); }
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
-
template <typename scalar_at> //
|
|
139
|
-
struct vectors_view_gt {
|
|
140
|
-
using scalar_t = scalar_at;
|
|
141
|
-
|
|
142
|
-
scalar_t const* begin_{};
|
|
143
|
-
std::size_t count_{};
|
|
144
|
-
std::size_t stride_{};
|
|
145
|
-
|
|
146
|
-
std::size_t size() const noexcept { return count_; }
|
|
147
|
-
scalar_t const* at(std::size_t i) const noexcept { return begin_ + i * stride_; }
|
|
148
|
-
};
|
|
149
|
-
|
|
150
138
|
template <typename scalar_at, typename vector_id_at> //
|
|
151
139
|
struct persisted_dataset_gt {
|
|
152
140
|
using scalar_t = scalar_at;
|
package/cpp/test.cpp
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @brief A trivial test.
|
|
3
3
|
*/
|
|
4
|
-
#include <algorithm>
|
|
4
|
+
#include <algorithm> // `std::shuffle`
|
|
5
|
+
#include <cassert> // `assert`
|
|
6
|
+
#include <random> // `std::default_random_engine`
|
|
5
7
|
#include <stdexcept>
|
|
6
8
|
#include <unordered_map>
|
|
9
|
+
#include <vector> // for std::vector
|
|
7
10
|
|
|
8
11
|
#include <usearch/index.hpp>
|
|
9
12
|
#include <usearch/index_dense.hpp>
|
|
@@ -234,6 +237,26 @@ template <typename key_at, typename slot_at> void test_tanimoto(std::size_t dime
|
|
|
234
237
|
});
|
|
235
238
|
}
|
|
236
239
|
|
|
240
|
+
void test_exact_search(std::size_t dataset_count, std::size_t queries_count, std::size_t wanted_count) {
|
|
241
|
+
std::size_t dimensions = 10;
|
|
242
|
+
metric_punned_t metric(dimensions, metric_kind_t::cos_k);
|
|
243
|
+
|
|
244
|
+
std::random_device rd;
|
|
245
|
+
std::mt19937 gen(rd());
|
|
246
|
+
std::uniform_real_distribution<> dis(0.0, 1.0);
|
|
247
|
+
std::vector<float> dataset(dataset_count * dimensions);
|
|
248
|
+
std::generate(dataset.begin(), dataset.end(), [&] { return dis(gen); });
|
|
249
|
+
|
|
250
|
+
exact_search_t search;
|
|
251
|
+
auto results = search( //
|
|
252
|
+
(byte_t const*)dataset.data(), dataset_count, dimensions * sizeof(float), //
|
|
253
|
+
(byte_t const*)dataset.data(), queries_count, dimensions * sizeof(float), //
|
|
254
|
+
wanted_count, metric);
|
|
255
|
+
|
|
256
|
+
for (std::size_t i = 0; i < results.size(); ++i)
|
|
257
|
+
assert(results.at(i)[0].offset == i); // Validate the top match
|
|
258
|
+
}
|
|
259
|
+
|
|
237
260
|
template <typename index_at> void test_sets(index_at&& index) {
|
|
238
261
|
|
|
239
262
|
using index_t = typename std::remove_reference<index_at>::type;
|
|
@@ -272,6 +295,11 @@ template <typename index_at> void test_sets_moved(index_config_t const& config)
|
|
|
272
295
|
|
|
273
296
|
int main(int, char**) {
|
|
274
297
|
|
|
298
|
+
for (std::size_t dataset_count : {10, 100})
|
|
299
|
+
for (std::size_t queries_count : {1, 10})
|
|
300
|
+
for (std::size_t wanted_count : {1, 5})
|
|
301
|
+
test_exact_search(dataset_count, queries_count, wanted_count);
|
|
302
|
+
|
|
275
303
|
for (std::size_t collection_size : {10, 500})
|
|
276
304
|
for (std::size_t dimensions : {97, 256}) {
|
|
277
305
|
std::printf("Indexing %zu vectors with cos: <float, std::int64_t, std::uint32_t> \n", collection_size);
|
package/docs/compilation.md
CHANGED
|
@@ -13,15 +13,16 @@ Linux:
|
|
|
13
13
|
|
|
14
14
|
```sh
|
|
15
15
|
sudo apt-get update
|
|
16
|
-
sudo apt-get install cmake
|
|
16
|
+
sudo apt-get install cmake build-essential libjemalloc-dev
|
|
17
17
|
cmake -B ./build_release \
|
|
18
|
-
-DCMAKE_CXX_COMPILER="g++-12" \
|
|
19
18
|
-DCMAKE_BUILD_TYPE=Release \
|
|
20
|
-
-DUSEARCH_BUILD_TEST=1 \
|
|
21
19
|
-DUSEARCH_USE_OPENMP=1 \
|
|
22
20
|
-DUSEARCH_USE_SIMSIMD=1 \
|
|
23
21
|
-DUSEARCH_USE_JEMALLOC=1 \
|
|
24
|
-
-
|
|
22
|
+
-DUSEARCH_BUILD_TEST_CPP=1 \
|
|
23
|
+
-DUSEARCH_BUILD_BENCH_CPP=1 \
|
|
24
|
+
-DUSEARCH_BUILD_LIB_C=1 \
|
|
25
|
+
-DUSEARCH_BUILD_TEST_C=1 \
|
|
25
26
|
&& \
|
|
26
27
|
make -C ./build_release -j
|
|
27
28
|
```
|
|
@@ -35,8 +36,8 @@ cmake -B ./build_release \
|
|
|
35
36
|
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
|
|
36
37
|
-DUSEARCH_USE_OPENMP=1 \
|
|
37
38
|
-DUSEARCH_USE_SIMSIMD=1 \
|
|
38
|
-
-
|
|
39
|
-
-
|
|
39
|
+
-DUSEARCH_BUILD_BENCH_CPP=1 \
|
|
40
|
+
-DUSEARCH_BUILD_TEST_CPP=1 \
|
|
40
41
|
&& \
|
|
41
42
|
make -C ./build_release -j
|
|
42
43
|
```
|
|
@@ -53,7 +54,9 @@ cppcheck --enable=all --force --suppress=cstyleCast --suppress=unusedFunction \
|
|
|
53
54
|
Testing:
|
|
54
55
|
|
|
55
56
|
```sh
|
|
56
|
-
cmake -
|
|
57
|
+
cmake -DUSEARCH_BUILD_TEST_CPP=1 -B ./build_debug
|
|
58
|
+
cmake --build ./build_debug --config Debug
|
|
59
|
+
./build_debug/test_cpp
|
|
57
60
|
```
|
|
58
61
|
|
|
59
62
|
## Python 3
|
|
@@ -85,7 +88,7 @@ cibuildwheel --platform linux
|
|
|
85
88
|
Node.JS:
|
|
86
89
|
|
|
87
90
|
```sh
|
|
88
|
-
npm install && node javascript/test.js
|
|
91
|
+
npm install && node --test ./javascript/usearch.test.js
|
|
89
92
|
npm publish
|
|
90
93
|
```
|
|
91
94
|
|
|
@@ -93,7 +96,7 @@ WebAssembly:
|
|
|
93
96
|
|
|
94
97
|
```sh
|
|
95
98
|
emcmake cmake -B ./build -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -s TOTAL_MEMORY=64MB" && emmake make -C ./build
|
|
96
|
-
node ./build/test.js
|
|
99
|
+
node ./build/usearch.test.js
|
|
97
100
|
```
|
|
98
101
|
|
|
99
102
|
If you don't yet have `emcmake` installed:
|
|
@@ -124,7 +127,7 @@ javac -h . Index.java
|
|
|
124
127
|
|
|
125
128
|
# Ubuntu:
|
|
126
129
|
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
127
|
-
g++ -shared -fPIC -o
|
|
130
|
+
g++ -shared -fPIC -o libusearch_c.so cloud_unum_usearch_Index.o -lc
|
|
128
131
|
|
|
129
132
|
# Windows
|
|
130
133
|
g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
|
|
@@ -152,22 +155,26 @@ swift test -v
|
|
|
152
155
|
## C 99
|
|
153
156
|
|
|
154
157
|
There are a few ways to compile the C 99 USearch SDK.
|
|
155
|
-
Using the Makefile:
|
|
158
|
+
Using the Makefile, specifying the targets you need:
|
|
156
159
|
|
|
157
160
|
```sh
|
|
158
161
|
make -C ./c libusearch_c.so
|
|
159
162
|
```
|
|
160
163
|
|
|
161
|
-
|
|
164
|
+
With options:
|
|
162
165
|
|
|
163
166
|
```sh
|
|
164
|
-
|
|
167
|
+
make USEARCH_USE_OPENMP=1 USEARCH_USE_SIMSIMD=1 -C ./c libusearch_c.so
|
|
165
168
|
```
|
|
166
169
|
|
|
167
|
-
|
|
170
|
+
Using CMake:
|
|
168
171
|
|
|
169
172
|
```sh
|
|
170
|
-
|
|
173
|
+
cmake -B ./build_release -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_BUILD_TEST_C=1 -DUSEARCH_USE_OPENMP=1 -DUSEARCH_USE_SIMSIMD=1
|
|
174
|
+
cmake --build ./build_release --config Release -j
|
|
175
|
+
./build_release/test_c
|
|
176
|
+
# On Windows:
|
|
177
|
+
.\build_release\test_c.exe
|
|
171
178
|
```
|
|
172
179
|
|
|
173
180
|
|
|
@@ -177,7 +184,7 @@ GoLang bindings are based on C.
|
|
|
177
184
|
So one should first compile the C library, link it with GoLang, and only then run tests.
|
|
178
185
|
|
|
179
186
|
```sh
|
|
180
|
-
make -C ./c libusearch_c.so && mv ./c/libusearch_c.so ./golang/
|
|
187
|
+
make -C ./c libusearch_c.so && mv ./c/libusearch_c.so ./golang/ && cp ./c/usearch.h ./golang/
|
|
181
188
|
cd golang && go test -v ; cd ..
|
|
182
189
|
```
|
|
183
190
|
|
package/docs/conf.py
CHANGED
package/golang/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
Download and install from the Debian package from the latest release.
|
|
8
8
|
Substitute `<release_tag>`, `<arch>`, and `<usearch_version>` with your settings.
|
|
9
9
|
|
|
10
|
-
```
|
|
10
|
+
```sh
|
|
11
11
|
wget https://github.com/unum-cloud/usearch/releases/download/<release_tag>/usearch_linux_<arch>_<usearch_version>.deb
|
|
12
12
|
dpkg -i usearch_<arch>_<usearch_version>.deb
|
|
13
13
|
```
|
|
@@ -17,7 +17,7 @@ dpkg -i usearch_<arch>_<usearch_version>.deb
|
|
|
17
17
|
Run a `winlibinstaller.bat` script from the main repository in the folder where you will run `go run`.
|
|
18
18
|
That will install the USearch library and include in the same folder` where the script was run.
|
|
19
19
|
|
|
20
|
-
```
|
|
20
|
+
```sh
|
|
21
21
|
.\usearch\winlibinstaller.bat
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -25,10 +25,11 @@ That will install the USearch library and include in the same folder` where the
|
|
|
25
25
|
|
|
26
26
|
Download and unpack a zip archive from the latest release.
|
|
27
27
|
Move the USearch library and the include file to their respective folders.
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
```sh
|
|
29
30
|
wget https://github.com/unum-cloud/usearch/releases/download/<release_tag>/usearch_macOS_<arch>_<usearch_version>.zip
|
|
30
31
|
unzip usearch_macOS_<arch>_<usearch_version>.zip
|
|
31
|
-
sudo mv
|
|
32
|
+
sudo mv libusearch_c.so /usr/local/lib && sudo mv usearch.h /usr/local/include
|
|
32
33
|
|
|
33
34
|
```
|
|
34
35
|
|
|
@@ -36,60 +37,60 @@ sudo mv libusearch.so /usr/local/lib && sudo mv usearch.h /usr/local/include
|
|
|
36
37
|
|
|
37
38
|
1. Create a `go.mod` file:
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
```
|
|
41
|
+
module usearch_example
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
go <go_version>
|
|
44
|
+
```
|
|
44
45
|
|
|
45
46
|
2. Create an `example.go`:
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
48
|
+
```golang
|
|
49
|
+
package main
|
|
50
|
+
|
|
51
|
+
import (
|
|
52
|
+
"fmt"
|
|
53
|
+
usearch "github.com/unum-cloud/usearch/golang"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
func main() {
|
|
57
|
+
|
|
58
|
+
// Create Index
|
|
59
|
+
vector_size := 3
|
|
60
|
+
vectors_count := 100
|
|
61
|
+
conf := usearch.DefaultConfig(uint(vector_size))
|
|
62
|
+
index,err := usearch.NewIndex(conf)
|
|
63
|
+
if err != nil {
|
|
64
|
+
panic("Failed to create Index")
|
|
65
|
+
}
|
|
66
|
+
defer index.Destroy()
|
|
67
|
+
|
|
68
|
+
// Add to Index
|
|
69
|
+
err = index.Reserve(uint(vectors_count))
|
|
70
|
+
for i := 0; i < vectors_count; i++ {
|
|
71
|
+
err = index.Add(usearch.Key(i), []float32{float32(i), float32(i+1), float32(i+2)})
|
|
72
|
+
if err != nil {
|
|
73
|
+
panic("Failed to add")
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Search
|
|
78
|
+
keys, distances, err := index.Search([]float32{0.0, 1.0, 2.0}, 3)
|
|
79
|
+
if err != nil {
|
|
80
|
+
panic("Failed to search")
|
|
81
|
+
}
|
|
82
|
+
fmt.Println(keys, distances)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
84
85
|
|
|
85
86
|
3. Get USearch:
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
```sh
|
|
89
|
+
go get github.com/unum-cloud/usearch/golang
|
|
90
|
+
```
|
|
90
91
|
|
|
91
92
|
4. Run:
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
```sh
|
|
95
|
+
go run example.go
|
|
96
|
+
```
|
package/golang/lib.go
CHANGED
package/golang/lib_test.go
CHANGED
|
@@ -3,6 +3,7 @@ package usearch
|
|
|
3
3
|
import (
|
|
4
4
|
"runtime"
|
|
5
5
|
"testing"
|
|
6
|
+
"math"
|
|
6
7
|
)
|
|
7
8
|
|
|
8
9
|
func TestUSearch(t *testing.T) {
|
|
@@ -98,7 +99,9 @@ func TestUSearch(t *testing.T) {
|
|
|
98
99
|
if err != nil {
|
|
99
100
|
t.Fatalf("Failed to search: %s", err)
|
|
100
101
|
}
|
|
101
|
-
|
|
102
|
+
|
|
103
|
+
const tolerance = 1e-2 // For example, this sets the tolerance to 0.01
|
|
104
|
+
if keys[0] != 42 || math.Abs(float64(distances[0])) > tolerance {
|
|
102
105
|
t.Fatalf("Expected result 42 with distance 0, got key %d with distance %f", keys[0], distances[0])
|
|
103
106
|
}
|
|
104
107
|
})
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
#define UNUM_USEARCH_HPP
|
|
11
11
|
|
|
12
12
|
#define USEARCH_VERSION_MAJOR 2
|
|
13
|
-
#define USEARCH_VERSION_MINOR
|
|
13
|
+
#define USEARCH_VERSION_MINOR 7
|
|
14
14
|
#define USEARCH_VERSION_PATCH 0
|
|
15
15
|
|
|
16
16
|
// Inferring C++ version
|
|
@@ -268,7 +268,7 @@ template <typename scalar_at> class span_gt {
|
|
|
268
268
|
* @brief Similar to `std::vector`, but doesn't support dynamic resizing.
|
|
269
269
|
* On the bright side, this can't throw exceptions.
|
|
270
270
|
*/
|
|
271
|
-
template <typename scalar_at, typename allocator_at
|
|
271
|
+
template <typename scalar_at, typename allocator_at = std::allocator<scalar_at>> class buffer_gt {
|
|
272
272
|
scalar_at* data_;
|
|
273
273
|
std::size_t size_;
|
|
274
274
|
|