usearch 2.8.16 → 2.9.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 (62) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
  2. package/.github/workflows/prerelease.yml +33 -7
  3. package/.github/workflows/release.yml +25 -26
  4. package/.gitmodules +4 -1
  5. package/CITATION.cff +1 -1
  6. package/CMakeLists.txt +6 -8
  7. package/CONTRIBUTING.md +20 -1
  8. package/Cargo.toml +1 -1
  9. package/README.md +7 -6
  10. package/VERSION +1 -1
  11. package/conanfile.py +1 -1
  12. package/cpp/test.cpp +9 -2
  13. package/include/usearch/index.hpp +11 -11
  14. package/include/usearch/index_plugins.hpp +2 -1
  15. package/javascript/usearch.js +1 -1
  16. package/package.json +1 -1
  17. package/pyproject.toml +2 -2
  18. package/setup.py +10 -4
  19. package/simsimd/.releaserc +3 -2
  20. package/simsimd/Cargo.lock +708 -0
  21. package/simsimd/Cargo.toml +36 -0
  22. package/simsimd/README.md +37 -1
  23. package/simsimd/build.rs +20 -0
  24. package/simsimd/include/simsimd/simsimd.h +4 -4
  25. package/simsimd/include/simsimd/spatial.h +1 -1
  26. package/simsimd/include/simsimd/types.h +5 -1
  27. package/simsimd/package.json +1 -1
  28. package/simsimd/rust/benches/cosine.rs +27 -0
  29. package/simsimd/rust/benches/native.rs +27 -0
  30. package/simsimd/rust/benches/sqeuclidean.rs +27 -0
  31. package/simsimd/rust/lib.c +68 -0
  32. package/simsimd/rust/lib.rs +232 -0
  33. package/sqlite/README.md +178 -0
  34. package/sqlite/lib.cpp +325 -0
  35. package/stringzilla/CONTRIBUTING.md +429 -0
  36. package/stringzilla/Cargo.lock +25 -0
  37. package/stringzilla/Cargo.toml +26 -0
  38. package/stringzilla/LICENSE +201 -0
  39. package/stringzilla/README.md +1281 -0
  40. package/stringzilla/VERSION +1 -0
  41. package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
  42. package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
  43. package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
  44. package/stringzilla/binding.gyp +16 -0
  45. package/stringzilla/build.rs +14 -0
  46. package/stringzilla/c/lib.c +304 -0
  47. package/stringzilla/cli/README.md +48 -0
  48. package/stringzilla/cli/split.py +72 -0
  49. package/stringzilla/cli/wc.py +37 -0
  50. package/stringzilla/include/stringzilla/experimental.h +724 -0
  51. package/stringzilla/include/stringzilla/module.modulemap +9 -0
  52. package/stringzilla/include/stringzilla/stringzilla.h +5240 -0
  53. package/stringzilla/include/stringzilla/stringzilla.hpp +3830 -0
  54. package/stringzilla/javascript/lib.c +125 -0
  55. package/stringzilla/javascript/stringzilla.js +22 -0
  56. package/stringzilla/package-ci.json +10 -0
  57. package/stringzilla/package.json +32 -0
  58. package/stringzilla/rust/lib.rs +362 -0
  59. package/stringzilla/swift/StringProtocol+StringZilla.swift +280 -0
  60. package/stringzilla/swift/Test.swift +60 -0
  61. package/wasmer.toml +1 -1
  62. package/simsimd/bench.js +0 -51
@@ -1,7 +1,7 @@
1
1
  name: Report a bug
2
2
  description: Something doesn't work as expected?
3
3
  title: "Bug: "
4
- labels: ["bug", "invalid"]
4
+ labels: ["bug"]
5
5
  assignees:
6
6
  - octocat
7
7
  body:
@@ -61,9 +61,9 @@ jobs:
61
61
  with:
62
62
  node-version: 20
63
63
  - name: Build JavaScript
64
- run: npm install
64
+ run: npm ci
65
65
  - name: Test JavaScript
66
- run: npm ci && npm test
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 install
214
+ run: npm ci
216
215
  - name: Test JavaScript
217
- run: npm ci && npm test
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 install
276
+ run: npm ci
278
277
  - name: Test JavaScript
279
- run: npm ci && npm test
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-22.04, macOS-11, windows-2022]
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@v3
360
+ - uses: actions/checkout@v4
362
361
  with:
363
362
  ref: "main"
364
- - uses: actions/setup-python@v3
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: 23.0.1
371
-
366
+ python-version: 3.x
372
367
  - name: Setup QEMU
373
- if: matrix.os == 'ubuntu-22.04'
374
- uses: docker/setup-qemu-action@v2.1.0
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: python -m cibuildwheel
381
-
382
- - uses: actions/upload-artifact@v3
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@v3.0.2
395
+ uses: actions/download-artifact@v4
399
396
  with:
400
- path: ./dist/
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: ./dist/artifact
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
@@ -5,7 +5,7 @@ authors:
5
5
  given-names: "Ash"
6
6
  orcid: "https://orcid.org/0000-0002-4882-1815"
7
7
  title: "USearch by Unum Cloud"
8
- version: 2.8.16
8
+ version: 2.9.0
9
9
  doi: 10.5281/zenodo.7949416
10
10
  date-released: 2023-10-22
11
11
  url: "https://github.com/unum-cloud/usearch"
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
- if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
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 --platform linux
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
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "usearch"
3
- version = "2.8.16"
3
+ version = "2.9.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
@@ -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] implementation.
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 some of the most loved Datalakes and Databases, like [ClickHouse][clickhouse-docs].
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.8.16},
437
+ version = {2.9.0},
437
438
  year = {2023},
438
439
  month = oct,
439
440
  }
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.8.16
1
+ 2.9.0
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.8.16'
10
+ version = '2.9.0'
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"
package/cpp/test.cpp CHANGED
@@ -209,7 +209,14 @@ void test_cosine(std::size_t collection_size, std::size_t dimensions) {
209
209
  metric_punned_t metric(dimensions, metric_kind_t::cos_k, scalar_kind<scalar_at>());
210
210
  index_dense_config_t config(connectivity);
211
211
  config.multi = multi;
212
- index_t index = index_t::make(metric, config);
212
+ index_t index;
213
+ {
214
+ index_t index_tmp1 = index_t::make(metric, config);
215
+ // move construction
216
+ index_t index_tmp2 = std::move(index_tmp1);
217
+ // move assignment
218
+ index = std::move(index_tmp2);
219
+ }
213
220
  test_cosine<true>(index, matrix);
214
221
  }
215
222
  }
@@ -313,4 +320,4 @@ int main(int, char**) {
313
320
  test_tanimoto<std::int64_t, std::uint32_t>(dimensions, connectivity);
314
321
 
315
322
  return 0;
316
- }
323
+ }
@@ -10,8 +10,8 @@
10
10
  #define UNUM_USEARCH_HPP
11
11
 
12
12
  #define USEARCH_VERSION_MAJOR 2
13
- #define USEARCH_VERSION_MINOR 8
14
- #define USEARCH_VERSION_PATCH 16
13
+ #define USEARCH_VERSION_MINOR 9
14
+ #define USEARCH_VERSION_PATCH 0
15
15
 
16
16
  // Inferring C++ version
17
17
  // https://stackoverflow.com/a/61552074
@@ -1362,7 +1362,7 @@ class output_file_t {
1362
1362
  serialization_result_t write(void const* begin, std::size_t length) noexcept {
1363
1363
  serialization_result_t result;
1364
1364
  std::size_t written = std::fwrite(begin, length, 1, file_);
1365
- if (!written)
1365
+ if (length && !written)
1366
1366
  return result.failed(std::strerror(errno));
1367
1367
  return result;
1368
1368
  }
@@ -1404,7 +1404,7 @@ class input_file_t {
1404
1404
  serialization_result_t read(void* begin, std::size_t length) noexcept {
1405
1405
  serialization_result_t result;
1406
1406
  std::size_t read = std::fread(begin, length, 1, file_);
1407
- if (!read)
1407
+ if (length && !read)
1408
1408
  return result.failed(std::feof(file_) ? "End of file reached!" : std::strerror(errno));
1409
1409
  return result;
1410
1410
  }
@@ -1942,7 +1942,7 @@ class index_gt {
1942
1942
  std::size_t connectivity() const noexcept { return config_.connectivity; }
1943
1943
  std::size_t capacity() const noexcept { return nodes_capacity_; }
1944
1944
  std::size_t size() const noexcept { return nodes_count_; }
1945
- std::size_t max_level() const noexcept { return static_cast<std::size_t>(max_level_); }
1945
+ std::size_t max_level() const noexcept { return nodes_count_ ? static_cast<std::size_t>(max_level_) : 0; }
1946
1946
  index_config_t const& config() const noexcept { return config_; }
1947
1947
  index_limits_t const& limits() const noexcept { return limits_; }
1948
1948
  bool is_immutable() const noexcept { return bool(viewed_file_); }
@@ -3362,7 +3362,7 @@ class index_gt {
3362
3362
  visits.clear();
3363
3363
 
3364
3364
  // Optional prefetching
3365
- if (!std::is_same<typename std::decay<prefetch_at>::type, dummy_prefetch_t>::value)
3365
+ if (!is_dummy<prefetch_at>())
3366
3366
  prefetch(citerator_at(closest_slot), citerator_at(closest_slot + 1));
3367
3367
 
3368
3368
  distance_t closest_dist = context.measure(query, citerator_at(closest_slot), metric);
@@ -3374,7 +3374,7 @@ class index_gt {
3374
3374
  neighbors_ref_t closest_neighbors = neighbors_non_base_(node_at_(closest_slot), level);
3375
3375
 
3376
3376
  // Optional prefetching
3377
- if (!std::is_same<typename std::decay<prefetch_at>::type, dummy_prefetch_t>::value) {
3377
+ if (!is_dummy<prefetch_at>()) {
3378
3378
  candidates_range_t missing_candidates{*this, closest_neighbors, visits};
3379
3379
  prefetch(missing_candidates.begin(), missing_candidates.end());
3380
3380
  }
@@ -3416,7 +3416,7 @@ class index_gt {
3416
3416
  return false;
3417
3417
 
3418
3418
  // Optional prefetching
3419
- if (!std::is_same<typename std::decay<prefetch_at>::type, dummy_prefetch_t>::value)
3419
+ if (!is_dummy<prefetch_at>())
3420
3420
  prefetch(citerator_at(start_slot), citerator_at(start_slot + 1));
3421
3421
 
3422
3422
  distance_t radius = context.measure(query, citerator_at(start_slot), metric);
@@ -3441,7 +3441,7 @@ class index_gt {
3441
3441
  neighbors_ref_t candidate_neighbors = neighbors_(candidate_ref, level);
3442
3442
 
3443
3443
  // Optional prefetching
3444
- if (!std::is_same<typename std::decay<prefetch_at>::type, dummy_prefetch_t>::value) {
3444
+ if (!is_dummy<prefetch_at>()) {
3445
3445
  candidates_range_t missing_candidates{*this, candidate_neighbors, visits};
3446
3446
  prefetch(missing_candidates.begin(), missing_candidates.end());
3447
3447
  }
@@ -3490,7 +3490,7 @@ class index_gt {
3490
3490
  return false;
3491
3491
 
3492
3492
  // Optional prefetching
3493
- if (!std::is_same<typename std::decay<prefetch_at>::type, dummy_prefetch_t>::value)
3493
+ if (!is_dummy<prefetch_at>())
3494
3494
  prefetch(citerator_at(start_slot), citerator_at(start_slot + 1));
3495
3495
 
3496
3496
  distance_t radius = context.measure(query, citerator_at(start_slot), metric);
@@ -3510,7 +3510,7 @@ class index_gt {
3510
3510
  neighbors_ref_t candidate_neighbors = neighbors_base_(node_at_(candidate.slot));
3511
3511
 
3512
3512
  // Optional prefetching
3513
- if (!std::is_same<typename std::decay<prefetch_at>::type, dummy_prefetch_t>::value) {
3513
+ if (!is_dummy<prefetch_at>()) {
3514
3514
  candidates_range_t missing_candidates{*this, candidate_neighbors, visits};
3515
3515
  prefetch(missing_candidates.begin(), missing_candidates.end());
3516
3516
  }
@@ -1820,7 +1820,8 @@ class flat_hash_multi_set_gt {
1820
1820
  }
1821
1821
 
1822
1822
  // Reset populated slots count
1823
- std::memset(data_, 0, buckets_ * bytes_per_bucket());
1823
+ if (data_)
1824
+ std::memset(data_, 0, buckets_ * bytes_per_bucket());
1824
1825
  populated_slots_ = 0;
1825
1826
  }
1826
1827
 
@@ -303,7 +303,7 @@ class Index {
303
303
  */
304
304
  remove(keys) {
305
305
  let normalizedKeys = normalizeKeys(keys);
306
- normalizedResults = this._compiledIndex.remove(normalizedKeys);
306
+ let normalizedResults = this._compiledIndex.remove(normalizedKeys);
307
307
  if (isOneKey(keys))
308
308
  return normalizedResults[0];
309
309
  else
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "2.8.16",
3
+ "version": "2.9.0",
4
4
  "description": "Smaller & Faster Single-File Vector Search Engine from Unum",
5
5
  "author": "Ash Vardanian (https://ashvardanian.com/)",
6
6
  "license": "Apache 2.0",
package/pyproject.toml CHANGED
@@ -16,7 +16,7 @@ filterwarnings = ["error"]
16
16
  test-requires = []
17
17
  test-command = ""
18
18
  build-verbosity = 0
19
- skip = ["*musllinux*", "*i686*", "pp*", "cp36-*", "cp312-*"]
19
+ skip = ["*musllinux*", "*i686*", "pp*", "cp36-*"]
20
20
 
21
21
  [tool.cibuildwheel.linux]
22
22
  before-build = [
@@ -48,4 +48,4 @@ before-build = [
48
48
  "git submodule update --init --recursive",
49
49
  ]
50
50
  archs = ["x86", "AMD64"]
51
- skip = ["*win32*", "pp*", "cp36-*", "cp312-*"]
51
+ skip = ["*win32*", "pp*", "cp36-*"]
package/setup.py CHANGED
@@ -5,6 +5,7 @@ from setuptools import setup
5
5
 
6
6
  from pybind11.setup_helpers import Pybind11Extension
7
7
 
8
+ sources = ["python/lib.cpp"]
8
9
  compile_args = []
9
10
  link_args = []
10
11
  macros_args = []
@@ -127,12 +128,14 @@ if is_windows:
127
128
  ]
128
129
  )
129
130
 
130
- print("macros_args", macros_args)
131
+ if is_linux or is_macos:
132
+ sources.append("sqlite/lib.cpp")
133
+ link_args.append("-lsqlite3")
131
134
 
132
135
  ext_modules = [
133
136
  Pybind11Extension(
134
137
  "usearch.compiled",
135
- ["python/lib.cpp"],
138
+ sources,
136
139
  extra_compile_args=compile_args,
137
140
  extra_link_args=link_args,
138
141
  define_macros=macros_args,
@@ -147,7 +150,11 @@ with open(os.path.join(this_directory, "README.md")) as f:
147
150
  long_description = f.read()
148
151
 
149
152
  # Depending on the macros, adjust the include directories
150
- include_dirs = ["include"]
153
+ include_dirs = [
154
+ "include",
155
+ "python",
156
+ "stringzilla/include",
157
+ ]
151
158
  if use_simsimd:
152
159
  include_dirs.append("simsimd/include")
153
160
  if use_fp16lib:
@@ -190,6 +197,5 @@ setup(
190
197
  install_requires=[
191
198
  "numpy",
192
199
  "tqdm",
193
- 'ucall; python_version >= "3.9"',
194
200
  ],
195
201
  )
@@ -74,9 +74,10 @@
74
74
  {
75
75
  "assets": [
76
76
  "VERSION",
77
- "conanfile.py",
78
77
  "package.json",
79
- "Cargo.toml"
78
+ "Cargo.toml",
79
+ "CMakeLists.txt",
80
+ "include/simsimd/simsimd.h"
80
81
  ],
81
82
  "message": "Build: Released ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
82
83
  }