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.
Files changed (66) 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 +46 -1
  8. package/Cargo.toml +1 -1
  9. package/README.md +7 -6
  10. package/VERSION +1 -1
  11. package/c/lib.cpp +19 -17
  12. package/c/test.c +41 -7
  13. package/c/usearch.h +15 -15
  14. package/conanfile.py +1 -1
  15. package/cpp/test.cpp +9 -2
  16. package/include/usearch/index.hpp +15 -15
  17. package/include/usearch/index_dense.hpp +8 -4
  18. package/include/usearch/index_plugins.hpp +34 -23
  19. package/javascript/usearch.js +1 -1
  20. package/package.json +3 -2
  21. package/pyproject.toml +2 -2
  22. package/setup.py +10 -4
  23. package/simsimd/.releaserc +3 -2
  24. package/simsimd/Cargo.lock +708 -0
  25. package/simsimd/Cargo.toml +36 -0
  26. package/simsimd/README.md +37 -1
  27. package/simsimd/build.rs +20 -0
  28. package/simsimd/include/simsimd/simsimd.h +4 -4
  29. package/simsimd/include/simsimd/spatial.h +1 -1
  30. package/simsimd/include/simsimd/types.h +5 -1
  31. package/simsimd/package.json +1 -1
  32. package/simsimd/rust/benches/cosine.rs +27 -0
  33. package/simsimd/rust/benches/native.rs +27 -0
  34. package/simsimd/rust/benches/sqeuclidean.rs +27 -0
  35. package/simsimd/rust/lib.c +68 -0
  36. package/simsimd/rust/lib.rs +232 -0
  37. package/sqlite/README.md +178 -0
  38. package/sqlite/lib.cpp +325 -0
  39. package/stringzilla/CONTRIBUTING.md +429 -0
  40. package/stringzilla/Cargo.lock +25 -0
  41. package/stringzilla/Cargo.toml +26 -0
  42. package/stringzilla/LICENSE +201 -0
  43. package/stringzilla/README.md +1281 -0
  44. package/stringzilla/VERSION +1 -0
  45. package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
  46. package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
  47. package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
  48. package/stringzilla/binding.gyp +16 -0
  49. package/stringzilla/build.rs +14 -0
  50. package/stringzilla/c/lib.c +304 -0
  51. package/stringzilla/cli/README.md +48 -0
  52. package/stringzilla/cli/split.py +72 -0
  53. package/stringzilla/cli/wc.py +37 -0
  54. package/stringzilla/include/stringzilla/experimental.h +724 -0
  55. package/stringzilla/include/stringzilla/module.modulemap +9 -0
  56. package/stringzilla/include/stringzilla/stringzilla.h +5240 -0
  57. package/stringzilla/include/stringzilla/stringzilla.hpp +3830 -0
  58. package/stringzilla/javascript/lib.c +125 -0
  59. package/stringzilla/javascript/stringzilla.js +22 -0
  60. package/stringzilla/package-ci.json +10 -0
  61. package/stringzilla/package.json +32 -0
  62. package/stringzilla/rust/lib.rs +362 -0
  63. package/stringzilla/swift/StringProtocol+StringZilla.swift +280 -0
  64. package/stringzilla/swift/Test.swift +60 -0
  65. package/wasmer.toml +1 -1
  66. package/simsimd/bench.js +0 -51
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 1
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_); }
@@ -2543,8 +2543,8 @@ class index_gt {
2543
2543
  if (!next.reserve(expansion))
2544
2544
  return result.failed("Out of memory!");
2545
2545
 
2546
- result.cluster.member =
2547
- at(search_for_one_(query, metric, prefetch, entry_slot_, max_level_, level - 1, context));
2546
+ result.cluster.member = at(search_for_one_(query, metric, prefetch, entry_slot_, max_level_,
2547
+ static_cast<level_t>(level - 1), context));
2548
2548
  result.cluster.distance = context.measure(query, result.cluster.member, metric);
2549
2549
 
2550
2550
  // Normalize stats
@@ -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,13 +3416,13 @@ 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);
3423
3423
  next.insert_reserved({-radius, static_cast<compressed_slot_t>(start_slot)});
3424
3424
  top.insert_reserved({radius, static_cast<compressed_slot_t>(start_slot)});
3425
- visits.set(start_slot);
3425
+ visits.set(static_cast<compressed_slot_t>(start_slot));
3426
3426
 
3427
3427
  while (!next.empty()) {
3428
3428
 
@@ -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,13 +3490,13 @@ 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);
3497
3497
  next.insert_reserved({-radius, static_cast<compressed_slot_t>(start_slot)});
3498
3498
  top.insert_reserved({radius, static_cast<compressed_slot_t>(start_slot)});
3499
- visits.set(start_slot);
3499
+ visits.set(static_cast<compressed_slot_t>(start_slot));
3500
3500
 
3501
3501
  while (!next.empty()) {
3502
3502
 
@@ -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
  }
@@ -199,7 +199,7 @@ inline index_dense_metadata_result_t index_dense_metadata_from_path(char const*
199
199
 
200
200
  // Check if it starts with 32-bit
201
201
  if (offset_if_u32 + sizeof(index_dense_head_buffer_t) < file_size) {
202
- if (std::fseek(file.get(), offset_if_u32, SEEK_SET) != 0)
202
+ if (std::fseek(file.get(), static_cast<long>(offset_if_u32), SEEK_SET) != 0)
203
203
  return result.failed(std::strerror(errno));
204
204
  read = std::fread(result.head_buffer, sizeof(index_dense_head_buffer_t), 1, file.get());
205
205
  if (!read)
@@ -213,7 +213,7 @@ inline index_dense_metadata_result_t index_dense_metadata_from_path(char const*
213
213
 
214
214
  // Check if it starts with 64-bit
215
215
  if (offset_if_u64 + sizeof(index_dense_head_buffer_t) < file_size) {
216
- if (std::fseek(file.get(), offset_if_u64, SEEK_SET) != 0)
216
+ if (std::fseek(file.get(), static_cast<long>(offset_if_u64), SEEK_SET) != 0)
217
217
  return result.failed(std::strerror(errno));
218
218
  read = std::fread(result.head_buffer, sizeof(index_dense_head_buffer_t), 1, file.get());
219
219
  if (!read)
@@ -929,8 +929,10 @@ class index_dense_gt {
929
929
  if (head.kind_compressed_slot != unum::usearch::scalar_kind<compressed_slot_t>())
930
930
  return result.failed("Slot type doesn't match, consider rebuilding");
931
931
 
932
- metric_ = metric_t(head.dimensions, head.kind_metric, head.kind_scalar);
933
932
  config_.multi = head.multi;
933
+ metric_ = metric_t(head.dimensions, head.kind_metric, head.kind_scalar);
934
+ cast_buffer_.resize(available_threads_.size() * metric_.bytes_per_vector());
935
+ casts_ = make_casts_(head.kind_scalar);
934
936
  }
935
937
 
936
938
  // Pull the actual proximity graph
@@ -1013,8 +1015,10 @@ class index_dense_gt {
1013
1015
  if (head.kind_compressed_slot != unum::usearch::scalar_kind<compressed_slot_t>())
1014
1016
  return result.failed("Slot type doesn't match, consider rebuilding");
1015
1017
 
1016
- metric_ = metric_t(head.dimensions, head.kind_metric, head.kind_scalar);
1017
1018
  config_.multi = head.multi;
1019
+ metric_ = metric_t(head.dimensions, head.kind_metric, head.kind_scalar);
1020
+ cast_buffer_.resize(available_threads_.size() * metric_.bytes_per_vector());
1021
+ casts_ = make_casts_(head.kind_scalar);
1018
1022
  offset += sizeof(buffer);
1019
1023
  }
1020
1024
 
@@ -1006,10 +1006,11 @@ template <typename scalar_at = float, typename result_at = scalar_at> struct met
1006
1006
  #elif defined(USEARCH_DEFINED_GCC)
1007
1007
  #pragma GCC ivdep
1008
1008
  #endif
1009
- for (std::size_t i = 0; i != dim; ++i)
1010
- ab += result_t(a[i]) * result_t(b[i]), //
1011
- a2 += square<result_t>(a[i]), //
1012
- b2 += square<result_t>(b[i]);
1009
+ for (std::size_t i = 0; i != dim; ++i) {
1010
+ result_t ai = static_cast<result_t>(a[i]);
1011
+ result_t bi = static_cast<result_t>(b[i]);
1012
+ ab += ai * bi, a2 += square(ai), b2 += square(bi);
1013
+ }
1013
1014
 
1014
1015
  result_t result_if_zero[2][2];
1015
1016
  result_if_zero[0][0] = 1 - ab / (std::sqrt(a2) * std::sqrt(b2));
@@ -1036,8 +1037,11 @@ template <typename scalar_at = float, typename result_at = scalar_at> struct met
1036
1037
  #elif defined(USEARCH_DEFINED_GCC)
1037
1038
  #pragma GCC ivdep
1038
1039
  #endif
1039
- for (std::size_t i = 0; i != dim; ++i)
1040
- ab_deltas_sq += square(result_t(a[i]) - result_t(b[i]));
1040
+ for (std::size_t i = 0; i != dim; ++i) {
1041
+ result_t ai = static_cast<result_t>(a[i]);
1042
+ result_t bi = static_cast<result_t>(b[i]);
1043
+ ab_deltas_sq += square(ai - bi);
1044
+ }
1041
1045
  return ab_deltas_sq;
1042
1046
  }
1043
1047
  };
@@ -1095,9 +1099,10 @@ template <typename scalar_at = std::uint64_t, typename result_at = float> struct
1095
1099
  #elif defined(USEARCH_DEFINED_GCC)
1096
1100
  #pragma GCC ivdep
1097
1101
  #endif
1098
- for (std::size_t i = 0; i != words; ++i)
1099
- and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count(),
1100
- or_count += std::bitset<bits_per_word_k>(a[i] | b[i]).count();
1102
+ for (std::size_t i = 0; i != words; ++i) {
1103
+ and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count();
1104
+ or_count += std::bitset<bits_per_word_k>(a[i] | b[i]).count();
1105
+ }
1101
1106
  return 1 - result_t(and_count) / or_count;
1102
1107
  }
1103
1108
  };
@@ -1126,9 +1131,10 @@ template <typename scalar_at = std::uint64_t, typename result_at = float> struct
1126
1131
  #elif defined(USEARCH_DEFINED_GCC)
1127
1132
  #pragma GCC ivdep
1128
1133
  #endif
1129
- for (std::size_t i = 0; i != words; ++i)
1130
- and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count(),
1131
- any_count += std::bitset<bits_per_word_k>(a[i]).count() + std::bitset<bits_per_word_k>(b[i]).count();
1134
+ for (std::size_t i = 0; i != words; ++i) {
1135
+ and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count();
1136
+ any_count += std::bitset<bits_per_word_k>(a[i]).count() + std::bitset<bits_per_word_k>(b[i]).count();
1137
+ }
1132
1138
  return 1 - 2 * result_t(and_count) / any_count;
1133
1139
  }
1134
1140
  };
@@ -1176,11 +1182,13 @@ template <typename scalar_at = float, typename result_at = float> struct metric_
1176
1182
  #pragma GCC ivdep
1177
1183
  #endif
1178
1184
  for (std::size_t i = 0; i != dim; ++i) {
1179
- a_sum += result_t(a[i]);
1180
- b_sum += result_t(b[i]);
1181
- ab_sum += result_t(a[i]) * result_t(b[i]);
1182
- a_sq_sum += result_t(a[i]) * result_t(a[i]);
1183
- b_sq_sum += result_t(b[i]) * result_t(b[i]);
1185
+ result_t ai = static_cast<result_t>(a[i]);
1186
+ result_t bi = static_cast<result_t>(b[i]);
1187
+ a_sum += ai;
1188
+ b_sum += bi;
1189
+ ab_sum += ai * bi;
1190
+ a_sq_sum += ai * ai;
1191
+ b_sq_sum += bi * bi;
1184
1192
  }
1185
1193
  result_t denom = std::sqrt((dim * a_sq_sum - a_sum * a_sum) * (dim * b_sq_sum - b_sum * b_sum));
1186
1194
  result_t corr = (dim * ab_sum - a_sum * b_sum) / denom;
@@ -1197,7 +1205,7 @@ template <typename scalar_at = float, typename result_at = float> struct metric_
1197
1205
 
1198
1206
  inline result_t operator()(scalar_t const* p, scalar_t const* q, std::size_t dim) const noexcept {
1199
1207
  result_t kld_pm{}, kld_qm{};
1200
- scalar_t epsilon = std::numeric_limits<scalar_t>::epsilon();
1208
+ result_t epsilon = std::numeric_limits<result_t>::epsilon();
1201
1209
  #if USEARCH_USE_OPENMP
1202
1210
  #pragma omp simd reduction(+ : kld_pm, kld_qm)
1203
1211
  #elif defined(USEARCH_DEFINED_CLANG)
@@ -1206,9 +1214,11 @@ template <typename scalar_at = float, typename result_at = float> struct metric_
1206
1214
  #pragma GCC ivdep
1207
1215
  #endif
1208
1216
  for (std::size_t i = 0; i != dim; ++i) {
1209
- result_t mi = result_t(p[i] + q[i]) / 2 + epsilon;
1210
- kld_pm += p[i] * std::log((p[i] + epsilon) / mi);
1211
- kld_qm += q[i] * std::log((q[i] + epsilon) / mi);
1217
+ result_t pi = static_cast<result_t>(p[i]);
1218
+ result_t qi = static_cast<result_t>(q[i]);
1219
+ result_t mi = (pi + qi) / 2 + epsilon;
1220
+ kld_pm += pi * std::log((pi + epsilon) / mi);
1221
+ kld_qm += qi * std::log((qi + epsilon) / mi);
1212
1222
  }
1213
1223
  return (kld_pm + kld_qm) / 2;
1214
1224
  }
@@ -1253,7 +1263,7 @@ struct l2sq_i8_t {
1253
1263
  #endif
1254
1264
  for (std::size_t i = 0; i != dim; i++)
1255
1265
  ab_deltas_sq += square(std::int16_t(a[i]) - std::int16_t(b[i]));
1256
- return ab_deltas_sq;
1266
+ return static_cast<result_t>(ab_deltas_sq);
1257
1267
  }
1258
1268
  };
1259
1269
 
@@ -1820,7 +1830,8 @@ class flat_hash_multi_set_gt {
1820
1830
  }
1821
1831
 
1822
1832
  // Reset populated slots count
1823
- std::memset(data_, 0, buckets_ * bytes_per_bucket());
1833
+ if (data_)
1834
+ std::memset(data_, 0, buckets_ * bytes_per_bucket());
1824
1835
  populated_slots_ = 0;
1825
1836
  }
1826
1837
 
@@ -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.1",
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",
@@ -34,7 +34,8 @@
34
34
  "exports": {
35
35
  ".": {
36
36
  "types": "./javascript/types/usearch.d.ts",
37
- "require": "./javascript/usearch.js"
37
+ "require": "./javascript/usearch.js",
38
+ "import": "./javascript/usearch.js"
38
39
  },
39
40
  "./package.json": "./package.json"
40
41
  },
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
  }