usearch 2.8.15 → 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 (76) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
  2. package/.github/workflows/prerelease.yml +37 -11
  3. package/.github/workflows/release.yml +30 -28
  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 +8 -7
  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 +4 -2
  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 +91 -25
  23. package/simsimd/binding.gyp +18 -0
  24. package/simsimd/build.rs +20 -0
  25. package/simsimd/include/simsimd/probability.h +5 -5
  26. package/simsimd/include/simsimd/simsimd.h +9 -5
  27. package/simsimd/include/simsimd/spatial.h +20 -21
  28. package/simsimd/include/simsimd/types.h +5 -1
  29. package/simsimd/javascript/bench.js +20 -10
  30. package/simsimd/javascript/dist-package-cjs.json +3 -0
  31. package/simsimd/javascript/dist-package-esm.json +3 -0
  32. package/simsimd/javascript/fallback.ts +193 -0
  33. package/simsimd/javascript/node-gyp-build.d.ts +1 -0
  34. package/simsimd/javascript/simsimd.ts +124 -0
  35. package/simsimd/javascript/test.mjs +153 -0
  36. package/simsimd/javascript/tsconfig-base.json +25 -0
  37. package/simsimd/javascript/tsconfig-cjs.json +8 -0
  38. package/simsimd/javascript/tsconfig-esm.json +8 -0
  39. package/simsimd/package-lock.json +1688 -0
  40. package/simsimd/package.json +26 -11
  41. package/simsimd/rust/benches/cosine.rs +27 -0
  42. package/simsimd/rust/benches/native.rs +27 -0
  43. package/simsimd/rust/benches/sqeuclidean.rs +27 -0
  44. package/simsimd/rust/lib.c +68 -0
  45. package/simsimd/rust/lib.rs +232 -0
  46. package/sqlite/README.md +178 -0
  47. package/sqlite/lib.cpp +325 -0
  48. package/stringzilla/CONTRIBUTING.md +429 -0
  49. package/stringzilla/Cargo.lock +25 -0
  50. package/stringzilla/Cargo.toml +26 -0
  51. package/stringzilla/LICENSE +201 -0
  52. package/stringzilla/README.md +1281 -0
  53. package/stringzilla/VERSION +1 -0
  54. package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
  55. package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
  56. package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
  57. package/stringzilla/binding.gyp +16 -0
  58. package/stringzilla/build.rs +14 -0
  59. package/stringzilla/c/lib.c +304 -0
  60. package/stringzilla/cli/README.md +48 -0
  61. package/stringzilla/cli/split.py +72 -0
  62. package/stringzilla/cli/wc.py +37 -0
  63. package/stringzilla/include/stringzilla/experimental.h +724 -0
  64. package/stringzilla/include/stringzilla/module.modulemap +9 -0
  65. package/stringzilla/include/stringzilla/stringzilla.h +5240 -0
  66. package/stringzilla/include/stringzilla/stringzilla.hpp +3830 -0
  67. package/stringzilla/javascript/lib.c +125 -0
  68. package/stringzilla/javascript/stringzilla.js +22 -0
  69. package/stringzilla/package-ci.json +10 -0
  70. package/stringzilla/package.json +32 -0
  71. package/stringzilla/rust/lib.rs +362 -0
  72. package/stringzilla/swift/StringProtocol+StringZilla.swift +280 -0
  73. package/stringzilla/swift/Test.swift +60 -0
  74. package/wasmer.toml +1 -1
  75. package/simsimd/javascript/simsimd.js +0 -45
  76. package/simsimd/javascript/test/simsimd.test.js +0 -47
@@ -0,0 +1,36 @@
1
+ [package]
2
+ name = "simsimd"
3
+ description = "Fastest SIMD-Accelerated Vector Similarity Functions for x86 and Arm"
4
+ version = "3.8.0"
5
+ edition = "2021"
6
+ license = "Apache-2.0"
7
+ authors = [
8
+ "Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>",
9
+ "Pedro Planel <pplanel@gmail.com>",
10
+ ]
11
+ repository = "https://github.com/ashvardanian/SimSIMD"
12
+ documentation = "https://docs.rs/simsimd"
13
+ homepage = "https://ashvardanian.com/posts/simsimd-faster-scipy"
14
+ keywords = ["simd", "search", "linear-algebra", "vector"]
15
+ categories = ["mathematics", "hardware-support", "no-std", "wasm", "external-ffi-bindings"]
16
+
17
+ [lib]
18
+ name = "simsimd"
19
+ path = "rust/lib.rs"
20
+
21
+ [build-dependencies]
22
+ cc = "1.0.83"
23
+
24
+ [[bench]]
25
+ name = "cosine"
26
+ harness = false
27
+ path = "rust/benches/cosine.rs"
28
+
29
+ [[bench]]
30
+ name = "sqeuclidean"
31
+ harness = false
32
+ path = "rust/benches/sqeuclidean.rs"
33
+
34
+ [dev-dependencies]
35
+ criterion = { version = "0.5.1" }
36
+ rand = { version = "0.8.5" }
package/simsimd/README.md CHANGED
@@ -1,25 +1,27 @@
1
1
  # SimSIMD 📏
2
2
 
3
3
  <div>
4
- <a href="https://pepy.tech/project/simsimd"> <img alt="PyPI" src="https://static.pepy.tech/personalized-badge/simsimd?period=month&units=abbreviation&left_color=black&right_color=blue&left_text=Python%20monthly%20installs"> </a>
4
+ <a href="https://pepy.tech/project/simsimd"> <img alt="PyPI" src="https://static.pepy.tech/personalized-badge/simsimd?period=total&units=abbreviation&left_color=black&right_color=blue&left_text=SimSIMD%20Python%20installs"> </a>
5
5
  <a href="https://www.npmjs.com/package/simsimd"> <img alt="npm" src="https://img.shields.io/npm/dy/simsimd?label=npm%20dowloads"> </a>
6
+ <a href="https://crates.io/crates/simsimd"> <img alt="rust" src="https://img.shields.io/crates/d/simsimd?logo=rust" /> </a>
6
7
  <img alt="GitHub code size in bytes" src="https://img.shields.io/github/languages/code-size/ashvardanian/simsimd">
7
8
  </div>
8
9
 
9
- ## Efficient Alternative to [`scipy.spatial.distance`][scipy] and [`numpy.inner`][numpy]
10
+ ## Hardware-Accelerated Similarity Metrics and Distance Functions
10
11
 
11
- SimSIMD leverages SIMD intrinsics, capabilities that only select compilers effectively utilize. This framework supports conventional AVX2 instructions on x86, NEON on Arm, as well as __rare__ AVX-512 FP16 instructions on x86 and Scalable Vector Extensions (SVE) on Arm. Designed specifically for Machine Learning contexts, it's optimized for handling high-dimensional vector embeddings.
12
+ - Zero-dependency [header-only C 99](#using-simsimd-in-c) library.
13
+ - Bindings for [Python](#using-simsimd-in-python), [Rust](#using-simsimd-in-rust) and [JavaScript](#using-simsimd-in-javascript).
14
+ - Targets ARM NEON, SVE, x86 AVX2, AVX-512 (VNNI, FP16) hardware backends.
15
+ - Zero-copy compatible with NumPy, PyTorch, TensorFlow, and other tensors.
16
+ - Handles `f64` double-, `f32` single-, and `f16` half-precision, `i8` integral, and binary vectors.
17
+ - __Up to 200x faster__ than [`scipy.spatial.distance`][scipy] and [`numpy.inner`][numpy].
18
+ - Used in [USearch](https://github.com/unum-cloud/usearch) and several DBMS products.
12
19
 
13
- - ✅ __3-200x faster__ than NumPy and SciPy distance functions.
14
- - ✅ Euclidean (L2), Inner Product, and Cosine (Angular) spatial distances.
15
- - ✅ Hamming (~ Manhattan) and Jaccard (~ Tanimoto) binary distances.
16
- - ✅ Kullback-Leibler and Jensen–Shannon divergences for probability distributions.
17
- - ✅ Single-precision `f32`, half-precision `f16`, `i8`, and binary vectors.
18
- - ✅ Compatible with GCC and Clang on MacOS and Linux, and MinGW on Windows.
19
- - ✅ Compatible with NumPy, PyTorch, TensorFlow, and other tensors.
20
- - ✅ Has __no dependencies__, not even LibC.
21
- - ✅ [JavaScript API](#using-simsimd-in-javascript).
22
- - ✅ [C API](#using-simsimd-in-c).
20
+ __Implemented distance functions__ include:
21
+
22
+ - Euclidean (L2), Inner Distance, and Cosine (Angular) spatial distances.
23
+ - Hamming (~ Manhattan) and Jaccard (~ Tanimoto) binary distances.
24
+ - Kullback-Leibler and Jensen–Shannon divergences for probability distributions.
23
25
 
24
26
  [scipy]: https://docs.scipy.org/doc/scipy/reference/spatial.distance.html#module-scipy.spatial.distance
25
27
  [numpy]: https://numpy.org/doc/stable/reference/generated/numpy.inner.html
@@ -43,18 +45,18 @@ Given 1000 embeddings from OpenAI Ada API with 1536 dimensions, running on the A
43
45
  | :------------- | ----------------: | ----------------: | ---------------: | :------------------------------------- | :-------------- |
44
46
  | Cosine | __32 x__ | __79 x__ | __133 x__ | `scipy.spatial.distance.cosine` | `cosine` |
45
47
  | Euclidean ² | __5 x__ | __26 x__ | __17 x__ | `scipy.spatial.distance.sqeuclidean` | `sqeuclidean` |
46
- | Inner Product | __2 x__ | __9 x__ | __18 x__ | `numpy.inner` | `inner` |
48
+ | Inner Distance | __2 x__ | __9 x__ | __18 x__ | `numpy.inner` | `inner` |
47
49
  | Jensen Shannon | __31 x__ | __53 x__ | | `scipy.spatial.distance.jensenshannon` | `jensenshannon` |
48
50
 
49
51
  ### Intel Sapphire Rapids
50
52
 
51
- On the Intel Sapphire Rapids platform, SimSIMD was benchmarked against auto-vectorized code using GCC 12. GCC handles single-precision `float`, but might not be the best choice for `int8` and `_Float16` arrays, which has been part of the C language since 2011.
53
+ On the Intel Sapphire Rapids platform, SimSIMD was benchmarked against auto-vectorized code using GCC 12. GCC handles single-precision `float` but might not be the best choice for `int8` and `_Float16` arrays, which has been part of the C language since 2011.
52
54
 
53
55
  | Kind | GCC 12 `f32` | GCC 12 `f16` | SimSIMD `f16` | `f16` improvement |
54
56
  | :------------- | -----------: | -----------: | ------------: | ----------------: |
55
57
  | Cosine | 3.28 M/s | _336.29 k/s_ | _6.88 M/s_ | __20 x__ |
56
58
  | Euclidean ² | 4.62 M/s | _147.25 k/s_ | _5.32 M/s_ | __36 x__ |
57
- | Inner Product | 3.81 M/s | _192.02 k/s_ | _5.99 M/s_ | __31 x__ |
59
+ | Inner Distance | 3.81 M/s | _192.02 k/s_ | _5.99 M/s_ | __31 x__ |
58
60
  | Jensen Shannon | 1.18 M/s | _18.13 k/s_ | _2.14 M/s_ | __118 x__ |
59
61
 
60
62
  __Broader Benchmarking Results__:
@@ -63,7 +65,7 @@ __Broader Benchmarking Results__:
63
65
  - [4th Gen Intel Xeon Platinum](https://ashvardanian.com/posts/simsimd-faster-scipy/#appendix-2-performance-on-4th-gen-intel-xeon-platinum-8480).
64
66
  - [AWS Graviton 3](https://ashvardanian.com/posts/simsimd-faster-scipy/#appendix-3-performance-on-aws-graviton-3).
65
67
 
66
- ## Using in Python
68
+ ## Using SimSIMD in Python
67
69
 
68
70
  ### Installation
69
71
 
@@ -92,7 +94,7 @@ batch2 = np.random.randn(100, 1536).astype(np.float32)
92
94
  dist = simsimd.cosine(batch1, batch2)
93
95
  ```
94
96
 
95
- If either batch has more than one vector, the other batch must have one or same number of vectors.
97
+ If either batch has more than one vector, the other batch must have one or the same number of vectors.
96
98
  If it contains just one, the value is broadcasted.
97
99
 
98
100
  ### All Pairwise Distances
@@ -124,7 +126,7 @@ print(simsimd.get_capabilities())
124
126
  ### Using Python API with USearch
125
127
 
126
128
  Want to use it in Python with [USearch](https://github.com/unum-cloud/usearch)?
127
- You can wrap the raw C function pointers SimSIMD backends into a `CompiledMetric`, and pass it to USearch, similar to how it handles Numba's JIT-compiled code.
129
+ You can wrap the raw C function pointers SimSIMD backends into a `CompiledMetric` and pass it to USearch, similar to how it handles Numba's JIT-compiled code.
128
130
 
129
131
  ```py
130
132
  from usearch.index import Index, CompiledMetric, MetricKind, MetricSignature
@@ -139,9 +141,46 @@ metric = CompiledMetric(
139
141
  index = Index(256, metric=metric)
140
142
  ```
141
143
 
144
+ ## Using SimSIMD in Rust
145
+
146
+ To install, add the following to your `Cargo.toml`:
147
+
148
+ ```toml
149
+ [dependencies]
150
+ simsimd = "..."
151
+ ```
152
+
153
+ To use it:
154
+
155
+ ```rust
156
+ use simsimd::{cosine, sqeuclidean};
157
+
158
+ fn main() {
159
+ let vector_a = vec![1.0, 2.0, 3.0];
160
+ let vector_b = vec![4.0, 5.0, 6.0];
161
+
162
+ let distance = cosine(&vector_a, &vector_b);
163
+ println!("Cosine Distance: {}", distance);
164
+
165
+ let distance = sqeuclidean(&vector_a, &vector_b);
166
+ println!("Squared Euclidean Distance: {}", distance);
167
+ }
168
+ ```
169
+
142
170
  ## Using SimSIMD in JavaScript
143
171
 
144
- After you add `simsimd` as a dependency and `npm install`, you will be able to call SimSIMD function on various `TypedArray` variants:
172
+ To install, choose one of the following options depending on your environment:
173
+
174
+ - `npm install --save simsimd`
175
+ - `yarn add simsimd`
176
+ - `pnpm add simsimd`
177
+ - `bun install simsimd`
178
+
179
+ The package is distributed with prebuilt binaries for Node.js v10 and above for Linux (x86_64, arm64), macOS (x86_64, arm64), and Windows (i386,x86_64).
180
+
181
+ If your platform is not supported, you can build the package from source via `npm run build`. This will automatically happen unless you install the package with `--ignore-scripts` flag or use Bun.
182
+
183
+ After you install it, you will be able to call the SimSIMD functions on various `TypedArray` variants:
145
184
 
146
185
  ```js
147
186
  const { sqeuclidean, cosine, inner, hamming, jaccard } = require('simsimd');
@@ -155,8 +194,6 @@ console.log('Squared Euclidean Distance:', distance);
155
194
 
156
195
  ## Using SimSIMD in C
157
196
 
158
- If you're aiming to utilize the `_Float16` functionality with SimSIMD, ensure your development environment is compatible with C 11. For other functionalities of SimSIMD, C 99 compatibility will suffice.
159
-
160
197
  For integration within a CMake-based project, add the following segment to your `CMakeLists.txt`:
161
198
 
162
199
  ```cmake
@@ -166,12 +203,30 @@ FetchContent_Declare(
166
203
  GIT_SHALLOW TRUE
167
204
  )
168
205
  FetchContent_MakeAvailable(simsimd)
169
- include_directories(${simsimd_SOURCE_DIR}/include)
170
206
  ```
171
207
 
172
- Stay updated with the latest advancements by always using the most recent compiler available for your platform. This ensures that you benefit from the newest intrinsics.
208
+ If you're aiming to utilize the `_Float16` functionality with SimSIMD, ensure your development environment is compatible with C 11.
209
+ For other functionalities of SimSIMD, C 99 compatibility will suffice.
210
+ A minimal usage example would be:
211
+
212
+ ```c
213
+ #include <simsimd/simsimd.h>
214
+
215
+ int main() {
216
+ simsimd_f32_t vector_a[1536];
217
+ simsimd_f32_t vector_b[1536];
218
+ simsimd_f32_t distance = simsimd_avx512_f32_cos(vector_a, vector_b, 1536);
219
+ return 0;
220
+ }
221
+ ```
222
+
223
+ All of the functions names follow the same pattern: `simsimd_{backend}_{type}_{metric}`.
173
224
 
174
- Should you wish to integrate SimSIMD within USearch, simply compile USearch with the flag `USEARCH_USE_SIMSIMD=1`. Notably, this is the default setting on the majority of platforms.
225
+ - The backend can be `avx512`, `avx2`, `neon`, or `sve`.
226
+ - The type can be `f64`, `f32`, `f16`, `i8`, or `b8`.
227
+ - The metric can be `cos`, `ip`, `l2sq`, `hamming`, `jaccard`, `kl`, or `js`.
228
+
229
+ In case you want to avoid hard-coding the backend, you can use the `simsimd_metric_punned_t` to pun the function pointer, and `simsimd_capabilities` function to get the available backends at runtime.
175
230
 
176
231
  ## Benchmarking and Contributing
177
232
 
@@ -189,6 +244,9 @@ __To test and benchmark with Python bindings__:
189
244
  ```sh
190
245
  pip install -e .
191
246
  pytest python/test.py -s -x
247
+
248
+ pip install numpy scipy scikit-learn # for comparison baselines
249
+ python python/bench.py # to run default benchmarks
192
250
  python python/bench.py --n 1000 --ndim 1000000 # batch size and dimensions
193
251
  ```
194
252
 
@@ -207,3 +265,11 @@ cd golang
207
265
  go test # To test
208
266
  go test -run=^$ -bench=. -benchmem # To benchmark
209
267
  ```
268
+
269
+ __To test and benchmark Rust bindings__:
270
+
271
+ ```sh
272
+ cargo test
273
+ cargo bench
274
+ open ./target/criterion/report/index.html
275
+ ```
@@ -1,4 +1,7 @@
1
1
  {
2
+ "variables": {
3
+ "openssl_fips": ""
4
+ },
2
5
  "targets": [
3
6
  {
4
7
  "target_name": "simsimd",
@@ -13,6 +16,21 @@
13
16
  "-Wno-cast-function-type",
14
17
  "-Wno-switch",
15
18
  ],
19
+ "conditions": [
20
+ ["OS=='mac'", {
21
+ "xcode_settings": {
22
+ "MACOSX_DEPLOYMENT_TARGET": "11.0",
23
+ "OTHER_CFLAGS": [
24
+ "-arch arm64",
25
+ "-arch x86_64"
26
+ ],
27
+ "OTHER_LDFLAGS": [
28
+ "-arch arm64",
29
+ "-arch x86_64"
30
+ ]
31
+ }
32
+ }]
33
+ ]
16
34
  }
17
35
  ]
18
36
  }
@@ -0,0 +1,20 @@
1
+ fn main() {
2
+ cc::Build::new()
3
+ .file("rust/lib.c")
4
+ .include("include")
5
+ .flag("-O3")
6
+ .flag("-DSIMSIMD_NATIVE_F16=0")
7
+ .flag("-std=c99") // Enforce C99 standard
8
+ .flag("-pedantic") // Ensure strict compliance with the C standard
9
+ .warnings(false)
10
+ .compile("simsimd");
11
+
12
+ println!("cargo:rerun-if-changed=rust/lib.c");
13
+ println!("cargo:rerun-if-changed=rust/lib.rs");
14
+ println!("cargo:rerun-if-changed=include/simsimd/simsimd.h");
15
+
16
+ println!("cargo:rerun-if-changed=include/simsimd/binary.h");
17
+ println!("cargo:rerun-if-changed=include/simsimd/probability.h");
18
+ println!("cargo:rerun-if-changed=include/simsimd/spatial.h");
19
+ println!("cargo:rerun-if-changed=include/simsimd/types.h");
20
+ }
@@ -271,7 +271,7 @@ simsimd_avx2_f32_log2(__m256 x) {
271
271
  __attribute__((target("avx2,f16c,fma"))) //
272
272
  inline static simsimd_f32_t
273
273
  simsimd_avx2_f16_kl(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
274
- __m256 sum_vec = _mm256_set1_ps(0);
274
+ __m256 sum_vec = _mm256_setzero_ps();
275
275
  simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
276
276
  __m256 epsilon_vec = _mm256_set1_ps(epsilon);
277
277
  simsimd_size_t i = 0;
@@ -303,7 +303,7 @@ simsimd_avx2_f16_kl(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size
303
303
  __attribute__((target("avx2,f16c,fma"))) //
304
304
  inline static simsimd_f32_t
305
305
  simsimd_avx2_f16_js(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
306
- __m256 sum_vec = _mm256_set1_ps(0);
306
+ __m256 sum_vec = _mm256_setzero_ps();
307
307
  simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
308
308
  __m256 epsilon_vec = _mm256_set1_ps(epsilon);
309
309
  simsimd_size_t i = 0;
@@ -377,7 +377,7 @@ simsimd_avx512_f32_log2(__m512 x) {
377
377
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
378
378
  inline static simsimd_f32_t
379
379
  simsimd_avx512_f32_kl(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
380
- __m512 sum_vec = _mm512_set1_ps(0);
380
+ __m512 sum_vec = _mm512_setzero();
381
381
  simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
382
382
  __m512 epsilon_vec = _mm512_set1_ps(epsilon);
383
383
  __m512 a_vec, b_vec;
@@ -407,8 +407,8 @@ simsimd_avx512_f32_kl_cycle:
407
407
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
408
408
  inline static simsimd_f32_t
409
409
  simsimd_avx512_f32_js(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
410
- __m512 sum_a_vec = _mm512_set1_ps(0);
411
- __m512 sum_b_vec = _mm512_set1_ps(0);
410
+ __m512 sum_a_vec = _mm512_setzero();
411
+ __m512 sum_b_vec = _mm512_setzero();
412
412
  simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
413
413
  __m512 epsilon_vec = _mm512_set1_ps(epsilon);
414
414
  __m512 a_vec, b_vec;
@@ -11,8 +11,12 @@
11
11
  * Detecting target CPU features at compile time: https://stackoverflow.com/a/28939692/2766161
12
12
  */
13
13
 
14
- #ifndef SIMSIMD_SIMSIMD_H
15
- #define SIMSIMD_SIMSIMD_H
14
+ #ifndef SIMSIMD_H
15
+ #define SIMSIMD_H
16
+
17
+ #define SIMSIMD_VERSION_MAJOR 3
18
+ #define SIMSIMD_VERSION_MINOR 8
19
+ #define SIMSIMD_VERSION_PATCH 0
16
20
 
17
21
  #include "binary.h" // Hamming, Jaccard
18
22
  #include "probability.h" // Kullback-Leibler, Jensen–Shannon
@@ -65,7 +69,7 @@ typedef enum {
65
69
  */
66
70
  typedef enum {
67
71
  simsimd_cap_serial_k = 1, ///< Serial (non-SIMD) capability
68
- simsimd_cap_any_k = 0xFFFFFFFF, ///< Mask representing any capability
72
+ simsimd_cap_any_k = 0x7FFFFFFF, ///< Mask representing any capability with `INT_MAX`
69
73
 
70
74
  simsimd_cap_arm_neon_k = 1 << 10, ///< ARM NEON capability
71
75
  simsimd_cap_arm_sve_k = 1 << 11, ///< ARM SVE capability
@@ -108,11 +112,11 @@ typedef simsimd_f32_t (*simsimd_metric_punned_t)(void const* a, void const* b, s
108
112
  * @brief Function to determine the SIMD capabilities of the current machine at @b runtime.
109
113
  * @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
110
114
  */
111
- inline static simsimd_capability_t simsimd_capabilities() {
115
+ inline static simsimd_capability_t simsimd_capabilities(void) {
112
116
 
113
117
  #if SIMSIMD_TARGET_X86
114
118
 
115
- /// The states of 4 registers populated for a specific "cpuid" assmebly call
119
+ /// The states of 4 registers populated for a specific "cpuid" assembly call
116
120
  union four_registers_t {
117
121
  int array[4];
118
122
  struct separate_t {
@@ -548,12 +548,11 @@ simsimd_sve_f64_cos(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size
548
548
  // Avoid `simsimd_approximate_inverse_square_root` on Arm NEON
549
549
  simsimd_f64_t a2_b2_arr[2] = {a2, b2};
550
550
  float64x2_t a2_b2 = vld1q_f64(a2_b2_arr);
551
- a2_b2 = vrsqrteq_f64(a2_b2);
551
+ a2_b2 = vrsqrteq_f64(a2_b2);
552
552
  vst1q_f64(a2_b2_arr, a2_b2);
553
553
  return ab != 0 ? 1 - ab * a2_b2_arr[0] * a2_b2_arr[1] : 1;
554
554
  }
555
555
 
556
-
557
556
  #endif // SIMSIMD_TARGET_ARM_SVE
558
557
  #endif // SIMSIMD_TARGET_ARM
559
558
 
@@ -574,7 +573,7 @@ simsimd_sve_f64_cos(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size
574
573
  __attribute__((target("avx2,f16c,fma"))) //
575
574
  inline static simsimd_f32_t
576
575
  simsimd_avx2_f16_l2sq(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
577
- __m256 d2_vec = _mm256_set1_ps(0);
576
+ __m256 d2_vec = _mm256_setzero_ps();
578
577
  simsimd_size_t i = 0;
579
578
  for (; i + 8 <= n; i += 8) {
580
579
  __m256 a_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(a + i)));
@@ -601,7 +600,7 @@ simsimd_avx2_f16_l2sq(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_si
601
600
  __attribute__((target("avx2,f16c,fma"))) //
602
601
  inline static simsimd_f32_t
603
602
  simsimd_avx2_f16_ip(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
604
- __m256 ab_vec = _mm256_set1_ps(0);
603
+ __m256 ab_vec = _mm256_setzero_ps();
605
604
  simsimd_size_t i = 0;
606
605
  for (; i + 8 <= n; i += 8) {
607
606
  __m256 a_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(a + i)));
@@ -625,7 +624,7 @@ __attribute__((target("avx2,f16c,fma"))) //
625
624
  inline static simsimd_f32_t
626
625
  simsimd_avx2_f16_cos(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
627
626
 
628
- __m256 ab_vec = _mm256_set1_ps(0), a2_vec = _mm256_set1_ps(0), b2_vec = _mm256_set1_ps(0);
627
+ __m256 ab_vec = _mm256_setzero_ps(), a2_vec = _mm256_setzero_ps(), b2_vec = _mm256_setzero_ps();
629
628
  simsimd_size_t i = 0;
630
629
  for (; i + 8 <= n; i += 8) {
631
630
  __m256 a_vec = _mm256_cvtph_ps(_mm_loadu_si128((__m128i const*)(a + i)));
@@ -814,7 +813,7 @@ simsimd_avx2_i8_ip(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t
814
813
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
815
814
  inline static simsimd_f32_t
816
815
  simsimd_avx512_f32_l2sq(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
817
- __m512 d2_vec = _mm512_set1_ps(0);
816
+ __m512 d2_vec = _mm512_setzero();
818
817
  __m512 a_vec, b_vec;
819
818
 
820
819
  simsimd_avx512_f32_l2sq_cycle:
@@ -839,7 +838,7 @@ simsimd_avx512_f32_l2sq_cycle:
839
838
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
840
839
  inline static simsimd_f32_t
841
840
  simsimd_avx512_f32_ip(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
842
- __m512 ab_vec = _mm512_set1_ps(0);
841
+ __m512 ab_vec = _mm512_setzero();
843
842
  __m512 a_vec, b_vec;
844
843
 
845
844
  simsimd_avx512_f32_ip_cycle:
@@ -863,9 +862,9 @@ simsimd_avx512_f32_ip_cycle:
863
862
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
864
863
  inline static simsimd_f32_t
865
864
  simsimd_avx512_f32_cos(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
866
- __m512 ab_vec = _mm512_set1_ps(0);
867
- __m512 a2_vec = _mm512_set1_ps(0);
868
- __m512 b2_vec = _mm512_set1_ps(0);
865
+ __m512 ab_vec = _mm512_setzero();
866
+ __m512 a2_vec = _mm512_setzero();
867
+ __m512 b2_vec = _mm512_setzero();
869
868
  __m512 a_vec, b_vec;
870
869
 
871
870
  simsimd_avx512_f32_cos_cycle:
@@ -910,7 +909,7 @@ simsimd_avx512_f32_cos_cycle:
910
909
  __attribute__((target("avx512fp16,avx512vl,avx512f,bmi2"))) //
911
910
  inline static simsimd_f32_t
912
911
  simsimd_avx512_f16_l2sq(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
913
- __m512h d2_vec = _mm512_set1_ph(0);
912
+ __m512h d2_vec = _mm512_setzero_ph();
914
913
  __m512i a_i16_vec, b_i16_vec;
915
914
 
916
915
  simsimd_avx512_f16_l2sq_cycle:
@@ -935,7 +934,7 @@ simsimd_avx512_f16_l2sq_cycle:
935
934
  __attribute__((target("avx512fp16,avx512vl,avx512f,bmi2"))) //
936
935
  inline static simsimd_f32_t
937
936
  simsimd_avx512_f16_ip(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
938
- __m512h ab_vec = _mm512_set1_ph(0);
937
+ __m512h ab_vec = _mm512_setzero_ph();
939
938
  __m512i a_i16_vec, b_i16_vec;
940
939
 
941
940
  simsimd_avx512_f16_ip_cycle:
@@ -959,9 +958,9 @@ simsimd_avx512_f16_ip_cycle:
959
958
  __attribute__((target("avx512fp16,avx512vl,avx512f,bmi2"))) //
960
959
  inline static simsimd_f32_t
961
960
  simsimd_avx512_f16_cos(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
962
- __m512h ab_vec = _mm512_set1_ph(0);
963
- __m512h a2_vec = _mm512_set1_ph(0);
964
- __m512h b2_vec = _mm512_set1_ph(0);
961
+ __m512h ab_vec = _mm512_setzero_ph();
962
+ __m512h a2_vec = _mm512_setzero_ph();
963
+ __m512h b2_vec = _mm512_setzero_ph();
965
964
  __m512i a_i16_vec, b_i16_vec;
966
965
 
967
966
  simsimd_avx512_f16_cos_cycle:
@@ -1084,7 +1083,7 @@ simsimd_avx512_i8_ip(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_
1084
1083
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
1085
1084
  inline static simsimd_f32_t
1086
1085
  simsimd_avx512_f64_l2sq(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size_t n) {
1087
- __m512d d2_vec = _mm512_set1_pd(0);
1086
+ __m512d d2_vec = _mm512_setzero_pd();
1088
1087
  __m512d a_vec, b_vec;
1089
1088
 
1090
1089
  simsimd_avx512_f64_l2sq_cycle:
@@ -1109,7 +1108,7 @@ simsimd_avx512_f64_l2sq_cycle:
1109
1108
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
1110
1109
  inline static simsimd_f32_t
1111
1110
  simsimd_avx512_f64_ip(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size_t n) {
1112
- __m512d ab_vec = _mm512_set1_pd(0);
1111
+ __m512d ab_vec = _mm512_setzero_pd();
1113
1112
  __m512d a_vec, b_vec;
1114
1113
 
1115
1114
  simsimd_avx512_f64_ip_cycle:
@@ -1133,9 +1132,9 @@ simsimd_avx512_f64_ip_cycle:
1133
1132
  __attribute__((target("avx512f,avx512vl,bmi2"))) //
1134
1133
  inline static simsimd_f32_t
1135
1134
  simsimd_avx512_f64_cos(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size_t n) {
1136
- __m512d ab_vec = _mm512_set1_pd(0);
1137
- __m512d a2_vec = _mm512_set1_pd(0);
1138
- __m512d b2_vec = _mm512_set1_pd(0);
1135
+ __m512d ab_vec = _mm512_setzero_pd();
1136
+ __m512d a2_vec = _mm512_setzero_pd();
1137
+ __m512d b2_vec = _mm512_setzero_pd();
1139
1138
  __m512d a_vec, b_vec;
1140
1139
 
1141
1140
  simsimd_avx512_f64_cos_cycle:
@@ -1173,4 +1172,4 @@ simsimd_avx512_f64_cos_cycle:
1173
1172
  }
1174
1173
  #endif
1175
1174
 
1176
- #endif
1175
+ #endif
@@ -102,7 +102,7 @@ typedef signed char simsimd_i8_t;
102
102
  typedef unsigned char simsimd_b8_t;
103
103
  typedef unsigned long long simsimd_size_t;
104
104
 
105
- #if !defined(SIMSIMD_NATIVE_F16)
105
+ #if !defined(SIMSIMD_NATIVE_F16) || SIMSIMD_NATIVE_F16
106
106
  /**
107
107
  * @brief Half-precision floating-point type.
108
108
  *
@@ -112,12 +112,16 @@ typedef unsigned long long simsimd_size_t;
112
112
  */
113
113
  #if (defined(__GNUC__) || defined(__clang__)) && (defined(__ARM_ARCH) || defined(__aarch64__)) && \
114
114
  (defined(__ARM_FP16_FORMAT_IEEE))
115
+ #if !defined(SIMSIMD_NATIVE_F16)
115
116
  #define SIMSIMD_NATIVE_F16 1
117
+ #endif
116
118
  typedef __fp16 simsimd_f16_t;
117
119
  #elif ((defined(__GNUC__) || defined(__clang__)) && (defined(__x86_64__) || defined(__i386__)) && \
118
120
  (defined(__SSE2__) || defined(__AVX512F__)))
119
121
  typedef _Float16 simsimd_f16_t;
122
+ #if !defined(SIMSIMD_NATIVE_F16)
120
123
  #define SIMSIMD_NATIVE_F16 1
124
+ #endif
121
125
  #else // Unknown compiler or architecture
122
126
  #define SIMSIMD_NATIVE_F16 0
123
127
  #endif // Unknown compiler or architecture
@@ -1,9 +1,8 @@
1
- import benchmark from 'benchmark';
2
- import bindings from 'bindings';
3
- import * as math from 'mathjs';
4
- import usearch, { MetricKind } from 'usearch';
5
-
6
- const simsimd = bindings('simsimd');
1
+ const benchmark = require('benchmark');
2
+ const math = require('mathjs');
3
+ const usearch = require('usearch');
4
+ const MetricKind = usearch.MetricKind;
5
+ const simsimd = require("./dist/cjs/simsimd.js");
7
6
 
8
7
  // Assuming the vectors are of the same length
9
8
  function cosineDistance(a, b) {
@@ -29,6 +28,8 @@ function cosineDistanceMathJS(a, b) {
29
28
  const dimensions = 1536; // Adjust dimensions as needed
30
29
  const array1 = Array.from({ length: dimensions }, () => Math.random() * 100);
31
30
  const array2 = Array.from({ length: dimensions }, () => Math.random() * 100);
31
+ const mathm1 = math.matrix(Array.from({ length: dimensions }, () => Math.random() * 100));
32
+ const mathm2 = math.matrix(Array.from({ length: dimensions }, () => Math.random() * 100));
32
33
  const floatArray1 = new Float32Array(array1);
33
34
  const floatArray2 = new Float32Array(array2);
34
35
  const intArray1 = new Int8Array(array1);
@@ -65,8 +66,8 @@ singleSuite
65
66
  .add('Array of Numbers with MathJS', () => {
66
67
  cosineDistanceMathJS(array1, array2);
67
68
  })
68
- .add('TypedArray of Float32 with MathJS', () => {
69
- cosineDistanceMathJS(floatArray1, floatArray2);
69
+ .add('MathMatrix with MathJS', () => {
70
+ cosineDistanceMathJS(mathm1, mathm2);
70
71
  })
71
72
 
72
73
  // SimSIMD
@@ -78,7 +79,11 @@ singleSuite
78
79
  })
79
80
 
80
81
  .on('cycle', (event) => {
81
- console.log(String(event.target));
82
+ if (event.target.error) {
83
+ console.error(String(event.target.error));
84
+ } else {
85
+ console.log(String(event.target));
86
+ }
82
87
  })
83
88
  .on('complete', () => {
84
89
  console.log('Fastest Single-Vector Processing is ' + singleSuite.filter('fastest').map('name'));
@@ -106,7 +111,11 @@ batchSuite
106
111
  usearch.exactSearch(intMatrix1, intMatrix2, dimensions, 1, MetricKind.Cos);
107
112
  })
108
113
  .on('cycle', (event) => {
109
- console.log(String(event.target));
114
+ if (event.target.error) {
115
+ console.error(String(event.target.error));
116
+ } else {
117
+ console.log(String(event.target));
118
+ }
110
119
  })
111
120
  .on('complete', () => {
112
121
  console.log('Fastest Batch-Vector Processing is ' + batchSuite.filter('fastest').map('name'));
@@ -115,3 +124,4 @@ batchSuite
115
124
  noCache: true,
116
125
  async: false,
117
126
  });
127
+
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }