usearch 2.8.15 → 2.8.16

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.
@@ -59,7 +59,7 @@ jobs:
59
59
  - name: Set up Node.js
60
60
  uses: actions/setup-node@v3
61
61
  with:
62
- node-version: 18
62
+ node-version: 20
63
63
  - name: Build JavaScript
64
64
  run: npm install
65
65
  - name: Test JavaScript
@@ -151,7 +151,7 @@ jobs:
151
151
  - name: Set up Node.js
152
152
  uses: actions/setup-node@v3
153
153
  with:
154
- node-version: 18
154
+ node-version: 20
155
155
  - name: Build and test JavaScript
156
156
  run: |
157
157
  npm install
@@ -210,7 +210,7 @@ jobs:
210
210
  - name: Set up Node.js
211
211
  uses: actions/setup-node@v3
212
212
  with:
213
- node-version: 18
213
+ node-version: 20
214
214
  - name: Build JavaScript
215
215
  run: npm install
216
216
  - name: Test JavaScript
@@ -272,7 +272,7 @@ jobs:
272
272
  - name: Set up Node.js
273
273
  uses: actions/setup-node@v3
274
274
  with:
275
- node-version: 18
275
+ node-version: 20
276
276
  - name: Build JavaScript
277
277
  run: npm install
278
278
  - name: Test JavaScript
@@ -24,7 +24,10 @@ jobs:
24
24
  - uses: actions/checkout@v3
25
25
  with:
26
26
  persist-credentials: false
27
- - uses: actions/setup-node@v3
27
+ - name: Set up Node.js
28
+ uses: actions/setup-node@v3
29
+ with:
30
+ node-version: 20
28
31
  - run: npm install --save-dev --prefix ./package-ci @semantic-release/exec @semantic-release/git conventional-changelog-eslint semantic-release && npx --prefix ./package-ci semantic-release
29
32
 
30
33
  rebase:
@@ -425,7 +428,7 @@ jobs:
425
428
  - name: Set up Node.js
426
429
  uses: actions/setup-node@v3
427
430
  with:
428
- node-version: 18
431
+ node-version: 20
429
432
 
430
433
  - name: Build and Test
431
434
  run: |
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.15
8
+ version: 2.8.16
9
9
  doi: 10.5281/zenodo.7949416
10
10
  date-released: 2023-10-22
11
11
  url: "https://github.com/unum-cloud/usearch"
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "usearch"
3
- version = "2.8.15"
3
+ version = "2.8.16"
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
@@ -36,7 +36,7 @@ Linux • MacOS • Windows • iOS • WebAssembly
36
36
  </p>
37
37
 
38
38
  <div align="center">
39
- <a href="https://pepy.tech/project/usearch"> <img alt="PyPI" src="https://static.pepy.tech/personalized-badge/usearch?period=month&units=abbreviation&left_color=black&right_color=blue&left_text=Python%20monthly%20installs"> </a>
39
+ <a href="https://pepy.tech/project/usearch"> <img alt="PyPI" src="https://static.pepy.tech/personalized-badge/usearch?period=total&units=abbreviation&left_color=black&right_color=blue&left_text=USearch%20Python%20installs"> </a>
40
40
  <a href="https://www.npmjs.com/package/usearch"> <img alt="NPM" src="https://img.shields.io/npm/dy/usearch?label=NPM%20installs"> </a>
41
41
  <a href="https://crates.io/crates/usearch"> <img alt="Crate" src="https://img.shields.io/crates/d/usearch?label=Crate%20installs"> </a>
42
42
  <a href="https://www.nuget.org/packages/Cloud.Unum.USearch"> <img alt="NuGet" src="https://img.shields.io/nuget/dt/Cloud.Unum.USearch?label=NuGet%20installs"> </a>
@@ -433,7 +433,7 @@ doi = {10.5281/zenodo.7949416},
433
433
  author = {Vardanian, Ash},
434
434
  title = {{USearch by Unum Cloud}},
435
435
  url = {https://github.com/unum-cloud/usearch},
436
- version = {2.8.15},
436
+ version = {2.8.16},
437
437
  year = {2023},
438
438
  month = oct,
439
439
  }
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.8.15
1
+ 2.8.16
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.15'
10
+ version = '2.8.16'
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"
@@ -11,7 +11,7 @@
11
11
 
12
12
  #define USEARCH_VERSION_MAJOR 2
13
13
  #define USEARCH_VERSION_MINOR 8
14
- #define USEARCH_VERSION_PATCH 15
14
+ #define USEARCH_VERSION_PATCH 16
15
15
 
16
16
  // Inferring C++ version
17
17
  // https://stackoverflow.com/a/61552074
@@ -1345,8 +1345,9 @@ class metric_punned_t {
1345
1345
  #if USEARCH_USE_SIMSIMD
1346
1346
  if (!configure_with_simsimd())
1347
1347
  configure_with_auto_vectorized();
1348
- #endif
1348
+ #else
1349
1349
  configure_with_auto_vectorized();
1350
+ #endif
1350
1351
 
1351
1352
  if (scalar_kind == scalar_kind_t::b1x8_k)
1352
1353
  raw_arg3_ = raw_arg4_ = divide_round_up<CHAR_BIT>(dimensions_);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "2.8.15",
3
+ "version": "2.8.16",
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/simsimd/README.md CHANGED
@@ -1,25 +1,25 @@
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
6
  <img alt="GitHub code size in bytes" src="https://img.shields.io/github/languages/code-size/ashvardanian/simsimd">
7
7
  </div>
8
8
 
9
- ## Efficient Alternative to [`scipy.spatial.distance`][scipy] and [`numpy.inner`][numpy]
9
+ ## Hardware-Accelerated Similarity Metrics and Distance Functions
10
10
 
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.
11
+ - Zero-dependency [header-only C 99](#using-simsimd-in-c) library with bindings for [Python](#using-simsimd-in-python) and [JavaScript](#using-simsimd-in-javascript).
12
+ - Targets ARM NEON, SVE, x86 AVX2, AVX-512 (VNNI, FP16) hardware backends.
13
+ - Zero-copy compatible with NumPy, PyTorch, TensorFlow, and other tensors.
14
+ - Handles `f64` double-, `f32` single-, and `f16` half-precision, `i8` integral, and binary vectors.
15
+ - __Up to 200x faster__ than [`scipy.spatial.distance`][scipy] and [`numpy.inner`][numpy].
16
+ - Used in [USearch](https://github.com/unum-cloud/usearch) and several DBMS products.
12
17
 
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).
18
+ __Implemented distance functions__ include:
19
+
20
+ - Euclidean (L2), Inner Distance, and Cosine (Angular) spatial distances.
21
+ - Hamming (~ Manhattan) and Jaccard (~ Tanimoto) binary distances.
22
+ - Kullback-Leibler and Jensen–Shannon divergences for probability distributions.
23
23
 
24
24
  [scipy]: https://docs.scipy.org/doc/scipy/reference/spatial.distance.html#module-scipy.spatial.distance
25
25
  [numpy]: https://numpy.org/doc/stable/reference/generated/numpy.inner.html
@@ -43,18 +43,18 @@ Given 1000 embeddings from OpenAI Ada API with 1536 dimensions, running on the A
43
43
  | :------------- | ----------------: | ----------------: | ---------------: | :------------------------------------- | :-------------- |
44
44
  | Cosine | __32 x__ | __79 x__ | __133 x__ | `scipy.spatial.distance.cosine` | `cosine` |
45
45
  | Euclidean ² | __5 x__ | __26 x__ | __17 x__ | `scipy.spatial.distance.sqeuclidean` | `sqeuclidean` |
46
- | Inner Product | __2 x__ | __9 x__ | __18 x__ | `numpy.inner` | `inner` |
46
+ | Inner Distance | __2 x__ | __9 x__ | __18 x__ | `numpy.inner` | `inner` |
47
47
  | Jensen Shannon | __31 x__ | __53 x__ | | `scipy.spatial.distance.jensenshannon` | `jensenshannon` |
48
48
 
49
49
  ### Intel Sapphire Rapids
50
50
 
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.
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.
52
52
 
53
53
  | Kind | GCC 12 `f32` | GCC 12 `f16` | SimSIMD `f16` | `f16` improvement |
54
54
  | :------------- | -----------: | -----------: | ------------: | ----------------: |
55
55
  | Cosine | 3.28 M/s | _336.29 k/s_ | _6.88 M/s_ | __20 x__ |
56
56
  | 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__ |
57
+ | Inner Distance | 3.81 M/s | _192.02 k/s_ | _5.99 M/s_ | __31 x__ |
58
58
  | Jensen Shannon | 1.18 M/s | _18.13 k/s_ | _2.14 M/s_ | __118 x__ |
59
59
 
60
60
  __Broader Benchmarking Results__:
@@ -63,7 +63,7 @@ __Broader Benchmarking Results__:
63
63
  - [4th Gen Intel Xeon Platinum](https://ashvardanian.com/posts/simsimd-faster-scipy/#appendix-2-performance-on-4th-gen-intel-xeon-platinum-8480).
64
64
  - [AWS Graviton 3](https://ashvardanian.com/posts/simsimd-faster-scipy/#appendix-3-performance-on-aws-graviton-3).
65
65
 
66
- ## Using in Python
66
+ ## Using SimSIMD in Python
67
67
 
68
68
  ### Installation
69
69
 
@@ -92,7 +92,7 @@ batch2 = np.random.randn(100, 1536).astype(np.float32)
92
92
  dist = simsimd.cosine(batch1, batch2)
93
93
  ```
94
94
 
95
- If either batch has more than one vector, the other batch must have one or same number of vectors.
95
+ If either batch has more than one vector, the other batch must have one or the same number of vectors.
96
96
  If it contains just one, the value is broadcasted.
97
97
 
98
98
  ### All Pairwise Distances
@@ -124,7 +124,7 @@ print(simsimd.get_capabilities())
124
124
  ### Using Python API with USearch
125
125
 
126
126
  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.
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.
128
128
 
129
129
  ```py
130
130
  from usearch.index import Index, CompiledMetric, MetricKind, MetricSignature
@@ -141,7 +141,18 @@ index = Index(256, metric=metric)
141
141
 
142
142
  ## Using SimSIMD in JavaScript
143
143
 
144
- After you add `simsimd` as a dependency and `npm install`, you will be able to call SimSIMD function on various `TypedArray` variants:
144
+ To install, choose one of the following options depending on your environment:
145
+
146
+ - `npm install --save simsimd`
147
+ - `yarn add simsimd`
148
+ - `pnpm add simsimd`
149
+ - `bun install simsimd`
150
+
151
+ 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).
152
+
153
+ 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.
154
+
155
+ After you install it, you will be able to call the SimSIMD functions on various `TypedArray` variants:
145
156
 
146
157
  ```js
147
158
  const { sqeuclidean, cosine, inner, hamming, jaccard } = require('simsimd');
@@ -155,8 +166,6 @@ console.log('Squared Euclidean Distance:', distance);
155
166
 
156
167
  ## Using SimSIMD in C
157
168
 
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
169
  For integration within a CMake-based project, add the following segment to your `CMakeLists.txt`:
161
170
 
162
171
  ```cmake
@@ -166,12 +175,30 @@ FetchContent_Declare(
166
175
  GIT_SHALLOW TRUE
167
176
  )
168
177
  FetchContent_MakeAvailable(simsimd)
169
- include_directories(${simsimd_SOURCE_DIR}/include)
170
178
  ```
171
179
 
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.
180
+ If you're aiming to utilize the `_Float16` functionality with SimSIMD, ensure your development environment is compatible with C 11.
181
+ For other functionalities of SimSIMD, C 99 compatibility will suffice.
182
+ A minimal usage example would be:
173
183
 
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.
184
+ ```c
185
+ #include <simsimd/simsimd.h>
186
+
187
+ int main() {
188
+ simsimd_f32_t vector_a[1536];
189
+ simsimd_f32_t vector_b[1536];
190
+ simsimd_f32_t distance = simsimd_avx512_f32_cos(vector_a, vector_b, 1536);
191
+ return 0;
192
+ }
193
+ ```
194
+
195
+ All of the functions names follow the same pattern: `simsimd_{backend}_{type}_{metric}`.
196
+
197
+ - The backend can be `avx512`, `avx2`, `neon`, or `sve`.
198
+ - The type can be `f64`, `f32`, `f16`, `i8`, or `b8`.
199
+ - The metric can be `cos`, `ip`, `l2sq`, `hamming`, `jaccard`, `kl`, or `js`.
200
+
201
+ 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
202
 
176
203
  ## Benchmarking and Contributing
177
204
 
@@ -189,6 +216,9 @@ __To test and benchmark with Python bindings__:
189
216
  ```sh
190
217
  pip install -e .
191
218
  pytest python/test.py -s -x
219
+
220
+ pip install numpy scipy scikit-learn # for comparison baselines
221
+ python python/bench.py # to run default benchmarks
192
222
  python python/bench.py --n 1000 --ndim 1000000 # batch size and dimensions
193
223
  ```
194
224
 
@@ -0,0 +1,51 @@
1
+ const benchmark = require('benchmark');
2
+
3
+ // Assuming the vectors are of the same length
4
+ function cosineDistance(a, b) {
5
+ let dotProduct = 0;
6
+ let magA = 0;
7
+ let magB = 0;
8
+ for (let i = 0; i < a.length; i++) {
9
+ dotProduct += a[i] * b[i];
10
+ magA += a[i] * a[i];
11
+ magB += b[i] * b[i];
12
+ }
13
+ return 1 - (dotProduct / (Math.sqrt(magA) * Math.sqrt(magB)));
14
+ }
15
+
16
+
17
+ // Generate random data for testing
18
+ const dimensions = 1536; // Adjust dimensions as needed
19
+ const array1 = Array.from({ length: dimensions }, () => Math.random() * 100);
20
+ const array2 = Array.from({ length: dimensions }, () => Math.random() * 100);
21
+ const floatArray1 = new Float32Array(array1);
22
+ const floatArray2 = new Float32Array(array2);
23
+
24
+
25
+ // Create benchmark suite
26
+ const singleSuite = new benchmark.Suite('Single Vector Processing');
27
+
28
+ // Single-vector processing benchmarks
29
+ singleSuite
30
+
31
+ // Pure JavaScript
32
+ .add('Array of Numbers', () => {
33
+ cosineDistance(array1, array2);
34
+ })
35
+ .add('TypedArray of Float32', () => {
36
+ cosineDistance(floatArray1, floatArray2);
37
+ })
38
+ .on('cycle', (event) => {
39
+ if (event.target.error) {
40
+ console.error(String(event.target.error));
41
+ } else {
42
+ console.log(String(event.target));
43
+ }
44
+ })
45
+ .on('complete', () => {
46
+ console.log('Fastest Single-Vector Processing is ' + singleSuite.filter('fastest').map('name'));
47
+ })
48
+ .run({
49
+ noCache: true,
50
+ async: false,
51
+ });
@@ -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
  }
@@ -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 6
19
+ #define SIMSIMD_VERSION_PATCH 0
16
20
 
17
21
  #include "binary.h" // Hamming, Jaccard
18
22
  #include "probability.h" // Kullback-Leibler, Jensen–Shannon
@@ -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:
@@ -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
+ }