usearch 1.2.2 → 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.
Files changed (42) hide show
  1. package/.github/workflows/prerelease.yml +71 -0
  2. package/.github/workflows/release.yml +77 -2
  3. package/.github/workflows/update_version.sh +1 -0
  4. package/.gitignore +11 -1
  5. package/.vscode/settings.json +5 -1
  6. package/CMakeLists.txt +1 -0
  7. package/Cargo.toml +1 -1
  8. package/README.md +31 -18
  9. package/c/lib.cpp +38 -4
  10. package/c/test.c +117 -114
  11. package/c/usearch.h +28 -1
  12. package/conanfile.py +1 -1
  13. package/cpp/test.cpp +2 -2
  14. package/csharp/.editorconfig +361 -0
  15. package/csharp/Cloud.Unum.USearch.sln +34 -0
  16. package/csharp/DEV_SETUP.md +51 -0
  17. package/csharp/Directory.Build.props +29 -0
  18. package/csharp/README.md +77 -0
  19. package/csharp/build_and_test.cmd +31 -0
  20. package/csharp/build_and_test.sh +30 -0
  21. package/csharp/eng/build_lib.sh +65 -0
  22. package/csharp/eng/clean.sh +12 -0
  23. package/csharp/nuget/NUGET.md +11 -0
  24. package/csharp/nuget/nuget-package.props +33 -0
  25. package/csharp/pack.sh +56 -0
  26. package/csharp/src/Cloud.Unum.USearch.Tests/Cloud.Unum.USearch.Tests.csproj +39 -0
  27. package/csharp/src/Cloud.Unum.USearch.Tests/InitTests.cs +306 -0
  28. package/csharp/src/Cloud.Unum.USearch.Tests/Usings.cs +1 -0
  29. package/docs/benchmarks.md +6 -6
  30. package/docs/compilation.md +1 -1
  31. package/include/usearch/index.hpp +172 -52
  32. package/include/usearch/index_dense.hpp +201 -64
  33. package/include/usearch/index_plugins.hpp +90 -69
  34. package/package.json +2 -2
  35. package/python/lib.cpp +99 -37
  36. package/python/scripts/test_index.py +38 -10
  37. package/python/usearch/index.py +87 -37
  38. package/rust/README.md +2 -2
  39. package/rust/lib.cpp +42 -19
  40. package/rust/lib.hpp +14 -0
  41. package/rust/lib.rs +85 -43
  42. package/wasmer.toml +1 -1
@@ -17,6 +17,32 @@ permissions:
17
17
 
18
18
  jobs:
19
19
 
20
+ test_c:
21
+ name: Test C
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v3
25
+ with:
26
+ ref: main-dev
27
+ - run: git submodule update --init --recursive
28
+ - name: Prepare Environment
29
+ run: |
30
+ sudo apt update &&
31
+ sudo apt install -y cmake g++-12 build-essential libjemalloc-dev
32
+ - name: Build
33
+ run: |
34
+ cmake -B ./build_release \
35
+ -DCMAKE_CXX_COMPILER="g++-12" \
36
+ -DCMAKE_BUILD_TYPE=Release \
37
+ -DUSEARCH_BUILD_TEST=1 \
38
+ -DUSEARCH_USE_OPENMP=1 \
39
+ -DUSEARCH_USE_SIMSIMD=1 \
40
+ -DUSEARCH_USE_JEMALLOC=1 \
41
+ -DUSEARCH_BUILD_BENCHMARK=0 &&
42
+ make -C ./build_release -j
43
+ - name: Run tests
44
+ run: ./build_release/test_c
45
+
20
46
  test_cpp:
21
47
  name: Test C++
22
48
  runs-on: ubuntu-latest
@@ -148,6 +174,51 @@ jobs:
148
174
  - name: Run tests
149
175
  run: swift test
150
176
 
177
+ test_csharp:
178
+ name: Test C#
179
+ runs-on: ${{ matrix.os }}
180
+ strategy:
181
+ fail-fast: false
182
+ matrix:
183
+ os: [ubuntu-latest, windows-latest, macos-latest]
184
+ dotnet-version: ['7.0.x']
185
+ steps:
186
+ - uses: actions/checkout@v3
187
+ - run: git submodule update --init --recursive
188
+ - name: Setup .NET ${{ matrix.dotnet-version }}
189
+ uses: actions/setup-dotnet@v3
190
+ with:
191
+ dotnet-version: ${{ matrix.dotnet-version }}
192
+
193
+ - name: Ubuntu/macOS build native lib
194
+ if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
195
+ run: ./build_lib.sh
196
+ shell: bash
197
+ working-directory: ${{ github.workspace }}/csharp/eng/
198
+
199
+ # Use cl.exe https://www.appveyor.com/docs/lang/cpp/#visual-studio-2017
200
+ # There is no support for c++11
201
+ - name: Windows MSVC build
202
+ if: matrix.os == 'windows-latest'
203
+ run: |
204
+ call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
205
+ where cl
206
+ cl /EHsc /std:c++14 /O2 /LD /Fe:libusearch_c.dll lib.cpp /I. /I../include/ /I../fp16/include/
207
+ working-directory: ${{ github.workspace }}/c
208
+ shell: cmd
209
+
210
+ - name: Windows move dll to lib dir
211
+ if: matrix.os == 'windows-latest'
212
+ run: |
213
+ mkdir -p "${GITHUB_WORKSPACE}/csharp/lib/runtimes/win-x64/native"
214
+ mv "${GITHUB_WORKSPACE}/c/libusearch_c.dll" "${GITHUB_WORKSPACE}/csharp/lib/runtimes/win-x64/native"
215
+ shell: bash
216
+
217
+ - name: Build and test
218
+ run: dotnet test -c Release
219
+ shell: bash
220
+ working-directory: ${{ github.workspace }}/csharp/
221
+
151
222
  build_docker:
152
223
  name: Test Docker Image
153
224
  runs-on: ubuntu-latest
@@ -271,11 +271,86 @@ jobs:
271
271
  tags: ${{ steps.meta.outputs.tags }}
272
272
  labels: ${{ steps.meta.outputs.labels }}
273
273
 
274
+ build_csharp:
275
+ name: Build NuGet
276
+ strategy:
277
+ matrix:
278
+ os: [ubuntu-latest, macos-latest, windows-latest]
279
+ runs-on: ${{ matrix.os }}
280
+ defaults:
281
+ run:
282
+ shell: bash
283
+ steps:
284
+ - uses: actions/checkout@v3
285
+ - run: git submodule update --init --recursive
286
+
287
+ - name: Ubuntu/macOS build usearch shared obj
288
+ if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
289
+ run: ./build_lib.sh
290
+ working-directory: ${{ github.workspace }}/csharp/eng
291
+
292
+ - name: Windows MSVC build usearch dll
293
+ if: matrix.os == 'windows-latest'
294
+ run: |
295
+ call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
296
+ where cl
297
+ cl /EHsc /std:c++14 /O2 /LD /Fe:libusearch_c.dll lib.cpp /I. /I../include/ /I../fp16/include/
298
+ working-directory: ${{ github.workspace }}/c
299
+ shell: cmd
300
+
301
+ - name: Windows copy dll
302
+ if: matrix.os == 'windows-latest'
303
+ run: |
304
+ mkdir -p "${GITHUB_WORKSPACE}/csharp/lib/runtimes/win-x64/native"
305
+ cp "${GITHUB_WORKSPACE}/c/libusearch_c.dll" "${GITHUB_WORKSPACE}/csharp/lib/runtimes/win-x64/native"
306
+ shell: bash
307
+
308
+ - name: Upload Artifacts
309
+ uses: actions/upload-artifact@v3
310
+ with:
311
+ name: usearch-libs
312
+ path: ${{ github.workspace }}/csharp/lib/**/*
313
+
314
+ publish_csharp:
315
+ name: Publish C#
316
+ runs-on: ubuntu-latest
317
+ needs: [build_csharp]
318
+ env:
319
+ USEARCH_LIBS: ${{ github.workspace }}/csharp/lib
320
+ NUGET_DIR: ${{ github.workspace }}/csharp/packages
321
+ # NUGET_SOURCE: https://apiint.nugettest.org/v3/index.json
322
+ NUGET_SOURCE: https://api.nuget.org/v3/index.json
323
+ SOLUTION_DIR: ${{ github.workspace }}/csharp
324
+ steps:
325
+ - uses: actions/checkout@v3
326
+ - run: git submodule update --init --recursive
327
+
328
+ - name: Download usearch libs artifact
329
+ uses: actions/download-artifact@v3
330
+ with:
331
+ name: usearch-libs
332
+ path: ${{ env.USEARCH_LIBS }}
333
+
334
+ - name: Setup .NET
335
+ uses: actions/setup-dotnet@v3
336
+ with:
337
+ dotnet-version: 7.0.x
338
+
339
+ - name: Pack project
340
+ run: |
341
+ VERSION_CONTENT=$(< VERSION)
342
+ dotnet pack "${{ env.SOLUTION_DIR }}" -c Release -p:Version="$VERSION_CONTENT" --output ${{ env.NUGET_DIR }}
343
+ working-directory: ${{ github.workspace }}
344
+
345
+ - name: Publish NuGet packages
346
+ run: |
347
+ dotnet nuget push "${{ env.NUGET_DIR }}/*.nupkg" --api-key "${{ secrets.NUGET_APIKEY }}" --source "${{ env.NUGET_SOURCE }}"
348
+
274
349
  build_docs:
275
350
  name: Build Docs
276
351
  runs-on: ubuntu-22.04
277
352
  if: ${{ always() }}
278
- needs: [publish_python, publish_javascript, publish_rust, publish_java, publish_swift, publish_docker]
353
+ needs: [publish_python, publish_javascript, publish_rust, publish_java, publish_swift, publish_docker, publish_csharp]
279
354
  permissions:
280
355
  contents: write
281
356
  steps:
@@ -287,7 +362,7 @@ jobs:
287
362
  run: |
288
363
  sudo apt update &&
289
364
  sudo apt install -y doxygen graphviz dia git &&
290
- pip install sphinx==7.1.2 sphinx-js breathe furo m2r2 sphinxcontrib-googleanalytics==0.2.dev20220708 sphinxcontrib-jquery &&
365
+ pip install sphinx==5.3.0 sphinx-js==3.2.1 breathe==4.35.0 furo==2023.3.27 m2r2==0.3.3.post2 sphinxcontrib-googleanalytics==0.2.dev20220708 sphinxcontrib-jquery==4.1 &&
291
366
  npm install -g jsdoc
292
367
  - name: Install USearch from PyPi
293
368
  run: pip install usearch
@@ -10,4 +10,5 @@ echo $1 > VERSION &&
10
10
  sed -i "s/^\(#define USEARCH_VERSION_PATCH \).*/\1$(echo "$1" | cut -d. -f3)/" ./include/usearch/index.hpp &&
11
11
  sed -i "s/<version>[0-9]\+\.[0-9]\+\.[0-9]\+/<version>$1/" README.md &&
12
12
  sed -i "s/version = {[0-9]\+\.[0-9]\+\.[0-9]\+}/version = {$1}/" README.md &&
13
+ sed -i "s/>[0-9]\+\.[0-9]\+\.[0-9]\+<\/Version>/>$1<\/Version>/" ./csharp/nuget/nuget-package.props &&
13
14
  sed -i "s/version=\".*\"/version=\"$1\"/" wasmer.toml
package/.gitignore CHANGED
@@ -31,6 +31,9 @@ __pycache__
31
31
  dist/
32
32
  wheelhouse/
33
33
 
34
+ # Python Environments
35
+ venv/
36
+
34
37
  # JS wrappers
35
38
  package-lock.json
36
39
  node_modules/
@@ -39,7 +42,7 @@ node_modules/
39
42
  Cargo.lock
40
43
  target/
41
44
 
42
- # Java binings
45
+ # Java bindings
43
46
  .gradle
44
47
  *.class
45
48
 
@@ -47,6 +50,12 @@ target/
47
50
  .build
48
51
  .swiftpm
49
52
 
53
+ # C# builds
54
+ csharp/**/[Bb]in/
55
+ csharp/**/[Oo]bj/
56
+ csharp/lib
57
+ csharp/packages
58
+
50
59
  # Prerequisites
51
60
  *.d
52
61
 
@@ -82,3 +91,4 @@ target/
82
91
  *.exe
83
92
  *.out
84
93
  *.app
94
+
@@ -111,6 +111,7 @@
111
111
  "Availible",
112
112
  "bidict",
113
113
  "BLAS",
114
+ "Cdecl",
114
115
  "cflags",
115
116
  "citerator",
116
117
  "downcasted",
@@ -126,6 +127,7 @@
126
127
  "hnswlib",
127
128
  "ibin",
128
129
  "jaccard",
130
+ "libusearch",
129
131
  "longlong",
130
132
  "memmap",
131
133
  "Napi",
@@ -146,7 +148,8 @@
146
148
  "uninitialize",
147
149
  "unumusearch",
148
150
  "usearch",
149
- "usecases"
151
+ "usecases",
152
+ "Xunit"
150
153
  ],
151
154
  "autoDocstring.docstringFormat": "sphinx",
152
155
  "java.configuration.updateBuildConfiguration": "interactive",
@@ -163,4 +166,5 @@
163
166
  "editor.formatOnSave": true,
164
167
  "editor.defaultFormatter": "golang.go"
165
168
  },
169
+ "dotnet.defaultSolution": "csharp/Cloud.Unum.USearch.sln",
166
170
  }
package/CMakeLists.txt CHANGED
@@ -113,6 +113,7 @@ if(USEARCH_INSTALL)
113
113
  endif()
114
114
 
115
115
  if(${USEARCH_BUILD_TEST} OR ${USEARCH_BUILD_BENCHMARK})
116
+ add_subdirectory(c)
116
117
  add_subdirectory(cpp)
117
118
  endif()
118
119
 
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "usearch"
3
- version = "1.2.2"
3
+ version = "2.0.0"
4
4
  authors = ["Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
5
5
  description = "Smaller & Faster Single-File Vector Search Engine from Unum"
6
6
  edition = "2021"
package/README.md CHANGED
@@ -109,10 +109,10 @@ Comparing the performance of FAISS against USearch on 1 Million 96-dimensional v
109
109
 
110
110
  | | FAISS, `f32` | USearch, `f32` | USearch, `f16` | USearch, `i8` |
111
111
  | :----------- | -----------: | -------------: | -------------: | ----------------: |
112
- | Batch Insert | 16 K/s | 73 K/s | 100 K/s | 104 K/s **+550%** |
113
- | Batch Search | 82 K/s | 103 K/s | 113 K/s | 134 K/s **+63%** |
114
- | Bulk Insert | 76 K/s | 105 K/s | 115 K/s | 202 K/s **+165%** |
115
- | Bulk Search | 118 K/s | 174 K/s | 173 K/s | 304 K/s **+157%** |
112
+ | Batch Insert | 16 K/s | 73 K/s | 100 K/s | 104 K/s __+550%__ |
113
+ | Batch Search | 82 K/s | 103 K/s | 113 K/s | 134 K/s __+63%__ |
114
+ | Bulk Insert | 76 K/s | 105 K/s | 115 K/s | 202 K/s __+165%__ |
115
+ | Bulk Search | 118 K/s | 174 K/s | 173 K/s | 304 K/s __+157%__ |
116
116
  | Recall @ 10 | 99% | 99.2% | 99.1% | 99.2% |
117
117
 
118
118
  > HNSW was configured with identical hyper-parameters:
@@ -152,10 +152,16 @@ Instead, we have focused on high-precision arithmetic over low-precision downcas
152
152
  The same index, and `add` and `search` operations will automatically down-cast or up-cast between `f32_t`, `f16_t`, `f64_t`, and `i8_t` representations, even if the hardware doesn't natively support it.
153
153
  Continuing the topic of memory efficiency, we provide a `uint40_t` to allow collection with over 4B+ vectors without allocating 8 bytes for every neighbor reference in the proximity graph.
154
154
 
155
- ## Serving `Index` from Disk
155
+ ## Serialization & Serving `Index` from Disk
156
156
 
157
- With USearch, you can serve indexes from external memory, enabling you to optimize your server choices for indexing speed and serving costs.
158
- This can result in **20x cost reduction** on AWS and other public clouds.
157
+ USearch supports multiple forms of serialization:
158
+
159
+ - Into a __file__ defined with a path.
160
+ - Into a __stream__ defined with a callback, serializing or reconstructing incrementally.
161
+ - Into a __buffer__ of fixed length, or a memory-mapped file, that supports random access.
162
+
163
+ The latter allows you to serve indexes from external memory, enabling you to optimize your server choices for indexing speed and serving costs.
164
+ This can result in __20x cost reduction__ on AWS and other public clouds.
159
165
 
160
166
  ```py
161
167
  index.save("index.usearch")
@@ -186,10 +192,10 @@ many_in_many: BatchMatches = search(vectors, vectors, 50, MetricKind.L2sq, exact
186
192
  ```
187
193
 
188
194
  By passing the `exact=True` argument, the system bypasses indexing altogether and performs a brute-force search through the entire dataset using SIMD-optimized similarity metrics from [SimSIMD](https://github.com/ashvardanian/simsimd).
189
- When compared to FAISS's `IndexFlatL2` in Google Colab, **[USearch may offer up to a 20x performance improvement](https://github.com/unum-cloud/usearch/issues/176#issuecomment-1666650778)**:
195
+ When compared to FAISS's `IndexFlatL2` in Google Colab, __[USearch may offer up to a 20x performance improvement](https://github.com/unum-cloud/usearch/issues/176#issuecomment-1666650778)__:
190
196
 
191
- - `faiss.IndexFlatL2`: **55.3 ms**.
192
- - `usearch.index.search`: **2.54 ms**.
197
+ - `faiss.IndexFlatL2`: __55.3 ms__.
198
+ - `usearch.index.search`: __2.54 ms__.
193
199
 
194
200
  ## `Indexes` for Multi-Index Lookups
195
201
 
@@ -277,8 +283,10 @@ Broader functionality is ported per request.
277
283
 
278
284
  ### USearch + AI = Multi-Modal Semantic Search
279
285
 
286
+ [![USearch Semantic Image Search](https://github.com/ashvardanian/usearch-images/raw/main/assets/usearch-images-slow.gif)](https://github.com/ashvardanian/usearch-images)
287
+
280
288
  AI has a growing number of applications, but one of the coolest classic ideas is to use it for Semantic Search.
281
- One can take an encoder model, like the multi-modal UForm, and a web-programming framework, like UCall, and build a text-to-image search platform in just 20 lines of Python.
289
+ One can take an encoder model, like the multi-modal [UForm](https://github.com/unum-cloud/uform), and a web-programming framework, like UCall, and build a text-to-image search platform in just 20 lines of Python.
282
290
 
283
291
  ```python
284
292
  import ucall
@@ -308,13 +316,14 @@ def search(query: str) -> np.ndarray:
308
316
  server.run()
309
317
  ```
310
318
 
319
+ A more complete [demo with Streamlit is available on GitHub](https://github.com/ashvardanian/usearch-images).
311
320
  We have pre-processed some commonly used datasets, cleaned the images, produced the vectors, and pre-built the index.
312
321
 
313
- | Dataset | Modalities | Images | Download |
314
- | :------------------------------------- | --------------------: | -----: | ------------------------------------: |
315
- | [Unsplash 25K][unsplash-25k-origin] | Images & Descriptions | 25 K | [HuggingFace / Unum][unsplash-25k-hf] |
316
- | [Conceptual Captions 3M][cc-3m-origin] | Images & Descriptions | 3 M | [HuggingFace / Unum][cc-3m-hf] |
317
- | [Arxiv 2M][arxiv-2m-origin] | Titles & Abstracts | 2 M | [HuggingFace / Unum][arxiv-2m-hf] |
322
+ | Dataset | Modalities | Images | Download |
323
+ | :---------------------------------- | --------------------: | -----: | ------------------------------------: |
324
+ | [Unsplash][unsplash-25k-origin] | Images & Descriptions | 25 K | [HuggingFace / Unum][unsplash-25k-hf] |
325
+ | [Conceptual Captions][cc-3m-origin] | Images & Descriptions | 3 M | [HuggingFace / Unum][cc-3m-hf] |
326
+ | [Arxiv][arxiv-2m-origin] | Titles & Abstracts | 2 M | [HuggingFace / Unum][arxiv-2m-hf] |
318
327
 
319
328
  [unsplash-25k-origin]: https://github.com/unsplash/datasets
320
329
  [cc-3m-origin]: https://huggingface.co/datasets/conceptual_captions
@@ -358,15 +367,19 @@ matches = index.search(fingerprints, 10)
358
367
 
359
368
  ### USearch + POI Coordinates = GIS Applications... on iOS?
360
369
 
361
- With Objective-C and iOS bindings, USearch can be easily used in mobile applications
370
+ [![USearch Maps with SwiftUI](https://github.com/ashvardanian/SwiftVectorSearch/raw/main/USearch+SwiftUI.gif)](https://github.com/ashvardanian/SwiftVectorSearch)
362
371
 
372
+ With Objective-C and Swift iOS bindings, USearch can be easily used in mobile applications.
373
+ The [SwiftVectorSearch](https://github.com/ashvardanian/SwiftVectorSearch) project illustrates how to build a dynamic, real-time search system on iOS.
374
+ In this example, we use 2-dimensional vectors—encoded as latitude and longitude—to find the closest Points of Interest (POIs) on a map.
375
+ The search is based on the Haversine distance metric, but can easily be extended to support high-dimensional vectors.
363
376
 
364
377
  ## Integrations
365
378
 
366
379
  - [x] GPTCache: [Python](https://github.com/zilliztech/GPTCache/releases/tag/0.1.29).
367
380
  - [x] LangChain: [Python](https://github.com/langchain-ai/langchain/releases/tag/v0.0.257) and [JavaScipt](https://github.com/hwchase17/langchainjs/releases/tag/0.0.125).
368
381
  - [x] ClickHouse: [C++](https://github.com/ClickHouse/ClickHouse/pull/53447).
369
- - [ ] Microsoft Semantic Kernel: [Python](https://github.com/microsoft/semantic-kernel/pull/2358) and C#.
382
+ - [x] Microsoft Semantic Kernel: [Python](https://github.com/microsoft/semantic-kernel/releases/tag/python-0.3.9.dev) and C#.
370
383
 
371
384
  ## Citations
372
385
 
package/c/lib.cpp CHANGED
@@ -48,18 +48,18 @@ add_result_t add_(index_dense_t* index, usearch_key_t key, void const* vector, s
48
48
  case scalar_kind_t::f32_k: return index->add(key, (f32_t const*)vector);
49
49
  case scalar_kind_t::f64_k: return index->add(key, (f64_t const*)vector);
50
50
  case scalar_kind_t::f16_k: return index->add(key, (f16_t const*)vector);
51
- case scalar_kind_t::i8_k: return index->add(key, (i8_bits_t const*)vector);
51
+ case scalar_kind_t::i8_k: return index->add(key, (i8_t const*)vector);
52
52
  case scalar_kind_t::b1x8_k: return index->add(key, (b1x8_t const*)vector);
53
53
  default: return add_result_t{}.failed("Unknown scalar kind!");
54
54
  }
55
55
  }
56
56
 
57
- bool get_(index_dense_t* index, usearch_key_t key, size_t count, void* vector, scalar_kind_t kind) {
57
+ std::size_t get_(index_dense_t* index, usearch_key_t key, size_t count, void* vector, scalar_kind_t kind) {
58
58
  switch (kind) {
59
59
  case scalar_kind_t::f32_k: return index->get(key, (f32_t*)vector, count);
60
60
  case scalar_kind_t::f64_k: return index->get(key, (f64_t*)vector, count);
61
61
  case scalar_kind_t::f16_k: return index->get(key, (f16_t*)vector, count);
62
- case scalar_kind_t::i8_k: return index->get(key, (i8_bits_t*)vector, count);
62
+ case scalar_kind_t::i8_k: return index->get(key, (i8_t*)vector, count);
63
63
  case scalar_kind_t::b1x8_k: return index->get(key, (b1x8_t*)vector, count);
64
64
  default: return search_result_t().failed("Unknown scalar kind!");
65
65
  }
@@ -70,7 +70,7 @@ search_result_t search_(index_dense_t* index, void const* vector, scalar_kind_t
70
70
  case scalar_kind_t::f32_k: return index->search((f32_t const*)vector, n);
71
71
  case scalar_kind_t::f64_k: return index->search((f64_t const*)vector, n);
72
72
  case scalar_kind_t::f16_k: return index->search((f16_t const*)vector, n);
73
- case scalar_kind_t::i8_k: return index->search((i8_bits_t const*)vector, n);
73
+ case scalar_kind_t::i8_k: return index->search((i8_t const*)vector, n);
74
74
  case scalar_kind_t::b1x8_k: return index->search((b1x8_t const*)vector, n);
75
75
  default: return search_result_t().failed("Unknown scalar kind!");
76
76
  }
@@ -103,6 +103,11 @@ USEARCH_EXPORT void usearch_free(usearch_index_t index, usearch_error_t*) {
103
103
  delete reinterpret_cast<index_dense_t*>(index);
104
104
  }
105
105
 
106
+ USEARCH_EXPORT size_t usearch_serialized_length(usearch_index_t index, usearch_error_t*) {
107
+ assert(index);
108
+ return reinterpret_cast<index_dense_t*>(index)->serialized_length();
109
+ }
110
+
106
111
  USEARCH_EXPORT void usearch_save(usearch_index_t index, char const* path, usearch_error_t* error) {
107
112
 
108
113
  assert(index && path && error);
@@ -127,6 +132,35 @@ USEARCH_EXPORT void usearch_view(usearch_index_t index, char const* path, usearc
127
132
  *error = result.error.release();
128
133
  }
129
134
 
135
+ USEARCH_EXPORT void usearch_save_buffer(usearch_index_t index, void* buffer, size_t length, usearch_error_t* error) {
136
+
137
+ assert(index && buffer && length && error);
138
+ memory_mapped_file_t memory_map((byte_t*)buffer, length);
139
+ serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->save(std::move(memory_map));
140
+ if (!result)
141
+ *error = result.error.release();
142
+ }
143
+
144
+ USEARCH_EXPORT void usearch_load_buffer(usearch_index_t index, void const* buffer, size_t length,
145
+ usearch_error_t* error) {
146
+
147
+ assert(index && buffer && length && error);
148
+ memory_mapped_file_t memory_map((byte_t*)buffer, length);
149
+ serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->load(std::move(memory_map));
150
+ if (!result)
151
+ *error = result.error.release();
152
+ }
153
+
154
+ USEARCH_EXPORT void usearch_view_buffer(usearch_index_t index, void const* buffer, size_t length,
155
+ usearch_error_t* error) {
156
+
157
+ assert(index && buffer && length && error);
158
+ memory_mapped_file_t memory_map((byte_t*)buffer, length);
159
+ serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->view(std::move(memory_map));
160
+ if (!result)
161
+ *error = result.error.release();
162
+ }
163
+
130
164
  USEARCH_EXPORT size_t usearch_size(usearch_index_t index, usearch_error_t*) { //
131
165
  return reinterpret_cast<index_dense_t*>(index)->size();
132
166
  }