usearch 2.8.16 → 2.9.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/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
- package/.github/workflows/prerelease.yml +33 -7
- package/.github/workflows/release.yml +25 -26
- package/.gitmodules +4 -1
- package/CITATION.cff +1 -1
- package/CMakeLists.txt +6 -8
- package/CONTRIBUTING.md +46 -1
- package/Cargo.toml +1 -1
- package/README.md +7 -6
- package/VERSION +1 -1
- package/c/lib.cpp +19 -17
- package/c/test.c +41 -7
- package/c/usearch.h +15 -15
- package/conanfile.py +1 -1
- package/cpp/test.cpp +9 -2
- package/include/usearch/index.hpp +15 -15
- package/include/usearch/index_dense.hpp +8 -4
- package/include/usearch/index_plugins.hpp +34 -23
- package/javascript/usearch.js +1 -1
- package/package.json +3 -2
- package/pyproject.toml +2 -2
- package/setup.py +10 -4
- package/simsimd/.releaserc +3 -2
- package/simsimd/Cargo.lock +708 -0
- package/simsimd/Cargo.toml +36 -0
- package/simsimd/README.md +37 -1
- package/simsimd/build.rs +20 -0
- package/simsimd/include/simsimd/simsimd.h +4 -4
- package/simsimd/include/simsimd/spatial.h +1 -1
- package/simsimd/include/simsimd/types.h +5 -1
- package/simsimd/package.json +1 -1
- package/simsimd/rust/benches/cosine.rs +27 -0
- package/simsimd/rust/benches/native.rs +27 -0
- package/simsimd/rust/benches/sqeuclidean.rs +27 -0
- package/simsimd/rust/lib.c +68 -0
- package/simsimd/rust/lib.rs +232 -0
- package/sqlite/README.md +178 -0
- package/sqlite/lib.cpp +325 -0
- package/stringzilla/CONTRIBUTING.md +429 -0
- package/stringzilla/Cargo.lock +25 -0
- package/stringzilla/Cargo.toml +26 -0
- package/stringzilla/LICENSE +201 -0
- package/stringzilla/README.md +1281 -0
- package/stringzilla/VERSION +1 -0
- package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
- package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
- package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
- package/stringzilla/binding.gyp +16 -0
- package/stringzilla/build.rs +14 -0
- package/stringzilla/c/lib.c +304 -0
- package/stringzilla/cli/README.md +48 -0
- package/stringzilla/cli/split.py +72 -0
- package/stringzilla/cli/wc.py +37 -0
- package/stringzilla/include/stringzilla/experimental.h +724 -0
- package/stringzilla/include/stringzilla/module.modulemap +9 -0
- package/stringzilla/include/stringzilla/stringzilla.h +5240 -0
- package/stringzilla/include/stringzilla/stringzilla.hpp +3830 -0
- package/stringzilla/javascript/lib.c +125 -0
- package/stringzilla/javascript/stringzilla.js +22 -0
- package/stringzilla/package-ci.json +10 -0
- package/stringzilla/package.json +32 -0
- package/stringzilla/rust/lib.rs +362 -0
- package/stringzilla/swift/StringProtocol+StringZilla.swift +280 -0
- package/stringzilla/swift/Test.swift +60 -0
- package/wasmer.toml +1 -1
- package/simsimd/bench.js +0 -51
|
@@ -61,9 +61,9 @@ jobs:
|
|
|
61
61
|
with:
|
|
62
62
|
node-version: 20
|
|
63
63
|
- name: Build JavaScript
|
|
64
|
-
run: npm
|
|
64
|
+
run: npm ci
|
|
65
65
|
- name: Test JavaScript
|
|
66
|
-
run: npm
|
|
66
|
+
run: npm test
|
|
67
67
|
|
|
68
68
|
# Rust
|
|
69
69
|
- name: Test Rust
|
|
@@ -154,7 +154,6 @@ jobs:
|
|
|
154
154
|
node-version: 20
|
|
155
155
|
- name: Build and test JavaScript
|
|
156
156
|
run: |
|
|
157
|
-
npm install
|
|
158
157
|
npm ci
|
|
159
158
|
npm test
|
|
160
159
|
|
|
@@ -212,9 +211,9 @@ jobs:
|
|
|
212
211
|
with:
|
|
213
212
|
node-version: 20
|
|
214
213
|
- name: Build JavaScript
|
|
215
|
-
run: npm
|
|
214
|
+
run: npm ci
|
|
216
215
|
- name: Test JavaScript
|
|
217
|
-
run: npm
|
|
216
|
+
run: npm test
|
|
218
217
|
|
|
219
218
|
# ObjC/Swift
|
|
220
219
|
- name: Build ObjC/Swift
|
|
@@ -274,9 +273,9 @@ jobs:
|
|
|
274
273
|
with:
|
|
275
274
|
node-version: 20
|
|
276
275
|
- name: Build JavaScript
|
|
277
|
-
run: npm
|
|
276
|
+
run: npm ci
|
|
278
277
|
- name: Test JavaScript
|
|
279
|
-
run: npm
|
|
278
|
+
run: npm test
|
|
280
279
|
|
|
281
280
|
# C#
|
|
282
281
|
- name: Setup .NET ${{ env.DOTNET_VERSION }}
|
|
@@ -303,3 +302,30 @@ jobs:
|
|
|
303
302
|
context: .
|
|
304
303
|
load: true
|
|
305
304
|
push: false
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
build_wheels:
|
|
308
|
+
name: Build Python ${{ matrix.python-version }} for ${{ matrix.os }}
|
|
309
|
+
runs-on: ${{ matrix.os }}
|
|
310
|
+
needs: [test_ubuntu_gcc, test_ubuntu_clang, test_macos, test_windows]
|
|
311
|
+
strategy:
|
|
312
|
+
matrix:
|
|
313
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
314
|
+
python-version: ["37", "38", "39", "310", "311", "312"]
|
|
315
|
+
steps:
|
|
316
|
+
- uses: actions/checkout@v4
|
|
317
|
+
- name: Set up Python
|
|
318
|
+
uses: actions/setup-python@v5
|
|
319
|
+
with:
|
|
320
|
+
python-version: 3.x
|
|
321
|
+
|
|
322
|
+
# We only need QEMU for Linux builds
|
|
323
|
+
- name: Setup QEMU
|
|
324
|
+
if: matrix.os == 'ubuntu-latest'
|
|
325
|
+
uses: docker/setup-qemu-action@v3
|
|
326
|
+
- name: Install cibuildwheel
|
|
327
|
+
run: python -m pip install cibuildwheel
|
|
328
|
+
- name: Build wheels
|
|
329
|
+
run: cibuildwheel --output-dir wheelhouse
|
|
330
|
+
env:
|
|
331
|
+
CIBW_BUILD: cp${{ matrix.python-version }}-*
|
|
@@ -349,39 +349,36 @@ jobs:
|
|
|
349
349
|
* ${{ steps.hashes.outputs.asset_name_15 }} : `${{ steps.hashes.outputs.asset_hash_15 }}`
|
|
350
350
|
|
|
351
351
|
build_wheels:
|
|
352
|
-
name: Build Python
|
|
353
|
-
needs: versioning
|
|
352
|
+
name: Build Python ${{ matrix.python-version }} for ${{ matrix.os }}
|
|
354
353
|
runs-on: ${{ matrix.os }}
|
|
354
|
+
needs: versioning
|
|
355
355
|
strategy:
|
|
356
|
-
fail-fast: false
|
|
357
356
|
matrix:
|
|
358
|
-
os: [ubuntu-
|
|
359
|
-
|
|
357
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
358
|
+
python-version: ["37", "38", "39", "310", "311", "312"]
|
|
360
359
|
steps:
|
|
361
|
-
- uses: actions/checkout@
|
|
360
|
+
- uses: actions/checkout@v4
|
|
362
361
|
with:
|
|
363
362
|
ref: "main"
|
|
364
|
-
-
|
|
365
|
-
|
|
366
|
-
- name: Setup Docker
|
|
367
|
-
if: matrix.os == 'ubuntu-22.04'
|
|
368
|
-
uses: crazy-max/ghaction-setup-docker@v1.0.0
|
|
363
|
+
- name: Set up Python
|
|
364
|
+
uses: actions/setup-python@v5
|
|
369
365
|
with:
|
|
370
|
-
version:
|
|
371
|
-
|
|
366
|
+
python-version: 3.x
|
|
372
367
|
- name: Setup QEMU
|
|
373
|
-
if: matrix.os == 'ubuntu-
|
|
374
|
-
uses: docker/setup-qemu-action@
|
|
375
|
-
|
|
376
|
-
- name: Install CIBuildWheel
|
|
368
|
+
if: matrix.os == 'ubuntu-latest' # We only need QEMU for Linux builds
|
|
369
|
+
uses: docker/setup-qemu-action@v3
|
|
370
|
+
- name: Install cibuildwheel
|
|
377
371
|
run: python -m pip install cibuildwheel
|
|
378
|
-
|
|
379
372
|
- name: Build wheels
|
|
380
|
-
run:
|
|
381
|
-
|
|
382
|
-
|
|
373
|
+
run: cibuildwheel --output-dir wheelhouse
|
|
374
|
+
env:
|
|
375
|
+
CIBW_BUILD: cp${{ matrix.python-version }}-*
|
|
376
|
+
- name: Upload wheels
|
|
377
|
+
uses: actions/upload-artifact@v4
|
|
383
378
|
with:
|
|
379
|
+
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
|
384
380
|
path: ./wheelhouse/*.whl
|
|
381
|
+
overwrite: true
|
|
385
382
|
|
|
386
383
|
publish_python:
|
|
387
384
|
name: Publish Python
|
|
@@ -395,17 +392,20 @@ jobs:
|
|
|
395
392
|
|
|
396
393
|
steps:
|
|
397
394
|
- name: Download artifacts
|
|
398
|
-
uses: actions/download-artifact@
|
|
395
|
+
uses: actions/download-artifact@v4
|
|
399
396
|
with:
|
|
400
|
-
|
|
397
|
+
# unpacks all CIBW artifacts into dist/
|
|
398
|
+
pattern: cibw-*
|
|
399
|
+
path: dist
|
|
400
|
+
merge-multiple: true
|
|
401
401
|
|
|
402
402
|
- name: Publish to PyPi
|
|
403
403
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
404
404
|
with:
|
|
405
|
-
packages-dir:
|
|
405
|
+
packages-dir: dist
|
|
406
406
|
verbose: true
|
|
407
407
|
print-hash: true
|
|
408
|
-
|
|
408
|
+
|
|
409
409
|
publish_javascript:
|
|
410
410
|
name: Publish JavaScript
|
|
411
411
|
needs: versioning
|
|
@@ -432,7 +432,6 @@ jobs:
|
|
|
432
432
|
|
|
433
433
|
- name: Build and Test
|
|
434
434
|
run: |
|
|
435
|
-
npm install
|
|
436
435
|
npm ci
|
|
437
436
|
npm test
|
|
438
437
|
npm run typegen
|
package/.gitmodules
CHANGED
|
@@ -3,4 +3,7 @@
|
|
|
3
3
|
url = https://github.com/ashvardanian/simsimd
|
|
4
4
|
[submodule "fp16"]
|
|
5
5
|
path = fp16
|
|
6
|
-
url = https://github.com/maratyszcza/fp16
|
|
6
|
+
url = https://github.com/maratyszcza/fp16
|
|
7
|
+
[submodule "stringzilla"]
|
|
8
|
+
path = stringzilla
|
|
9
|
+
url = https://github.com/ashvardanian/stringzilla
|
package/CITATION.cff
CHANGED
package/CMakeLists.txt
CHANGED
|
@@ -13,6 +13,11 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
|
|
13
13
|
set(USEARCH_IS_MAIN_PROJECT ON)
|
|
14
14
|
endif ()
|
|
15
15
|
|
|
16
|
+
# Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory
|
|
17
|
+
if (POLICY CMP0077)
|
|
18
|
+
cmake_policy(SET CMP0077 NEW)
|
|
19
|
+
endif ()
|
|
20
|
+
|
|
16
21
|
# Options
|
|
17
22
|
option(USEARCH_INSTALL "Install CMake targets" OFF)
|
|
18
23
|
|
|
@@ -31,11 +36,6 @@ option(USEARCH_BUILD_WOLFRAM "Compile Wolfram Language bindings" OFF)
|
|
|
31
36
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
|
|
32
37
|
include(ExternalProject)
|
|
33
38
|
|
|
34
|
-
# Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory
|
|
35
|
-
if (POLICY CMP0077)
|
|
36
|
-
cmake_policy(SET CMP0077 NEW)
|
|
37
|
-
endif ()
|
|
38
|
-
|
|
39
39
|
# Configuration
|
|
40
40
|
include(GNUInstallDirs)
|
|
41
41
|
set(USEARCH_TARGET_NAME ${PROJECT_NAME})
|
|
@@ -186,9 +186,7 @@ function (setup_target TARGET_NAME)
|
|
|
186
186
|
target_link_libraries(${TARGET_NAME} PRIVATE OpenMP::OpenMP_CXX)
|
|
187
187
|
endif ()
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
target_link_libraries(${TARGET_NAME} PRIVATE Threads::Threads)
|
|
191
|
-
endif ()
|
|
189
|
+
target_link_libraries(${TARGET_NAME} PRIVATE Threads::Threads)
|
|
192
190
|
|
|
193
191
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
194
192
|
target_compile_options(
|
package/CONTRIBUTING.md
CHANGED
|
@@ -130,7 +130,26 @@ Still, if you have Docker running on any desktop OS, you can use it to build and
|
|
|
130
130
|
|
|
131
131
|
```sh
|
|
132
132
|
pip install cibuildwheel
|
|
133
|
-
cibuildwheel
|
|
133
|
+
cibuildwheel
|
|
134
|
+
cibuildwheel --platform linux # works on any OS and builds all Linux backends
|
|
135
|
+
cibuildwheel --platform linux --archs x86_64 # 64-bit x86, the most common on desktop and servers
|
|
136
|
+
cibuildwheel --platform linux --archs aarch64 # 64-bit Arm for mobile devices, Apple M-series, and AWS Graviton
|
|
137
|
+
cibuildwheel --platform linux --archs i686 # 32-bit Linux
|
|
138
|
+
cibuildwheel --platform linux --archs s390x # emulating big-endian IBM Z
|
|
139
|
+
cibuildwheel --platform macos # works only on MacOS
|
|
140
|
+
cibuildwheel --platform windows # works only on Windows
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
You may need root previligies for multi-architecture builds:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
sudo $(which cibuildwheel) --platform linux
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
On Windows and MacOS, to avoid frequent path resolution issues, you may want to use:
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
python -m cibuildwheel --platform windows
|
|
134
153
|
```
|
|
135
154
|
|
|
136
155
|
## JavaScript
|
|
@@ -272,6 +291,32 @@ cp cloud/unum/usearch/libusearch.* .
|
|
|
272
291
|
java -cp . -Djava.library.path="$(pwd)" cloud.unum.usearch.Index
|
|
273
292
|
```
|
|
274
293
|
|
|
294
|
+
## C#
|
|
295
|
+
|
|
296
|
+
Setup the .NET environment:
|
|
297
|
+
|
|
298
|
+
```sh
|
|
299
|
+
dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
USearch provides CSharp bindings, that depend on the C library that must be installed beforehand.
|
|
303
|
+
So one should first compile the C library, link it with CSharp, and only then run tests.
|
|
304
|
+
|
|
305
|
+
```sh
|
|
306
|
+
cmake -B ./build_artifacts -DUSEARCH_BUILD_LIB_C=1 -DUSEARCH_BUILD_TEST_C=1 -DUSEARCH_USE_OPENMP=1 -DUSEARCH_USE_SIMSIMD=1
|
|
307
|
+
cmake --build ./build_artifacts --config Release -j
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Then, on Windows, copy the library to the CSharp project and run the tests:
|
|
311
|
+
|
|
312
|
+
```sh
|
|
313
|
+
mkdir -p ".\csharp\lib\runtimes\win-x64\native"
|
|
314
|
+
cp ".\build_artifacts\libusearch_c.dll" ".\csharp\lib\runtimes\win-x64\native"
|
|
315
|
+
cd csharp
|
|
316
|
+
dotnet test -c Debug --logger "console;verbosity=detailed"
|
|
317
|
+
dotnet test -c Release
|
|
318
|
+
```
|
|
319
|
+
|
|
275
320
|
## Wolfram
|
|
276
321
|
|
|
277
322
|
```sh
|
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -30,7 +30,8 @@ Spatial • Binary • Probabilistic • User-Defined Metrics
|
|
|
30
30
|
<a href="https://unum-cloud.github.io/usearch/swift">Swift</a> •
|
|
31
31
|
<a href="https://unum-cloud.github.io/usearch/csharp">C#</a> •
|
|
32
32
|
<a href="https://unum-cloud.github.io/usearch/golang">GoLang</a> •
|
|
33
|
-
<a href="https://unum-cloud.github.io/usearch/wolfram">Wolfram</a>
|
|
33
|
+
<a href="https://unum-cloud.github.io/usearch/wolfram">Wolfram</a> •
|
|
34
|
+
<a href="https://unum-cloud.github.io/usearch/sqlite">SQLite3</a>
|
|
34
35
|
<br/>
|
|
35
36
|
Linux • MacOS • Windows • iOS • WebAssembly
|
|
36
37
|
</p>
|
|
@@ -47,10 +48,10 @@ Linux • MacOS • Windows • iOS • WebAssembly
|
|
|
47
48
|
|
|
48
49
|
---
|
|
49
50
|
|
|
50
|
-
- ✅ [10x faster][faster-than-faiss] [HNSW][hnsw-algorithm] implementation than [FAISS][faiss].
|
|
51
|
-
- ✅ Simple and extensible [single C++11 header][usearch-header]
|
|
51
|
+
- ✅ __[10x faster][faster-than-faiss]__ [HNSW][hnsw-algorithm] implementation than [FAISS][faiss].
|
|
52
|
+
- ✅ Simple and extensible [single C++11 header][usearch-header] __library__.
|
|
52
53
|
- ✅ Compatible with a dozen programming languages out of the box.
|
|
53
|
-
- ✅ [Trusted](#integrations) by
|
|
54
|
+
- ✅ [Trusted](#integrations) by giants like Google and databases like [ClickHouse][clickhouse-docs].
|
|
54
55
|
- ✅ [SIMD][simd]-optimized and [user-defined metrics](#user-defined-functions) with JIT compilation.
|
|
55
56
|
- ✅ Hardware-agnostic `f16` & `i8` - [half-precision & quarter-precision support](#memory-efficiency-downcasting-and-quantization).
|
|
56
57
|
- ✅ [View large indexes from disk](#serving-index-from-disk) without loading into RAM.
|
|
@@ -60,7 +61,7 @@ Linux • MacOS • Windows • iOS • WebAssembly
|
|
|
60
61
|
- ✅ Space-efficient point-clouds with `uint40_t`, accommodating 4B+ size.
|
|
61
62
|
- ✅ Compatible with OpenMP and custom "executors" for fine-grained control over CPU utilization.
|
|
62
63
|
- ✅ Near-real-time [clustering and sub-clustering](#clustering) for Tens or Millions of clusters.
|
|
63
|
-
- ✅ [Semantic Search](#usearch--ai--multi-modal-semantic-search) and [Joins](#joins).
|
|
64
|
+
- ✅ [Semantic Search](#usearch--ai--multi-modal-semantic-search) and [Joins](#joins-one-to-one-one-to-many-and-many-to-many-mappings).
|
|
64
65
|
|
|
65
66
|
[faiss]: https://github.com/facebookresearch/faiss
|
|
66
67
|
[usearch-header]: https://github.com/unum-cloud/usearch/blob/main/include/usearch/index.hpp
|
|
@@ -433,7 +434,7 @@ doi = {10.5281/zenodo.7949416},
|
|
|
433
434
|
author = {Vardanian, Ash},
|
|
434
435
|
title = {{USearch by Unum Cloud}},
|
|
435
436
|
url = {https://github.com/unum-cloud/usearch},
|
|
436
|
-
version = {2.
|
|
437
|
+
version = {2.9.1},
|
|
437
438
|
year = {2023},
|
|
438
439
|
month = oct,
|
|
439
440
|
}
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.9.1
|
package/c/lib.cpp
CHANGED
|
@@ -106,7 +106,7 @@ extern "C" {
|
|
|
106
106
|
|
|
107
107
|
USEARCH_EXPORT usearch_index_t usearch_init(usearch_init_options_t* options, usearch_error_t* error) {
|
|
108
108
|
|
|
109
|
-
assert(options && error);
|
|
109
|
+
assert(options && error && "Missing arguments");
|
|
110
110
|
|
|
111
111
|
index_dense_config_t config(options->connectivity, options->expansion_add, options->expansion_search);
|
|
112
112
|
config.multi = options->multi;
|
|
@@ -132,13 +132,13 @@ USEARCH_EXPORT void usearch_free(usearch_index_t index, usearch_error_t*) {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
USEARCH_EXPORT size_t usearch_serialized_length(usearch_index_t index, usearch_error_t*) {
|
|
135
|
-
assert(index);
|
|
135
|
+
assert(index && "Missing arguments");
|
|
136
136
|
return reinterpret_cast<index_dense_t*>(index)->serialized_length();
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
USEARCH_EXPORT void usearch_save(usearch_index_t index, char const* path, usearch_error_t* error) {
|
|
140
140
|
|
|
141
|
-
assert(index && path && error);
|
|
141
|
+
assert(index && path && error && "Missing arguments");
|
|
142
142
|
serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->save(path);
|
|
143
143
|
if (!result)
|
|
144
144
|
*error = result.error.release();
|
|
@@ -146,7 +146,7 @@ USEARCH_EXPORT void usearch_save(usearch_index_t index, char const* path, usearc
|
|
|
146
146
|
|
|
147
147
|
USEARCH_EXPORT void usearch_load(usearch_index_t index, char const* path, usearch_error_t* error) {
|
|
148
148
|
|
|
149
|
-
assert(index && path && error);
|
|
149
|
+
assert(index && path && error && "Missing arguments");
|
|
150
150
|
serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->load(path);
|
|
151
151
|
if (!result)
|
|
152
152
|
*error = result.error.release();
|
|
@@ -154,7 +154,7 @@ USEARCH_EXPORT void usearch_load(usearch_index_t index, char const* path, usearc
|
|
|
154
154
|
|
|
155
155
|
USEARCH_EXPORT void usearch_view(usearch_index_t index, char const* path, usearch_error_t* error) {
|
|
156
156
|
|
|
157
|
-
assert(index && path && error);
|
|
157
|
+
assert(index && path && error && "Missing arguments");
|
|
158
158
|
serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->view(path);
|
|
159
159
|
if (!result)
|
|
160
160
|
*error = result.error.release();
|
|
@@ -162,7 +162,7 @@ USEARCH_EXPORT void usearch_view(usearch_index_t index, char const* path, usearc
|
|
|
162
162
|
|
|
163
163
|
USEARCH_EXPORT void usearch_metadata(char const* path, usearch_init_options_t* options, usearch_error_t* error) {
|
|
164
164
|
|
|
165
|
-
assert(path && options && error);
|
|
165
|
+
assert(path && options && error && "Missing arguments");
|
|
166
166
|
index_dense_metadata_result_t result = index_dense_metadata_from_path(path);
|
|
167
167
|
if (!result)
|
|
168
168
|
*error = result.error.release();
|
|
@@ -180,7 +180,7 @@ USEARCH_EXPORT void usearch_metadata(char const* path, usearch_init_options_t* o
|
|
|
180
180
|
|
|
181
181
|
USEARCH_EXPORT void usearch_save_buffer(usearch_index_t index, void* buffer, size_t length, usearch_error_t* error) {
|
|
182
182
|
|
|
183
|
-
assert(index && buffer && length && error);
|
|
183
|
+
assert(index && buffer && length && error && "Missing arguments");
|
|
184
184
|
memory_mapped_file_t memory_map((byte_t*)buffer, length);
|
|
185
185
|
serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->save(std::move(memory_map));
|
|
186
186
|
if (!result)
|
|
@@ -190,7 +190,7 @@ USEARCH_EXPORT void usearch_save_buffer(usearch_index_t index, void* buffer, siz
|
|
|
190
190
|
USEARCH_EXPORT void usearch_load_buffer(usearch_index_t index, void const* buffer, size_t length,
|
|
191
191
|
usearch_error_t* error) {
|
|
192
192
|
|
|
193
|
-
assert(index && buffer && length && error);
|
|
193
|
+
assert(index && buffer && length && error && "Missing arguments");
|
|
194
194
|
memory_mapped_file_t memory_map((byte_t*)buffer, length);
|
|
195
195
|
serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->load(std::move(memory_map));
|
|
196
196
|
if (!result)
|
|
@@ -200,7 +200,7 @@ USEARCH_EXPORT void usearch_load_buffer(usearch_index_t index, void const* buffe
|
|
|
200
200
|
USEARCH_EXPORT void usearch_view_buffer(usearch_index_t index, void const* buffer, size_t length,
|
|
201
201
|
usearch_error_t* error) {
|
|
202
202
|
|
|
203
|
-
assert(index && buffer && length && error);
|
|
203
|
+
assert(index && buffer && length && error && "Missing arguments");
|
|
204
204
|
memory_mapped_file_t memory_map((byte_t*)buffer, length);
|
|
205
205
|
serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->view(std::move(memory_map));
|
|
206
206
|
if (!result)
|
|
@@ -210,7 +210,7 @@ USEARCH_EXPORT void usearch_view_buffer(usearch_index_t index, void const* buffe
|
|
|
210
210
|
USEARCH_EXPORT void usearch_metadata_buffer(void const* buffer, size_t length, usearch_init_options_t* options,
|
|
211
211
|
usearch_error_t* error) {
|
|
212
212
|
|
|
213
|
-
assert(buffer && length && options && error);
|
|
213
|
+
assert(buffer && length && options && error && "Missing arguments");
|
|
214
214
|
index_dense_metadata_result_t result =
|
|
215
215
|
index_dense_metadata_from_buffer(memory_mapped_file_t((byte_t*)(buffer), length));
|
|
216
216
|
if (!result)
|
|
@@ -244,7 +244,7 @@ USEARCH_EXPORT size_t usearch_connectivity(usearch_index_t index, usearch_error_
|
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
USEARCH_EXPORT void usearch_reserve(usearch_index_t index, size_t capacity, usearch_error_t* error) {
|
|
247
|
-
assert(index && error);
|
|
247
|
+
assert(index && error && "Missing arguments");
|
|
248
248
|
if (!reinterpret_cast<index_dense_t*>(index)->reserve(capacity))
|
|
249
249
|
*error = "Out of memory!";
|
|
250
250
|
}
|
|
@@ -253,19 +253,19 @@ USEARCH_EXPORT void usearch_add(
|
|
|
253
253
|
usearch_index_t index, usearch_key_t key, void const* vector, usearch_scalar_kind_t kind, //
|
|
254
254
|
usearch_error_t* error) {
|
|
255
255
|
|
|
256
|
-
assert(index && vector && error);
|
|
256
|
+
assert(index && vector && error && "Missing arguments");
|
|
257
257
|
add_result_t result = add_(reinterpret_cast<index_dense_t*>(index), key, vector, scalar_kind_to_cpp(kind));
|
|
258
258
|
if (!result)
|
|
259
259
|
*error = result.error.release();
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
USEARCH_EXPORT bool usearch_contains(usearch_index_t index, usearch_key_t key, usearch_error_t*) {
|
|
263
|
-
assert(index);
|
|
263
|
+
assert(index && "Missing arguments");
|
|
264
264
|
return reinterpret_cast<index_dense_t*>(index)->contains(key);
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
USEARCH_EXPORT size_t usearch_count(usearch_index_t index, usearch_key_t key, usearch_error_t*) {
|
|
268
|
-
assert(index);
|
|
268
|
+
assert(index && "Missing arguments");
|
|
269
269
|
return reinterpret_cast<index_dense_t*>(index)->count(key);
|
|
270
270
|
}
|
|
271
271
|
|
|
@@ -273,7 +273,7 @@ USEARCH_EXPORT size_t usearch_search(
|
|
|
273
273
|
usearch_index_t index, void const* vector, usearch_scalar_kind_t kind, size_t results_limit, //
|
|
274
274
|
usearch_key_t* found_keys, usearch_distance_t* found_distances, usearch_error_t* error) {
|
|
275
275
|
|
|
276
|
-
assert(index && vector && error);
|
|
276
|
+
assert(index && vector && error && "Missing arguments");
|
|
277
277
|
search_result_t result =
|
|
278
278
|
search_(reinterpret_cast<index_dense_t*>(index), vector, scalar_kind_to_cpp(kind), results_limit);
|
|
279
279
|
if (!result) {
|
|
@@ -294,7 +294,7 @@ USEARCH_EXPORT size_t usearch_get( //
|
|
|
294
294
|
|
|
295
295
|
USEARCH_EXPORT size_t usearch_remove(usearch_index_t index, usearch_key_t key, usearch_error_t* error) {
|
|
296
296
|
|
|
297
|
-
assert(index && error);
|
|
297
|
+
assert(index && error && "Missing arguments");
|
|
298
298
|
labeling_result_t result = reinterpret_cast<index_dense_t*>(index)->remove(key);
|
|
299
299
|
if (!result)
|
|
300
300
|
*error = result.error.release();
|
|
@@ -304,7 +304,7 @@ USEARCH_EXPORT size_t usearch_remove(usearch_index_t index, usearch_key_t key, u
|
|
|
304
304
|
USEARCH_EXPORT size_t usearch_rename( //
|
|
305
305
|
usearch_index_t index, usearch_key_t from, usearch_key_t to, usearch_error_t* error) {
|
|
306
306
|
|
|
307
|
-
assert(index && error);
|
|
307
|
+
assert(index && error && "Missing arguments");
|
|
308
308
|
labeling_result_t result = reinterpret_cast<index_dense_t*>(index)->rename(from, to);
|
|
309
309
|
if (!result)
|
|
310
310
|
*error = result.error.release();
|
|
@@ -330,6 +330,8 @@ USEARCH_EXPORT void usearch_exact_search( //
|
|
|
330
330
|
usearch_distance_t* distances, size_t distances_stride, //
|
|
331
331
|
usearch_error_t* error) {
|
|
332
332
|
|
|
333
|
+
assert(dataset && queries && keys && distances && error && "Missing arguments");
|
|
334
|
+
|
|
333
335
|
metric_punned_t metric(dimensions, metric_kind_to_cpp(metric_kind), scalar_kind_to_cpp(scalar_kind));
|
|
334
336
|
executor_default_t executor(threads);
|
|
335
337
|
static exact_search_t search;
|
package/c/test.c
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#include <errno.h>
|
|
2
|
-
#include <stdio.h>
|
|
2
|
+
#include <stdio.h> // `remove`
|
|
3
3
|
#include <stdlib.h>
|
|
4
4
|
#include <sys/stat.h>
|
|
5
5
|
|
|
@@ -236,7 +236,13 @@ void test_save_load(size_t const collection_size, size_t const dimensions) {
|
|
|
236
236
|
|
|
237
237
|
usearch_error_t error = NULL;
|
|
238
238
|
usearch_init_options_t opts = create_options(dimensions);
|
|
239
|
-
|
|
239
|
+
usearch_init_options_t weird_ops = opts;
|
|
240
|
+
weird_ops.connectivity = 11;
|
|
241
|
+
weird_ops.expansion_add = 15;
|
|
242
|
+
weird_ops.expansion_search = 19;
|
|
243
|
+
weird_ops.metric_kind = usearch_metric_pearson_k;
|
|
244
|
+
weird_ops.quantization = usearch_scalar_f64_k;
|
|
245
|
+
usearch_index_t index = usearch_init(&weird_ops, &error);
|
|
240
246
|
usearch_reserve(index, collection_size, &error);
|
|
241
247
|
|
|
242
248
|
// Add vectors
|
|
@@ -248,23 +254,32 @@ void test_save_load(size_t const collection_size, size_t const dimensions) {
|
|
|
248
254
|
}
|
|
249
255
|
|
|
250
256
|
// Save and free the index
|
|
251
|
-
usearch_save(index, "
|
|
257
|
+
usearch_save(index, "tmp.usearch", &error);
|
|
252
258
|
ASSERT(!error, error);
|
|
253
259
|
usearch_free(index, &error);
|
|
254
260
|
ASSERT(!error, error);
|
|
255
261
|
|
|
262
|
+
// Reset the options
|
|
263
|
+
opts.connectivity = 0;
|
|
264
|
+
opts.dimensions = 0;
|
|
265
|
+
opts.expansion_add = 0;
|
|
266
|
+
opts.expansion_search = 0;
|
|
267
|
+
opts.metric = NULL;
|
|
268
|
+
opts.quantization = usearch_scalar_unknown_k;
|
|
269
|
+
opts.metric_kind = usearch_metric_unknown_k;
|
|
270
|
+
|
|
256
271
|
// Reinit
|
|
257
272
|
index = usearch_init(&opts, &error);
|
|
258
273
|
ASSERT(!error, error);
|
|
259
274
|
ASSERT(usearch_size(index, &error) == 0, error);
|
|
260
275
|
|
|
261
276
|
// Load
|
|
262
|
-
usearch_load(index, "
|
|
277
|
+
usearch_load(index, "tmp.usearch", &error);
|
|
263
278
|
ASSERT(!error, error);
|
|
264
279
|
ASSERT(usearch_size(index, &error) == collection_size, error);
|
|
265
280
|
ASSERT(usearch_capacity(index, &error) == collection_size, error);
|
|
266
281
|
ASSERT(usearch_dimensions(index, &error) == dimensions, error);
|
|
267
|
-
ASSERT(usearch_connectivity(index, &error) ==
|
|
282
|
+
ASSERT(usearch_connectivity(index, &error) == weird_ops.connectivity, error);
|
|
268
283
|
|
|
269
284
|
// Check vectors in the index
|
|
270
285
|
for (size_t i = 0; i < collection_size; ++i) {
|
|
@@ -272,8 +287,27 @@ void test_save_load(size_t const collection_size, size_t const dimensions) {
|
|
|
272
287
|
ASSERT(usearch_contains(index, key, &error), error);
|
|
273
288
|
}
|
|
274
289
|
|
|
290
|
+
// Create result buffers
|
|
291
|
+
usearch_key_t* keys = (usearch_key_t*)malloc(collection_size * sizeof(usearch_key_t));
|
|
292
|
+
float* distances = (float*)malloc(collection_size * sizeof(float));
|
|
293
|
+
ASSERT(keys && distances, "Failed to allocate memory");
|
|
294
|
+
|
|
295
|
+
// Find the vectors
|
|
296
|
+
for (size_t i = 0; i < collection_size; i++) {
|
|
297
|
+
size_t found_count = usearch_search(index, data + i * dimensions, usearch_scalar_f32_k, collection_size, keys,
|
|
298
|
+
distances, &error);
|
|
299
|
+
ASSERT(!error, error);
|
|
300
|
+
ASSERT(found_count >= 1 && found_count <= collection_size, "Vector is missing");
|
|
301
|
+
}
|
|
302
|
+
|
|
275
303
|
free(data);
|
|
304
|
+
free(keys);
|
|
305
|
+
free(distances);
|
|
276
306
|
usearch_free(index, &error);
|
|
307
|
+
|
|
308
|
+
// Remove the file from disk
|
|
309
|
+
remove("tmp.usearch");
|
|
310
|
+
|
|
277
311
|
printf("Test: Save/Load - PASSED\n");
|
|
278
312
|
}
|
|
279
313
|
|
|
@@ -300,7 +334,7 @@ void test_view(size_t const collection_size, size_t const dimensions) {
|
|
|
300
334
|
}
|
|
301
335
|
|
|
302
336
|
// Save and free the index
|
|
303
|
-
usearch_save(index, "
|
|
337
|
+
usearch_save(index, "tmp.usearch", &error);
|
|
304
338
|
ASSERT(!error, error);
|
|
305
339
|
usearch_free(index, &error);
|
|
306
340
|
ASSERT(!error, error);
|
|
@@ -310,7 +344,7 @@ void test_view(size_t const collection_size, size_t const dimensions) {
|
|
|
310
344
|
ASSERT(!error, error);
|
|
311
345
|
|
|
312
346
|
// View
|
|
313
|
-
usearch_view(index, "
|
|
347
|
+
usearch_view(index, "tmp.usearch", &error);
|
|
314
348
|
ASSERT(!error, error);
|
|
315
349
|
|
|
316
350
|
free(data);
|
package/c/usearch.h
CHANGED
|
@@ -39,25 +39,25 @@ USEARCH_EXPORT typedef usearch_distance_t (*usearch_metric_t)(void const*, void
|
|
|
39
39
|
*/
|
|
40
40
|
USEARCH_EXPORT typedef enum usearch_metric_kind_t {
|
|
41
41
|
usearch_metric_unknown_k = 0,
|
|
42
|
-
usearch_metric_cos_k,
|
|
43
|
-
usearch_metric_ip_k,
|
|
44
|
-
usearch_metric_l2sq_k,
|
|
45
|
-
usearch_metric_haversine_k,
|
|
46
|
-
usearch_metric_divergence_k,
|
|
47
|
-
usearch_metric_pearson_k,
|
|
48
|
-
usearch_metric_jaccard_k,
|
|
49
|
-
usearch_metric_hamming_k,
|
|
50
|
-
usearch_metric_tanimoto_k,
|
|
51
|
-
usearch_metric_sorensen_k,
|
|
42
|
+
usearch_metric_cos_k = 1,
|
|
43
|
+
usearch_metric_ip_k = 2,
|
|
44
|
+
usearch_metric_l2sq_k = 3,
|
|
45
|
+
usearch_metric_haversine_k = 4,
|
|
46
|
+
usearch_metric_divergence_k = 5,
|
|
47
|
+
usearch_metric_pearson_k = 6,
|
|
48
|
+
usearch_metric_jaccard_k = 7,
|
|
49
|
+
usearch_metric_hamming_k = 8,
|
|
50
|
+
usearch_metric_tanimoto_k = 9,
|
|
51
|
+
usearch_metric_sorensen_k = 10,
|
|
52
52
|
} usearch_metric_kind_t;
|
|
53
53
|
|
|
54
54
|
USEARCH_EXPORT typedef enum usearch_scalar_kind_t {
|
|
55
55
|
usearch_scalar_unknown_k = 0,
|
|
56
|
-
usearch_scalar_f32_k,
|
|
57
|
-
usearch_scalar_f64_k,
|
|
58
|
-
usearch_scalar_f16_k,
|
|
59
|
-
usearch_scalar_i8_k,
|
|
60
|
-
usearch_scalar_b1_k,
|
|
56
|
+
usearch_scalar_f32_k = 1,
|
|
57
|
+
usearch_scalar_f64_k = 2,
|
|
58
|
+
usearch_scalar_f16_k = 3,
|
|
59
|
+
usearch_scalar_i8_k = 4,
|
|
60
|
+
usearch_scalar_b1_k = 5,
|
|
61
61
|
} usearch_scalar_kind_t;
|
|
62
62
|
|
|
63
63
|
USEARCH_EXPORT typedef struct usearch_init_options_t {
|
package/conanfile.py
CHANGED
|
@@ -7,7 +7,7 @@ required_conan_version = ">=1.53.0"
|
|
|
7
7
|
class USearchConan(ConanFile):
|
|
8
8
|
|
|
9
9
|
name = "usearch"
|
|
10
|
-
version = '2.
|
|
10
|
+
version = '2.9.1'
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
description = "Smaller & Faster Single-File Vector Search Engine from Unum"
|
|
13
13
|
homepage = "https://github.com/unum-cloud/usearch"
|