usearch 2.9.1 → 2.10.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 (169) hide show
  1. package/README.md +50 -52
  2. package/javascript/{types → dist/cjs}/usearch.d.ts +90 -115
  3. package/javascript/dist/cjs/usearch.js +531 -0
  4. package/javascript/dist/esm/usearch.d.ts +212 -0
  5. package/javascript/{usearch.js → dist/esm/usearch.js} +202 -153
  6. package/package.json +25 -23
  7. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  8. package/prebuilds/linux-arm64/usearch.node +0 -0
  9. package/prebuilds/linux-x64/usearch.node +0 -0
  10. package/prebuilds/win32-ia32/usearch.node +0 -0
  11. package/prebuilds/win32-x64/usearch.node +0 -0
  12. package/.clang-format +0 -10
  13. package/.clang-tidy +0 -60
  14. package/.cmake-format.py +0 -19
  15. package/.dockerignore +0 -93
  16. package/.gitattributes +0 -9
  17. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
  18. package/.github/ISSUE_TEMPLATE/config.yml +0 -5
  19. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -64
  20. package/.github/workflows/Dockerfile.libs +0 -36
  21. package/.github/workflows/prerelease.yml +0 -331
  22. package/.github/workflows/release.yml +0 -722
  23. package/.github/workflows/update_version.sh +0 -15
  24. package/.gitmodules +0 -9
  25. package/.releaserc +0 -90
  26. package/CITATION.cff +0 -11
  27. package/CMakeLists.txt +0 -324
  28. package/CODE_OF_CONDUCT.md +0 -128
  29. package/CONTRIBUTING.md +0 -353
  30. package/Cargo.toml +0 -19
  31. package/Dockerfile +0 -16
  32. package/VERSION +0 -1
  33. package/assets/unum.png +0 -0
  34. package/assets/usearch-approaches-transparent.png +0 -0
  35. package/assets/usearch-approaches-white.png +0 -0
  36. package/assets/usearch-neighbor-types.png +0 -0
  37. package/binding.gyp +0 -87
  38. package/build.gradle +0 -204
  39. package/build.rs +0 -18
  40. package/c/CMakeLists.txt +0 -25
  41. package/c/README.md +0 -34
  42. package/c/lib.cpp +0 -358
  43. package/c/test.c +0 -374
  44. package/c/usearch.h +0 -311
  45. package/cmake/clipp.cmake +0 -7
  46. package/cmake/config.cmake.in +0 -15
  47. package/cmake/emscripten.cmake +0 -8
  48. package/cmake/jemalloc.cmake +0 -62
  49. package/cmake/pkg-config.pc.in +0 -4
  50. package/cmake/usearchConfigVersion.cmake.in +0 -20
  51. package/conanfile.py +0 -26
  52. package/cpp/CMakeLists.txt +0 -14
  53. package/cpp/README.md +0 -161
  54. package/cpp/bench.cpp +0 -618
  55. package/cpp/test.cpp +0 -323
  56. package/fp16/CMakeLists.txt +0 -176
  57. package/fp16/LICENSE +0 -11
  58. package/fp16/README.md +0 -20
  59. package/fp16/bench/alt-element.cc +0 -89
  60. package/fp16/bench/from-alt-array.cc +0 -175
  61. package/fp16/bench/from-ieee-array.cc +0 -399
  62. package/fp16/bench/ieee-element.cc +0 -272
  63. package/fp16/bench/to-alt-array.cc +0 -91
  64. package/fp16/bench/to-ieee-array.cc +0 -303
  65. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  66. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  67. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  68. package/fp16/configure.py +0 -65
  69. package/fp16/confu.yaml +0 -8
  70. package/fp16/include/fp16/__init__.py +0 -0
  71. package/fp16/include/fp16/avx.py +0 -50
  72. package/fp16/include/fp16/avx2.py +0 -53
  73. package/fp16/include/fp16/bitcasts.h +0 -92
  74. package/fp16/include/fp16/fp16.h +0 -451
  75. package/fp16/include/fp16/psimd.h +0 -131
  76. package/fp16/include/fp16.h +0 -11
  77. package/fp16/jni/Android.mk +0 -6
  78. package/fp16/jni/Application.mk +0 -4
  79. package/fp16/test/alt-from-fp32-value.cc +0 -498
  80. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  81. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  82. package/fp16/test/alt-to-fp32-value.cc +0 -348
  83. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  84. package/fp16/test/bitcasts.cc +0 -56
  85. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  86. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  87. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  88. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  89. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  90. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  91. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  92. package/fp16/test/peachpy/stubs.py +0 -38
  93. package/fp16/test/tables.cc +0 -530
  94. package/fp16/test/tables.h +0 -13
  95. package/fp16/third-party/THHalf.h +0 -92
  96. package/fp16/third-party/eigen-half.h +0 -170
  97. package/fp16/third-party/float16-compressor.h +0 -80
  98. package/fp16/third-party/half.hpp +0 -2916
  99. package/fp16/third-party/npy-halffloat.h +0 -328
  100. package/include/usearch/index.hpp +0 -3836
  101. package/include/usearch/index_dense.hpp +0 -2004
  102. package/include/usearch/index_plugins.hpp +0 -2203
  103. package/javascript/lib.cpp +0 -341
  104. package/javascript/types/usearch.d.ts.map +0 -1
  105. package/javascript/usearch.test.js +0 -74
  106. package/package-ci.json +0 -10
  107. package/pyproject.toml +0 -51
  108. package/setup.py +0 -201
  109. package/simsimd/.releaserc +0 -86
  110. package/simsimd/Cargo.lock +0 -708
  111. package/simsimd/Cargo.toml +0 -36
  112. package/simsimd/LICENSE +0 -201
  113. package/simsimd/README.md +0 -275
  114. package/simsimd/binding.gyp +0 -36
  115. package/simsimd/build.rs +0 -20
  116. package/simsimd/include/simsimd/binary.h +0 -201
  117. package/simsimd/include/simsimd/probability.h +0 -548
  118. package/simsimd/include/simsimd/simsimd.h +0 -456
  119. package/simsimd/include/simsimd/spatial.h +0 -1175
  120. package/simsimd/include/simsimd/types.h +0 -207
  121. package/simsimd/javascript/bench.js +0 -127
  122. package/simsimd/javascript/fallback.ts +0 -193
  123. package/simsimd/javascript/lib.c +0 -102
  124. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  125. package/simsimd/javascript/simsimd.ts +0 -124
  126. package/simsimd/javascript/test.mjs +0 -153
  127. package/simsimd/javascript/tsconfig-base.json +0 -25
  128. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  129. package/simsimd/javascript/tsconfig-esm.json +0 -8
  130. package/simsimd/package-lock.json +0 -1688
  131. package/simsimd/package.json +0 -61
  132. package/simsimd/rust/benches/cosine.rs +0 -27
  133. package/simsimd/rust/benches/native.rs +0 -27
  134. package/simsimd/rust/benches/sqeuclidean.rs +0 -27
  135. package/simsimd/rust/lib.c +0 -68
  136. package/simsimd/rust/lib.rs +0 -232
  137. package/sqlite/README.md +0 -178
  138. package/sqlite/lib.cpp +0 -325
  139. package/stringzilla/CONTRIBUTING.md +0 -429
  140. package/stringzilla/Cargo.lock +0 -25
  141. package/stringzilla/Cargo.toml +0 -26
  142. package/stringzilla/LICENSE +0 -201
  143. package/stringzilla/README.md +0 -1281
  144. package/stringzilla/VERSION +0 -1
  145. package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
  146. package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
  147. package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
  148. package/stringzilla/binding.gyp +0 -16
  149. package/stringzilla/build.rs +0 -14
  150. package/stringzilla/c/lib.c +0 -304
  151. package/stringzilla/cli/README.md +0 -48
  152. package/stringzilla/cli/split.py +0 -72
  153. package/stringzilla/cli/wc.py +0 -37
  154. package/stringzilla/include/stringzilla/experimental.h +0 -724
  155. package/stringzilla/include/stringzilla/module.modulemap +0 -9
  156. package/stringzilla/include/stringzilla/stringzilla.h +0 -5240
  157. package/stringzilla/include/stringzilla/stringzilla.hpp +0 -3830
  158. package/stringzilla/javascript/lib.c +0 -125
  159. package/stringzilla/javascript/stringzilla.js +0 -22
  160. package/stringzilla/package-ci.json +0 -10
  161. package/stringzilla/package.json +0 -32
  162. package/stringzilla/rust/lib.rs +0 -362
  163. package/stringzilla/swift/StringProtocol+StringZilla.swift +0 -280
  164. package/stringzilla/swift/Test.swift +0 -60
  165. package/tsconfig.json +0 -21
  166. package/wasmer.toml +0 -12
  167. package/winlibinstaller.bat +0 -42
  168. /package/{simsimd/javascript/dist-package-cjs.json → javascript/dist/cjs/package.json} +0 -0
  169. /package/{simsimd/javascript/dist-package-esm.json → javascript/dist/esm/package.json} +0 -0
@@ -1,61 +0,0 @@
1
- {
2
- "name": "simsimd",
3
- "version": "3.8.0",
4
- "description": "Fastest SIMD-Accelerated Vector Similarity Functions for x86 and Arm",
5
- "homepage": "https://github.com/ashvardanian/simsimd",
6
- "author": "Ash Vardanian",
7
- "license": "Apache 2.0",
8
- "keywords": [
9
- "vector",
10
- "distance",
11
- "similarity",
12
- "search",
13
- "ai",
14
- "math",
15
- "avx2",
16
- "avx512",
17
- "neon",
18
- "sve",
19
- "arm",
20
- "x86",
21
- "simd",
22
- "f16"
23
- ],
24
- "scripts": {
25
- "install": "node-gyp-build",
26
- "prebuild-single": "prebuildify --napi --strip --target=10.4.0",
27
- "prebuild-arm64": "prebuildify --arch arm64 --napi --strip --target=10.4.0",
28
- "prebuild-darwin-x64+arm64": "prebuildify --arch arm64+x64 --napi --strip --target=10.4.0",
29
- "build-js": "rm -fr javascript/dist/* && tsc -p javascript/tsconfig-esm.json && tsc -p javascript/tsconfig-cjs.json && cp javascript/dist-package-esm.json javascript/dist/esm/package.json && cp javascript/dist-package-cjs.json javascript/dist/cjs/package.json",
30
- "test": "node --test ./javascript/test.mjs",
31
- "bench": "node ./javascript/bench.js"
32
- },
33
- "main": "javascript/dist/cjs/simsimd.js",
34
- "module": "javascript/dist/esm/simsimd.js",
35
- "exports": {
36
- ".": {
37
- "import": "./javascript/dist/esm/simsimd.js",
38
- "require": "./javascript/dist/cjs/simsimd.js"
39
- }
40
- },
41
- "engines": {
42
- "node": "~10 >=10.20 || >=12.17"
43
- },
44
- "dependencies": {
45
- "@types/node": "^20.10.7",
46
- "bindings": "^1.5.0",
47
- "node-addon-api": "^3.2.1",
48
- "node-gyp-build": "^4.8.0"
49
- },
50
- "devDependencies": {
51
- "@types/bindings": "^1.5.5",
52
- "node-gyp": "^10.0.1",
53
- "prebuildify": "^6.0.0",
54
- "typescript": "^5.3.3"
55
- },
56
- "optionalDependencies": {
57
- "benchmark": "^2.1.4",
58
- "mathjs": "^11.11.2",
59
- "usearch": "^2.8.15"
60
- }
61
- }
@@ -1,27 +0,0 @@
1
- use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
2
- use simsimd::SimSIMD;
3
-
4
- mod native;
5
-
6
- const DIMENSIONS: usize = 1536;
7
-
8
- pub fn cosine_benchmark(c: &mut Criterion) {
9
- let inputs: (Vec<f32>, Vec<f32>) = (
10
- native::generate_random_vector(DIMENSIONS),
11
- native::generate_random_vector(DIMENSIONS),
12
- );
13
-
14
- let mut group = c.benchmark_group("SIMD Cosine");
15
-
16
- for i in 0..=5 {
17
- group.bench_with_input(BenchmarkId::new("SimSIMD", i), &i, |b, _| {
18
- b.iter(|| SimSIMD::cosine(&inputs.0, &inputs.1))
19
- });
20
- group.bench_with_input(BenchmarkId::new("Rust Native", i), &i, |b, _| {
21
- b.iter(|| native::cosine_similarity_cpu(&inputs.0, &inputs.1))
22
- });
23
- }
24
- }
25
-
26
- criterion_group!(benches, cosine_benchmark);
27
- criterion_main!(benches);
@@ -1,27 +0,0 @@
1
- #![allow(unused)]
2
- use rand::Rng;
3
-
4
- pub(crate) fn generate_random_vector(dim: usize) -> Vec<f32> {
5
- (0..dim).map(|_| rand::thread_rng().gen()).collect()
6
- }
7
-
8
- pub(crate) fn cosine_similarity_cpu(a: &[f32], b: &[f32]) -> Option<f32> {
9
- if a.len() != b.len() {
10
- return None;
11
- }
12
-
13
- let dot_product: f32 = a.iter().zip(b.iter()).map(|(a, b)| a * b).sum();
14
- let norm_a: f32 = a.iter().map(|a| a.powf(2.0)).sum();
15
- let norm_b: f32 = b.iter().map(|b| b.powf(2.0)).sum();
16
-
17
- Some(1.0 - (dot_product / (norm_a.sqrt() * norm_b.sqrt())))
18
- }
19
-
20
- pub(crate) fn squared_euclidean_cpu(a: &[f32], b: &[f32]) -> f32 {
21
- assert_eq!(a.len(), b.len());
22
-
23
- a.iter()
24
- .zip(b.iter())
25
- .map(|(x, y)| ((*x) - (*y)) * ((*x) - (*y)))
26
- .fold(0.0, ::std::ops::Add::add)
27
- }
@@ -1,27 +0,0 @@
1
- use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
2
- use simsimd::SimSIMD;
3
-
4
- mod native;
5
-
6
- const DIMENSIONS: usize = 1536;
7
-
8
- pub fn sqeuclidean_benchmark(c: &mut Criterion) {
9
- let inputs: (Vec<f32>, Vec<f32>) = (
10
- native::generate_random_vector(DIMENSIONS),
11
- native::generate_random_vector(DIMENSIONS),
12
- );
13
-
14
- let mut group = c.benchmark_group("SIMD SqEuclidean");
15
-
16
- for i in 0..=5 {
17
- group.bench_with_input(BenchmarkId::new("SimSIMD", i), &i, |b, _| {
18
- b.iter(|| SimSIMD::sqeuclidean(&inputs.0, &inputs.1))
19
- });
20
- group.bench_with_input(BenchmarkId::new("Rust Native", i), &i, |b, _| {
21
- b.iter(|| native::squared_euclidean_cpu(&inputs.0, &inputs.1))
22
- });
23
- }
24
- }
25
-
26
- criterion_group!(benches, sqeuclidean_benchmark);
27
- criterion_main!(benches);
@@ -1,68 +0,0 @@
1
- #include <simsimd/simsimd.h>
2
-
3
- simsimd_capability_t cached_capabilities(void) {
4
- static simsimd_capability_t static_capabilities = 0;
5
- if (static_capabilities == 0)
6
- static_capabilities = simsimd_capabilities();
7
- return static_capabilities;
8
- }
9
-
10
- simsimd_f32_t cosine_i8(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t d) {
11
- static simsimd_metric_punned_t metric = 0;
12
- if (metric == 0) {
13
- simsimd_capability_t used_capability;
14
- simsimd_find_metric_punned(simsimd_metric_cosine_k, simsimd_datatype_i8_k, cached_capabilities(),
15
- simsimd_cap_any_k, &metric, &used_capability);
16
- }
17
- return metric(a, b, d, d);
18
- }
19
-
20
- simsimd_f32_t cosine_f32(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t d) {
21
- static simsimd_metric_punned_t metric = 0;
22
- if (metric == 0) {
23
- simsimd_capability_t used_capability;
24
- simsimd_find_metric_punned(simsimd_metric_cosine_k, simsimd_datatype_f32_k, cached_capabilities(),
25
- simsimd_cap_any_k, &metric, &used_capability);
26
- }
27
- return metric(a, b, d, d);
28
- }
29
-
30
- simsimd_f32_t inner_i8(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t d) {
31
- static simsimd_metric_punned_t metric = 0;
32
- if (metric == 0) {
33
- simsimd_capability_t used_capability;
34
- simsimd_find_metric_punned(simsimd_metric_inner_k, simsimd_datatype_i8_k, cached_capabilities(),
35
- simsimd_cap_any_k, &metric, &used_capability);
36
- }
37
- return metric(a, b, d, d);
38
- }
39
-
40
- simsimd_f32_t inner_f32(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t d) {
41
- static simsimd_metric_punned_t metric = 0;
42
- if (metric == 0) {
43
- simsimd_capability_t used_capability;
44
- simsimd_find_metric_punned(simsimd_metric_inner_k, simsimd_datatype_f32_k, cached_capabilities(),
45
- simsimd_cap_any_k, &metric, &used_capability);
46
- }
47
- return metric(a, b, d, d);
48
- }
49
-
50
- simsimd_f32_t sqeuclidean_i8(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t d) {
51
- static simsimd_metric_punned_t metric = 0;
52
- if (metric == 0) {
53
- simsimd_capability_t used_capability;
54
- simsimd_find_metric_punned(simsimd_metric_sqeuclidean_k, simsimd_datatype_i8_k, cached_capabilities(),
55
- simsimd_cap_any_k, &metric, &used_capability);
56
- }
57
- return metric(a, b, d, d);
58
- }
59
-
60
- simsimd_f32_t sqeuclidean_f32(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t d) {
61
- static simsimd_metric_punned_t metric = 0;
62
- if (metric == 0) {
63
- simsimd_capability_t used_capability;
64
- simsimd_find_metric_punned(simsimd_metric_sqeuclidean_k, simsimd_datatype_f32_k, cached_capabilities(),
65
- simsimd_cap_any_k, &metric, &used_capability);
66
- }
67
- return metric(a, b, d, d);
68
- }
@@ -1,232 +0,0 @@
1
- //! # SimSIMD - Hardware-Accelerated Similarity Metrics and Distance Functions
2
- //!
3
- //! * Zero-dependency header-only C 99 library with bindings for Python, JavaScript and Rust.
4
- //! * Targets ARM NEON, SVE, x86 AVX2, AVX-512 (VNNI, FP16) hardware backends.
5
- //! * Zero-copy compatible with NumPy, PyTorch, TensorFlow, and other tensors.
6
- //! * Handles f64 double-, f32 single-, and f16 half-precision, i8 integral, and binary vectors.
7
- //! * Up to 200x faster than scipy.spatial.distance and numpy.inner.
8
- //! * Used in USearch and several DBMS products.
9
- //!
10
- //! ## Implemented distance functions include:
11
- //!
12
- //! * Euclidean (L2), Inner Distance, and Cosine (Angular) spatial distances.
13
- //! * Hamming (~ Manhattan) and Jaccard (~ Tanimoto) binary distances.
14
- //! * Kullback-Leibler and Jensen–Shannon divergences for probability distributions.
15
- //!
16
- //! The functions in this module are exposed through a trait `SimSIMD`, which is
17
- //! implemented for types with SIMD support (e.g., i8 and f32). The trait provides
18
- //! methods for computing cosine similarity, inner product, and squared Euclidean
19
- //! distance between slices of these types.
20
- //!
21
- //! # Example
22
- //!
23
- //! ```rust
24
- //! use simsimd::SimSIMD;
25
- //!
26
- //! let a = &[1, 2, 3];
27
- //! let b = &[4, 5, 6];
28
- //!
29
- //! // Compute cosine similarity
30
- //! let cosine_sim = i8::cosine(a, b);
31
- //!
32
- //! // Compute inner product
33
- //! let inner_product = i8::inner(a, b);
34
- //!
35
- //! // Compute squared Euclidean distance
36
- //! let sqeuclidean_dist = i8::sqeuclidean(a, b);
37
- //! ```
38
- //!
39
- //! # Safety
40
- //!
41
- //! The functions declared in the `extern "C"` block are low-level bindings to
42
- //! SimSIMD implementation. It is crucial to ensure that the input slices have the
43
- //! same length (`c` parameter) to avoid undefined behavior.
44
- //!
45
- //!
46
- //! # Trait Implementation
47
- //!
48
- //! The `SimSIMD` trait is implemented for types with SIMD support and provides
49
- //! three associated methods:
50
- //!
51
- //! - `cosine(a: &[Self], b: &[Self]) -> Option<f32>`: Computes cosine similarity between two slices.
52
- //! - `inner(a: &[Self], b: &[Self]) -> Option<f32>`: Computes inner product between two slices.
53
- //! - `sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32>`: Computes squared Euclidean distance between two slices.
54
- //!
55
- #![allow(non_camel_case_types)]
56
-
57
- extern "C" {
58
- /// Computes cosine similarity for i8 types.
59
- fn cosine_i8(a: *const i8, b: *const i8, c: usize) -> f32;
60
-
61
- /// Computes cosine similarity for f32 types.
62
- fn cosine_f32(a: *const f32, b: *const f32, c: usize) -> f32;
63
-
64
- /// Computes inner product for i8 types.
65
- fn inner_i8(a: *const i8, b: *const i8, c: usize) -> f32;
66
-
67
- /// Computes inner product for f32 types.
68
- fn inner_f32(a: *const f32, b: *const f32, c: usize) -> f32;
69
-
70
- /// Computes squared Euclidean distance for i8 types.
71
- fn sqeuclidean_i8(a: *const i8, b: *const i8, c: usize) -> f32;
72
-
73
- /// Computes squared Euclidean distance for f32 types.
74
- fn sqeuclidean_f32(a: *const f32, b: *const f32, c: usize) -> f32;
75
- }
76
-
77
- /// A trait for SIMD similarity functions.
78
- pub trait SimSIMD
79
- where
80
- Self: Sized,
81
- {
82
- /// Computes cosine similarity between two slices.
83
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32>;
84
-
85
- /// Computes inner product between two slices.
86
- fn inner(a: &[Self], b: &[Self]) -> Option<f32>;
87
-
88
- /// Computes squared Euclidean distance between two slices.
89
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32>;
90
- }
91
-
92
- impl SimSIMD for i8 {
93
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32> {
94
- if a.len() != b.len() {
95
- return None;
96
- }
97
-
98
- let operation = unsafe { cosine_i8(a.as_ptr(), b.as_ptr(), a.len()) };
99
-
100
- Some(operation)
101
- }
102
-
103
- fn inner(a: &[Self], b: &[Self]) -> Option<f32> {
104
- if a.len() != b.len() {
105
- return None;
106
- }
107
-
108
- let operation = unsafe { inner_i8(a.as_ptr(), b.as_ptr(), a.len()) };
109
-
110
- Some(operation)
111
- }
112
-
113
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32> {
114
- if a.len() != b.len() {
115
- return None;
116
- }
117
-
118
- let operation = unsafe { sqeuclidean_i8(a.as_ptr(), b.as_ptr(), a.len()) };
119
-
120
- Some(operation)
121
- }
122
- }
123
-
124
- impl SimSIMD for f32 {
125
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32> {
126
- if a.len() != b.len() {
127
- return None;
128
- }
129
-
130
- let operation = unsafe { cosine_f32(a.as_ptr(), b.as_ptr(), a.len()) };
131
-
132
- Some(operation)
133
- }
134
-
135
- fn inner(a: &[Self], b: &[Self]) -> Option<f32> {
136
- if a.len() != b.len() {
137
- return None;
138
- }
139
-
140
- let operation = unsafe { inner_f32(a.as_ptr(), b.as_ptr(), a.len()) };
141
-
142
- Some(operation)
143
- }
144
-
145
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32> {
146
- if a.len() != b.len() {
147
- return None;
148
- }
149
-
150
- let operation = unsafe { sqeuclidean_f32(a.as_ptr(), b.as_ptr(), a.len()) };
151
-
152
- Some(operation)
153
- }
154
- }
155
-
156
- #[cfg(test)]
157
- mod tests {
158
- use super::*;
159
- //
160
- fn assert_almost_equal(left: f32, right: f32, tolerance: f32) {
161
- let lower = right - tolerance;
162
- let upper = right + tolerance;
163
-
164
- assert!(left >= lower && left <= upper);
165
- }
166
-
167
- #[test]
168
- fn test_cosine_i8() {
169
- let a = &[3, 97, 127];
170
- let b = &[3, 97, 127];
171
-
172
- if let Some(result) = SimSIMD::cosine(a, b) {
173
- assert_almost_equal(0.00012027938, result, 0.01);
174
- println!("The result of cosine_i8 is {:.8}", result);
175
- }
176
- }
177
-
178
- #[test]
179
- fn test_cosine_f32() {
180
- let a = &[1.0, 2.0, 3.0];
181
- let b = &[1.0, 2.0, 3.0];
182
-
183
- if let Some(result) = SimSIMD::cosine(a, b) {
184
- assert_almost_equal(0.004930496, result, 0.01);
185
- println!("The result of cosine_f32 is {:.8}", result);
186
- }
187
- }
188
-
189
- #[test]
190
- fn test_inner_i8() {
191
- let a = &[1, 2, 3];
192
- let b = &[4, 5, 6];
193
-
194
- if let Some(result) = SimSIMD::inner(a, b) {
195
- assert_almost_equal(0.029403687, result, 0.01);
196
- println!("The result of inner_i8 is {:.8}", result);
197
- }
198
- }
199
-
200
- #[test]
201
- fn test_inner_f32() {
202
- let a = &[1.0, 2.0, 3.0];
203
- let b = &[4.0, 5.0, 6.0];
204
-
205
- if let Some(result) = SimSIMD::inner(a, b) {
206
- assert_almost_equal(-31.0, result, 0.01);
207
- println!("The result of inner_f32 is {:.8}", result);
208
- }
209
- }
210
-
211
- #[test]
212
- fn test_sqeuclidean_i8() {
213
- let a = &[1, 2, 3];
214
- let b = &[4, 5, 6];
215
-
216
- if let Some(result) = SimSIMD::sqeuclidean(a, b) {
217
- assert_almost_equal(27.0, result, 0.01);
218
- println!("The result of sqeuclidean_i8 is {:.8}", result);
219
- }
220
- }
221
-
222
- #[test]
223
- fn test_sqeuclidean_f32() {
224
- let a = &[1.0, 2.0, 3.0];
225
- let b = &[4.0, 5.0, 6.0];
226
-
227
- if let Some(result) = SimSIMD::sqeuclidean(a, b) {
228
- assert_almost_equal(27.0, result, 0.01);
229
- println!("The result of sqeuclidean_f32 is {:.8}", result);
230
- }
231
- }
232
- }
package/sqlite/README.md DELETED
@@ -1,178 +0,0 @@
1
- # USearch Extensions for SQLite
2
-
3
- USearch exposes the SIMD-accelerated distance functions for SQLite databases aimed to accelerate vector search and fuzzy string matching operations.
4
- This includes:
5
-
6
- - [x] Cosine and Euclidean distances for float vectors,
7
- - [x] Jaccard and Hamming distances for binary vectors,
8
- - [x] Levenshtein and Hamming distances for strings,
9
- - [x] Haversine distance for geographical coordinates.
10
-
11
- The SIMD-acceleration covers AVX2, most subsets of AVX512, ARM NEON, and Arm SVE instruction sets, more than most BLAS libraries.
12
- The implementations are coming from [SimSIMD](https://github.com/ashvardanian/simsimd) and [StringZilla](https://github.com/ashvardanian/stringzilla).
13
- They are most efficient when vectors are stored as BLOBs, but for broader compatibility can also handle JSONs, and even separate columns containing vector elements.
14
-
15
- ## Installation
16
-
17
- USearch currently ships the SQLite extensions as part of the Python wheels, so they can be obtained from PyPi.
18
-
19
- ```sh
20
- pip install usearch # brings sqlite extensions
21
- ```
22
-
23
- ## Quickstart
24
-
25
- To USearch extensions to your SQLite database, you can use the following commands:
26
-
27
- ```py
28
- import sqlite3
29
- import usearch
30
-
31
- conn = sqlite3.connect(":memory:")
32
- conn.enable_load_extension(True)
33
- conn.load_extension(usearch.sqlite)
34
- ```
35
-
36
- Afterwards, the following script should work fine.
37
-
38
- ```sql
39
- -- Create a table with a JSON column for vectors
40
- CREATE TABLE vectors_table (
41
- id SERIAL PRIMARY KEY,
42
- vector JSON NOT NULL
43
- );
44
-
45
- -- Insert two 3D vectors
46
- INSERT INTO vectors_table (id, vector)
47
- VALUES
48
- (42, '[1.0, 2.0, 3.0]'),
49
- (43, '[4.0, 5.0, 6.0]');
50
-
51
- -- Compute the distances to [7.0, 8.0, 9.0] using
52
- -- the `distance_cosine_f32` extension function
53
- SELECT
54
- id,
55
- distance_cosine_f32(vt.vector, '[7.0, 8.0, 9.0]') AS distance
56
- FROM vectors_table AS vt;
57
- ```
58
-
59
- ### Functionality
60
-
61
- #### Strings
62
-
63
- String functions accept BLOBs and TEXTs, and return the distance as an integer.
64
- This includes:
65
-
66
- - `distance_levenshtein_bytes`,
67
- - `distance_levenshtein_unicode`,
68
- - `distance_hamming_bytes`,
69
- - `distance_hamming_unicode`.
70
-
71
- The Levenshtein distance would report the number of insertions, deletions, and substitutions required to transform one string into another, while the Hamming distance would only report the substitutons.
72
- When applied to strings of different length, the Hamming distance would evalute the prefix of the longer string and will add the length difference to the result.
73
- The `_bytes` variants compute the distance in the number of bytes, while the `_unicode` variants compute the distance in the number of Unicode code points, assuming the inputs are UTF8 encoded.
74
- Take a look at the following three similar looking, but distinct strings:
75
-
76
- - `école` - 6 codepoints (runes), 7 bytes.
77
- - `école` - 5 codepoints (runes), 6 bytes.
78
- - `écolé` - 5 codepoints (runes), 7 bytes.
79
-
80
- Those have three different letter "e" variants, including etter "é" as a single character, etter as "e" and an accent "´", as well as the plain letter "e".
81
- This would result in different distances between those strings, depending on the chosen metric.
82
-
83
- ```sql
84
- CREATE TABLE strings_table (
85
- id SERIAL PRIMARY KEY,
86
- word TEXT NOT NULL
87
- );
88
-
89
- INSERT INTO strings_table (id, word)
90
- VALUES
91
- (42, 'école'),
92
- (43, 'école');
93
-
94
- SELECT
95
- st.id,
96
-
97
- distance_levenshtein_bytes(st.word, 'écolé') AS lb,
98
- distance_levenshtein_unicode(st.word, 'écolé') AS lu,
99
- distance_hamming_bytes(st.word, 'écolé') AS hb,
100
- distance_hamming_unicode(st.word, 'écolé') AS hu,
101
-
102
- distance_levenshtein_bytes(st.word, 'écolé', 2) AS lbb,
103
- distance_levenshtein_unicode(st.word, 'écolé', 2) AS lub,
104
- distance_hamming_bytes(st.word, 'écolé', 2) AS hbb,
105
- distance_hamming_unicode(st.word, 'écolé', 2) AS hub
106
-
107
- FROM strings_table AS st;
108
- ```
109
-
110
- The last 4 columns will contain the bounded versions of the distance, which are faster to compute, thanks to the early stopping condition.
111
- They might be handy, if you want to accelerate search for something like an "autocomplete" feature in a search bar.
112
- The output will look like this:
113
-
114
- | id | lb | lu | hb | hu | lbb | lub | hbb | hub |
115
- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
116
- | 42 | 5 | 3 | 7 | 6 | 2 | 2 | 2 | 2 |
117
- | 43 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 |
118
-
119
- #### Bit Vectors
120
-
121
- If using SQLite as a feature store, you might be dealing with single-bit vectors.
122
-
123
- - `distance_hamming_binary` - the Hamming distance, meaning number of bits that differ between two vectors,
124
- - `distance_jaccard_binary` - the Jaccard distance, meaning the number of bits that differ between two vectors divided by the number of bits that are set in at least one of the vectors.
125
-
126
- Here is an example:
127
-
128
- ```sql
129
- CREATE TABLE binary_vectors (
130
- id SERIAL PRIMARY KEY,
131
- vector BLOB NOT NULL
132
- );
133
- INSERT INTO binary_vectors (id, vector)
134
- VALUES
135
- (42, X'FFFFFF'), -- 111111111111111111111111 in binary
136
- (43, X'000000'); -- 000000000000000000000000 in binary
137
- SELECT bv.id,
138
- distance_hamming_binary(bv.vector, X'FFFF00') AS hamming_distance,
139
- distance_jaccard_binary(bv.vector, X'FFFF00') AS jaccard_distance
140
- FROM binary_vectors AS bv;
141
- ```
142
-
143
- #### Dense Vectors
144
-
145
- Distance functions for desnse vectors can be used on both BLOBs and JSONs.
146
- Every name is structured as `distance_<metric>_<type>`, where
147
-
148
- - `<metric>` is the name of the metric, like `cosine`, `inner`, `sqeuclidean`, and `divergence`,
149
- - `<type>` is the type of the vector elements, like `f64`, `f32`, `f16`, and `i8`.
150
-
151
- The `cosine` metric is the cosine similarity, the `inner` metric is the inner (dot) product, the `sqeuclidean` metric is the squared Euclidean distance, and the `divergence` metric is the Jensen-Shannon divergence - the symmetric variant of the Kullback-Leibler divergence.
152
-
153
- - `distance_sqeuclidean_f64`
154
- - `distance_cosine_f64`
155
- - `distance_inner_f64`
156
- - `distance_divergence_f64`
157
- - `distance_sqeuclidean_f32`
158
- - `distance_cosine_f32`
159
- - `distance_inner_f32`
160
- - `distance_divergence_f32`
161
- - `distance_sqeuclidean_f16`
162
- - `distance_cosine_f16`
163
- - `distance_inner_f16`
164
- - `distance_divergence_f16`
165
- - `distance_sqeuclidean_i8`
166
- - `distance_cosine_i8`
167
- - `distance_inner_i8`
168
- - `distance_divergence_i8`
169
-
170
- #### Geographical Coordinates
171
-
172
- When dealing with geographical or other spherical coordinates, you can use:
173
-
174
- - `distance_haversine_meters` - the Haversine distance on the sphere multiplied by the Earth's radius in meters.
175
-
176
- ---
177
-
178
- Feel free to contribute more examples to this file 🤗