usearch 2.16.8 → 2.16.9

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.
package/README.md CHANGED
@@ -546,7 +546,7 @@ doi = {10.5281/zenodo.7949416},
546
546
  author = {Vardanian, Ash},
547
547
  title = {{USearch by Unum Cloud}},
548
548
  url = {https://github.com/unum-cloud/usearch},
549
- version = {2.16.8},
549
+ version = {2.16.9},
550
550
  year = {2023},
551
551
  month = oct,
552
552
  }
@@ -9,7 +9,7 @@
9
9
 
10
10
  #define USEARCH_VERSION_MAJOR 2
11
11
  #define USEARCH_VERSION_MINOR 16
12
- #define USEARCH_VERSION_PATCH 8
12
+ #define USEARCH_VERSION_PATCH 9
13
13
 
14
14
  // Inferring C++ version
15
15
  // https://stackoverflow.com/a/61552074
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "2.16.8",
3
+ "version": "2.16.9",
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",
Binary file
Binary file
@@ -6,6 +6,26 @@ To keep the quality of the code high, we have a set of [guidelines](https://gith
6
6
  - [How to organize branches?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#branches)
7
7
  - [How to style commits?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#commits)
8
8
 
9
+ ## Navigating the Codebase
10
+
11
+ Primary kernels are implemented in header files under `include/simsimd/`:
12
+
13
+ - `dot.h` - dot products for real and complex vectors.
14
+ - `spatial.h` - spatial distances: L2, cosine distance.
15
+ - `binary.h` - binary distances: Hamming, Jaccard, etc.
16
+ - `probability.h` - probability metrics: KL-divergence, Jensen-Shannon, etc.
17
+ - `sparse.h` - sparse distances: weighted and normal set intersections.
18
+ - `curved.h` - bilinear forms for real and complex vectors, and Mahalanobis distance.
19
+
20
+ Bindings to other languages are in the respective directories:
21
+
22
+ - `python/lib.c` - Python bindings.
23
+ - `javascript/lib.c` - JavaScript bindings.
24
+ - `rust/lib.rs` - Rust bindings.
25
+ - `swift/SimSIMD.swift` - Swift bindings.
26
+
27
+ All tests, benchmarks, and examples are placed in the `scripts/` directory, if compatible with the toolchain of the implementation language.
28
+
9
29
  ## C and C++
10
30
 
11
31
  To rerun experiments utilize the following command:
@@ -63,6 +83,15 @@ cmake -D CMAKE_BUILD_TYPE=Release \
63
83
  cmake --build build_release --config Release
64
84
  ```
65
85
 
86
+ When benchmarking, make sure to disable multi-threading in the BLAS library, as it may interfere with the results:
87
+
88
+ ```sh
89
+ export OPENBLAS_NUM_THREADS=1 # for OpenBLAS
90
+ export MKL_NUM_THREADS=1 # for Intel MKL
91
+ export VECLIB_MAXIMUM_THREADS=1 # for Apple Accelerate
92
+ export BLIS_NUM_THREADS=1 # for BLIS
93
+ ```
94
+
66
95
  ## Python
67
96
 
68
97
  Testing:
@@ -140,7 +169,6 @@ cibuildwheel --platform linux # works on any OS and builds all
140
169
  cibuildwheel --platform linux --archs x86_64 # 64-bit x86, the most common on desktop and servers
141
170
  cibuildwheel --platform linux --archs aarch64 # 64-bit Arm for mobile devices, Apple M-series, and AWS Graviton
142
171
  cibuildwheel --platform linux --archs i686 # 32-bit Linux
143
- cibuildwheel --platform linux --archs s390x # emulating big-endian IBM Z
144
172
  cibuildwheel --platform macos # works only on MacOS
145
173
  cibuildwheel --platform windows # works only on Windows
146
174
  ```
@@ -168,35 +196,65 @@ open target/criterion/report/index.html
168
196
 
169
197
  ## JavaScript
170
198
 
171
- If you don't have NPM installed:
199
+ ### NodeJS
200
+
201
+ If you don't have the environment configured, here are the [installation options](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script) with different tools:
202
+
203
+ ```sh
204
+ wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash # Linux
205
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash # MacOS
206
+ ```
207
+
208
+ Install dependencies:
172
209
 
173
210
  ```sh
174
- wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
175
211
  nvm install 20
212
+ npm install -g typescript # Install the TypeScript compiler globally
213
+ npm install --save-dev @types/node # Install the Node.js type definitions as a dev dependency
176
214
  ```
177
215
 
178
216
  Testing and benchmarking:
179
217
 
180
218
  ```sh
181
- npm install -g typescript
182
- npm run build-js
183
- npm test
184
- npm run bench
219
+ npm run build-js # Build the JavaScript code using TypeScript configurations
220
+ npm test # Run the test suite
221
+ npm run bench # Run the benchmark script
185
222
  ```
186
223
 
187
- Running with Deno:
224
+ ### Deno
225
+
226
+ If you don't have the environment configured, here are [installation options](https://docs.deno.com/runtime/getting_started/installation/) with different tools:
227
+
228
+ ```sh
229
+ wget -qO- https://deno.land/x/install/install.sh | sh # Linux
230
+ curl -fsSL https://deno.land/install.sh | sh # MacOS
231
+ irm https://deno.land/install.ps1 | iex # Windows
232
+ ```
233
+
234
+ Testing:
188
235
 
189
236
  ```sh
190
237
  deno test --allow-read
191
238
  ```
192
239
 
193
- Running with Bun:
240
+ ### Bun
241
+
242
+ If you don't have the environment configured, here are the [installation options](https://bun.sh/docs/installation) with different tools:
243
+
244
+ ```sh
245
+ wget -qO- https://bun.sh/install | bash # for Linux
246
+ curl -fsSL https://bun.sh/install | bash # for macOS and WSL
247
+ ```
248
+
249
+ Testing:
194
250
 
195
251
  ```sh
196
- npm install -g bun
197
- bun test
252
+ bun install
253
+ bun test ./scripts/test.mjs
198
254
  ```
199
255
 
256
+ ... wouldn't work for now.
257
+
200
258
  ## Swift
201
259
 
202
260
  ```sh
@@ -239,4 +297,3 @@ cd golang
239
297
  go test # To test
240
298
  go test -run=^$ -bench=. -benchmem # To benchmark
241
299
  ```
242
-
@@ -496,7 +496,7 @@ dependencies = [
496
496
 
497
497
  [[package]]
498
498
  name = "simsimd"
499
- version = "6.0.5"
499
+ version = "6.2.3"
500
500
  dependencies = [
501
501
  "cc",
502
502
  "criterion",
@@ -1,7 +1,7 @@
1
1
  [package]
2
2
  name = "simsimd"
3
3
  description = "Portable mixed-precision BLAS-like vector math library for x86 and ARM"
4
- version = "6.0.5"
4
+ version = "6.2.3"
5
5
  edition = "2021"
6
6
  license = "Apache-2.0"
7
7
  authors = ["Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
package/simsimd/README.md CHANGED
@@ -9,7 +9,7 @@ The rare few that support minimal mixed precision, run only on one platform, and
9
9
  SimSIMD provides an alternative.
10
10
  1️⃣ SimSIMD functions are practically as fast as `memcpy`.
11
11
  2️⃣ Unlike BLAS, most kernels are designed for mixed-precision and bit-level operations.
12
- 3️⃣ SimSIMD [compiles to more platforms than NumPy (105 vs 35)][compatibility] and has more backends than most BLAS implementations, and more high-level interfaces than most libraries.
12
+ 3️⃣ SimSIMD often [ships more binaries than NumPy][compatibility] and has more backends than most BLAS implementations, and more high-level interfaces than most libraries.
13
13
 
14
14
  [benchmarks]: https://ashvardanian.com/posts/simsimd-faster-scipy
15
15
  [compatibility]: https://pypi.org/project/simsimd/#files
@@ -42,7 +42,7 @@ SimSIMD provides an alternative.
42
42
 
43
43
  ## Features
44
44
 
45
- __SimSIMD__ (Arabic: "سيمسيم دي") is a mixed-precision math library of __over 200 SIMD-optimized kernels__ extensively used in AI, Search, and DBMS workloads.
45
+ __SimSIMD__ (Arabic: "سيمسيم دي") is a mixed-precision math library of __over 350 SIMD-optimized kernels__ extensively used in AI, Search, and DBMS workloads.
46
46
  Named after the iconic ["Open Sesame"](https://en.wikipedia.org/wiki/Open_sesame) command that opened doors to treasure in _Ali Baba and the Forty Thieves_, SimSimd can help you 10x the cost-efficiency of your computational pipelines.
47
47
  Implemented distance functions include:
48
48
 
@@ -92,17 +92,196 @@ You can learn more about the technical implementation details in the following b
92
92
 
93
93
  ## Benchmarks
94
94
 
95
- For reference, we use 1536-dimensional vectors, like the embeddings produced by the OpenAI Ada API.
96
- Comparing the serial code throughput produced by GCC 12 to hand-optimized kernels in SimSIMD, we see the following single-core improvements for the two most common vector-vector similarity metrics - the Cosine similarity and the Euclidean distance:
95
+ <table style="width: 100%; text-align: center; table-layout: fixed;">
96
+ <colgroup>
97
+ <col style="width: 33%;">
98
+ <col style="width: 33%;">
99
+ <col style="width: 33%;">
100
+ </colgroup>
101
+ <tr>
102
+ <th align="center">NumPy</th>
103
+ <th align="center">C 99</th>
104
+ <th align="center">SimSIMD</th>
105
+ </tr>
106
+ <!-- Cosine distances with different precision levels -->
107
+ <tr>
108
+ <td colspan="4" align="center">cosine distances between 1536d vectors in <code>int8</code></td>
109
+ </tr>
110
+ <tr>
111
+ <td align="center"> <!-- scipy.spatial.distance.cosine -->
112
+ 🚧 overflows<br/>
113
+ </td>
114
+ <td align="center"> <!-- serial -->
115
+ <span style="color:#ABABAB;">x86:</span> <b>10,548,600</b> ops/s<br/>
116
+ <span style="color:#ABABAB;">arm:</span> <b>11,379,300</b> ops/s
117
+ </td>
118
+ <td align="center"> <!-- simsimd -->
119
+ <span style="color:#ABABAB;">x86:</span> <b>16,151,800</b> ops/s<br/>
120
+ <span style="color:#ABABAB;">arm:</span> <b>13,524,000</b> ops/s
121
+ </td>
122
+ </tr>
123
+ <tr>
124
+ <td colspan="4" align="center">cosine distances between 1536d vectors in <code>bfloat16</code></td>
125
+ </tr>
126
+ <tr>
127
+ <td align="center"> <!-- scipy.spatial.distance.cosine -->
128
+ 🚧 not supported<br/>
129
+ </td>
130
+ <td align="center"> <!-- serial -->
131
+ <span style="color:#ABABAB;">x86:</span> <b>119,835</b> ops/s<br/>
132
+ <span style="color:#ABABAB;">arm:</span> <b>403,909</b> ops/s
133
+ </td>
134
+ <td align="center"> <!-- simsimd -->
135
+ <span style="color:#ABABAB;">x86:</span> <b>9,738,540</b> ops/s<br/>
136
+ <span style="color:#ABABAB;">arm:</span> <b>4,881,900</b> ops/s
137
+ </td>
138
+ </tr>
139
+ <tr>
140
+ <td colspan="4" align="center">cosine distances between 1536d vectors in <code>float16</code></td>
141
+ </tr>
142
+ <tr>
143
+ <td align="center"> <!-- scipy.spatial.distance.cosine -->
144
+ <span style="color:#ABABAB;">x86:</span> <b>40,481</b> ops/s<br/>
145
+ <span style="color:#ABABAB;">arm:</span> <b>21,451</b> ops/s
146
+ </td>
147
+ <td align="center"> <!-- serial -->
148
+ <span style="color:#ABABAB;">x86:</span> <b>501,310</b> ops/s<br/>
149
+ <span style="color:#ABABAB;">arm:</span> <b>871,963</b> ops/s
150
+ </td>
151
+ <td align="center"> <!-- simsimd -->
152
+ <span style="color:#ABABAB;">x86:</span> <b>7,627,600</b> ops/s<br/>
153
+ <span style="color:#ABABAB;">arm:</span> <b>3,316,810</b> ops/s
154
+ </td>
155
+ </tr>
156
+ <tr>
157
+ <td colspan="4" align="center">cosine distances between 1536d vectors in <code>float32</code></td>
158
+ </tr>
159
+ <tr>
160
+ <td align="center"> <!-- scipy.spatial.distance.cosine -->
161
+ <span style="color:#ABABAB;">x86:</span> <b>253,902</b> ops/s<br/>
162
+ <span style="color:#ABABAB;">arm:</span> <b>46,394</b> ops/s
163
+ </td>
164
+ <td align="center"> <!-- serial -->
165
+ <span style="color:#ABABAB;">x86:</span> <b>882,484</b> ops/s<br/>
166
+ <span style="color:#ABABAB;">arm:</span> <b>399,661</b> ops/s
167
+ </td>
168
+ <td align="center"> <!-- simsimd -->
169
+ <span style="color:#ABABAB;">x86:</span> <b>8,202,910</b> ops/s<br/>
170
+ <span style="color:#ABABAB;">arm:</span> <b>3,400,620</b> ops/s
171
+ </td>
172
+ </tr>
173
+ <tr>
174
+ <td colspan="4" align="center">cosine distances between 1536d vectors in <code>float64</code></td>
175
+ </tr>
176
+ <tr>
177
+ <td align="center"> <!-- scipy.spatial.distance.cosine -->
178
+ <span style="color:#ABABAB;">x86:</span> <b>212,421</b> ops/s<br/>
179
+ <span style="color:#ABABAB;">arm:</span> <b>52,904</b> ops/s
180
+ </td>
181
+ <td align="center"> <!-- serial -->
182
+ <span style="color:#ABABAB;">x86:</span> <b>839,301</b> ops/s<br/>
183
+ <span style="color:#ABABAB;">arm:</span> <b>837,126</b> ops/s
184
+ </td>
185
+ <td align="center"> <!-- simsimd -->
186
+ <span style="color:#ABABAB;">x86:</span> <b>1,538,530</b> ops/s<br/>
187
+ <span style="color:#ABABAB;">arm:</span> <b>1,678,920</b> ops/s
188
+ </td>
189
+ </tr>
190
+
191
+ <!-- Euclidean distance with different precision level -->
192
+ <tr>
193
+ <td colspan="4" align="center">eculidean distance between 1536d vectors in <code>int8</code></td>
194
+ </tr>
195
+ <tr>
196
+ <td align="center"> <!-- scipy.spatial.distance.sqeuclidean -->
197
+ <span style="color:#ABABAB;">x86:</span> <b>252,113</b> ops/s<br/>
198
+ <span style="color:#ABABAB;">arm:</span> <b>177,443</b> ops/s
199
+ </td>
200
+ <td align="center"> <!-- serial -->
201
+ <span style="color:#ABABAB;">x86:</span> <b>6,690,110</b> ops/s<br/>
202
+ <span style="color:#ABABAB;">arm:</span> <b>4,114,160</b> ops/s
203
+ </td>
204
+ <td align="center"> <!-- simsimd -->
205
+ <span style="color:#ABABAB;">x86:</span> <b>18,989,000</b> ops/s<br/>
206
+ <span style="color:#ABABAB;">arm:</span> <b>18,878,200</b> ops/s
207
+ </td>
208
+ </tr>
209
+ <tr>
210
+ <td colspan="4" align="center">eculidean distance between 1536d vectors in <code>bfloat16</code></td>
211
+ </tr>
212
+ <tr>
213
+ <td align="center"> <!-- scipy.spatial.distance.sqeuclidean -->
214
+ 🚧 not supported<br/>
215
+ </td>
216
+ <td align="center"> <!-- serial -->
217
+ <span style="color:#ABABAB;">x86:</span> <b>119,842</b> ops/s<br/>
218
+ <span style="color:#ABABAB;">arm:</span> <b>1,049,230</b> ops/s
219
+ </td>
220
+ <td align="center"> <!-- simsimd -->
221
+ <span style="color:#ABABAB;">x86:</span> <b>9,727,210</b> ops/s<br/>
222
+ <span style="color:#ABABAB;">arm:</span> <b>4,233,420</b> ops/s
223
+ </td>
224
+ </tr>
225
+ <tr>
226
+ <td colspan="4" align="center">eculidean distance between 1536d vectors in <code>float16</code></td>
227
+ </tr>
228
+ <tr>
229
+ <td align="center"> <!-- scipy.spatial.distance.sqeuclidean -->
230
+ <span style="color:#ABABAB;">x86:</span> <b>54,621</b> ops/s<br/>
231
+ <span style="color:#ABABAB;">arm:</span> <b>71,793</b> ops/s
232
+ </td>
233
+ <td align="center"> <!-- serial -->
234
+ <span style="color:#ABABAB;">x86:</span> <b>196,413</b> ops/s<br/>
235
+ <span style="color:#ABABAB;">arm:</span> <b>911,370</b> ops/s
236
+ </td>
237
+ <td align="center"> <!-- simsimd -->
238
+ <span style="color:#ABABAB;">x86:</span> <b>19,466,800</b> ops/s<br/>
239
+ <span style="color:#ABABAB;">arm:</span> <b>3,522,760</b> ops/s
240
+ </td>
241
+ </tr>
242
+ <tr>
243
+ <td colspan="4" align="center">eculidean distance between 1536d vectors in <code>float32</code></td>
244
+ </tr>
245
+ <tr>
246
+ <td align="center"> <!-- scipy.spatial.distance.sqeuclidean -->
247
+ <span style="color:#ABABAB;">x86:</span> <b>424,944</b> ops/s<br/>
248
+ <span style="color:#ABABAB;">arm:</span> <b>292,629</b> ops/s
249
+ </td>
250
+ <td align="center"> <!-- serial -->
251
+ <span style="color:#ABABAB;">x86:</span> <b>1,295,210</b> ops/s<br/>
252
+ <span style="color:#ABABAB;">arm:</span> <b>1,055,940</b> ops/s
253
+ </td>
254
+ <td align="center"> <!-- simsimd -->
255
+ <span style="color:#ABABAB;">x86:</span> <b>8,924,100</b> ops/s<br/>
256
+ <span style="color:#ABABAB;">arm:</span> <b>3,602,650</b> ops/s
257
+ </td>
258
+ </tr>
259
+ <tr>
260
+ <td colspan="4" align="center">eculidean distance between 1536d vectors in <code>float64</code></td>
261
+ </tr>
262
+ <tr>
263
+ <td align="center"> <!-- scipy.spatial.distance.sqeuclidean -->
264
+ <span style="color:#ABABAB;">x86:</span> <b>334,929</b> ops/s<br/>
265
+ <span style="color:#ABABAB;">arm:</span> <b>237,505</b> ops/s
266
+ </td>
267
+ <td align="center"> <!-- serial -->
268
+ <span style="color:#ABABAB;">x86:</span> <b>1,215,190</b> ops/s<br/>
269
+ <span style="color:#ABABAB;">arm:</span> <b>905,782</b> ops/s
270
+ </td>
271
+ <td align="center"> <!-- simsimd -->
272
+ <span style="color:#ABABAB;">x86:</span> <b>1,701,740</b> ops/s<br/>
273
+ <span style="color:#ABABAB;">arm:</span> <b>1,735,840</b> ops/s
274
+ </td>
275
+ </tr>
276
+ <!-- Bilinear forms -->
277
+ <!-- Sparse set intersections -->
278
+ </table>
97
279
 
98
- | Type | Apple M2 Pro | Intel Sapphire Rapids | AWS Graviton 4 |
99
- | :--------- | ----------------------------: | -------------------------------: | ------------------------------: |
100
- | `float64` | 18.5 → 28.8 GB/s <br/> + 56 % | 21.9 → 41.4 GB/s <br/> + 89 % | 20.7 → 41.3 GB/s <br/> + 99 % |
101
- | `float32` | 9.2 → 29.6 GB/s <br/> + 221 % | 10.9 → 95.8 GB/s <br/> + 779 % | 4.9 → 41.9 GB/s <br/> + 755 % |
102
- | `float16` | 4.6 → 14.6 GB/s <br/> + 217 % | 3.1 → 108.4 GB/s <br/> + 3,397 % | 5.4 → 39.3 GB/s <br/> + 627 % |
103
- | `bfloat16` | 4.6 → 26.3 GB/s <br/> + 472 % | 0.8 → 59.5 GB/s <br/> +7,437 % | 2.5 → 29.9 GB/s <br/> + 1,096 % |
104
- | `int8` | 25.8 → 47.1 GB/s <br/> + 83 % | 33.1 → 65.3 GB/s <br/> + 97 % | 35.2 → 43.5 GB/s <br/> + 24 % |
105
- | `uint8` | | 32.5 → 66.5 GB/s <br/> + 105 % | |
280
+ > For benchmarks we mostly use 1536-dimensional vectors, like the embeddings produced by the OpenAI Ada API.
281
+ > The code was compiled with GCC 12, using glibc v2.35.
282
+ > The benchmarks performed on Arm-based Graviton3 AWS `c7g` instances and `r7iz` Intel Sapphire Rapids.
283
+ > Most modern Arm-based 64-bit CPUs will have similar relative speedups.
284
+ > Variance withing x86 CPUs will be larger.
106
285
 
107
286
  Similar speedups are often observed even when compared to BLAS and LAPACK libraries underlying most numerical computing libraries, including NumPy and SciPy in Python.
108
287
  Broader benchmarking results:
@@ -162,10 +341,22 @@ dist = simsimd.cosine(vec1, vec2, "int8")
162
341
  dist = simsimd.cosine(vec1, vec2, "float16")
163
342
  dist = simsimd.cosine(vec1, vec2, "float32")
164
343
  dist = simsimd.cosine(vec1, vec2, "float64")
165
- dist = simsimd.hamming(vec1, vec2, "bit8")
344
+ dist = simsimd.hamming(vec1, vec2, "bin8")
345
+ ```
346
+
347
+ Binary distance functions are computed at a bit-level.
348
+ Meaning a vector of 10x 8-bit integers will be treated as a sequence of 80 individual bits or dimensions.
349
+ This differs from NumPy, that can't handle smaller-than-byte types, but you can still avoid the `bin8` argument by reinterpreting the vector as booleans:
350
+
351
+ ```py
352
+ vec1 = np.random.randint(2, size=80).astype(np.uint8).packbits().view(np.bool_)
353
+ vec2 = np.random.randint(2, size=80).astype(np.uint8).packbits().view(np.bool_)
354
+ hamming_distance = simsimd.hamming(vec1, vec2)
355
+ jaccard_distance = simsimd.jaccard(vec1, vec2)
166
356
  ```
167
357
 
168
358
  With other frameworks, like PyTorch, one can get a richer type-system than NumPy, but the lack of good CPython interoperability makes it hard to pass data without copies.
359
+ Here is an example of using SimSIMD with PyTorch to compute the cosine similarity between two `bfloat16` vectors:
169
360
 
170
361
  ```py
171
362
  import numpy as np
@@ -181,7 +372,7 @@ torch.randn(8, out=vec2)
181
372
 
182
373
  # Both libs will look into the same memory buffers and report the same results
183
374
  dist_slow = 1 - torch.nn.functional.cosine_similarity(vec1, vec2, dim=0)
184
- dist_fast = simsimd.cosine(buf1, buf2, "bf16")
375
+ dist_fast = simsimd.cosine(buf1, buf2, "bfloat16")
185
376
  ```
186
377
 
187
378
  It also allows using SimSIMD for half-precision complex numbers, which NumPy does not support.
@@ -254,9 +445,9 @@ distances: DistancesTensor = simsimd.cdist(matrix1, matrix2, metric="cosine")
254
445
  distances_array: np.ndarray = np.array(distances, copy=True) # now managed by NumPy
255
446
  ```
256
447
 
257
- ### Elementwise Kernels
448
+ ### Element-wise Kernels
258
449
 
259
- SimSIMD also provides mixed-precision elementwise kernels, where the input vectors and the output have the same numeric type, but the intermediate accumulators are of a higher precision.
450
+ SimSIMD also provides mixed-precision element-wise kernels, where the input vectors and the output have the same numeric type, but the intermediate accumulators are of a higher precision.
260
451
 
261
452
  ```py
262
453
  import numpy as np
@@ -591,9 +782,9 @@ const binaryVectorB = toBinary(vectorB);
591
782
  const distance = hamming(binaryVectorA, binaryVectorB);
592
783
  ```
593
784
 
594
- ## Using SimSIMD in Sift
785
+ ## Using SimSIMD in Swift
595
786
 
596
- To install, simply add the following dependency to you `Package.swift`:
787
+ To install, simply add the following dependency to your `Package.swift`:
597
788
 
598
789
  ```swift
599
790
  dependencies: [
@@ -677,23 +868,29 @@ To override compilation settings and switch between runtime and compile-time dis
677
868
  #include <simsimd/simsimd.h>
678
869
 
679
870
  int main() {
871
+ simsimd_i8_t i8[1536];
872
+ simsimd_i8_t u8[1536];
680
873
  simsimd_f64_t f64s[1536];
681
874
  simsimd_f32_t f32s[1536];
682
875
  simsimd_f16_t f16s[1536];
683
- simsimd_i8_t i8[1536];
876
+ simsimd_bf16_t bf16s[1536];
684
877
  simsimd_distance_t distance;
685
878
 
686
879
  // Cosine distance between two vectors
687
880
  simsimd_cos_i8(i8s, i8s, 1536, &distance);
881
+ simsimd_cos_u8(u8s, u8s, 1536, &distance);
688
882
  simsimd_cos_f16(f16s, f16s, 1536, &distance);
689
883
  simsimd_cos_f32(f32s, f32s, 1536, &distance);
690
884
  simsimd_cos_f64(f64s, f64s, 1536, &distance);
885
+ simsimd_cos_bf16(bf16s, bf16s, 1536, &distance);
691
886
 
692
887
  // Euclidean distance between two vectors
693
888
  simsimd_l2sq_i8(i8s, i8s, 1536, &distance);
889
+ simsimd_l2sq_u8(u8s, u8s, 1536, &distance);
694
890
  simsimd_l2sq_f16(f16s, f16s, 1536, &distance);
695
891
  simsimd_l2sq_f32(f32s, f32s, 1536, &distance);
696
892
  simsimd_l2sq_f64(f64s, f64s, 1536, &distance);
893
+ simsimd_l2sq_bf16(bf16s, bf16s, 1536, &distance);
697
894
 
698
895
  return 0;
699
896
  }
@@ -705,25 +902,41 @@ int main() {
705
902
  #include <simsimd/simsimd.h>
706
903
 
707
904
  int main() {
708
- simsimd_f64_t f64s[1536];
709
- simsimd_f32_t f32s[1536];
905
+ // SimSIMD provides "sized" type-aliases without relying on `stdint.h`
906
+ simsimd_i8_t i8[1536];
907
+ simsimd_i8_t u8[1536];
710
908
  simsimd_f16_t f16s[1536];
711
- simsimd_distance_t distance;
712
-
713
- // Inner product between two vectors
714
- simsimd_dot_f16(f16s, f16s, 1536, &distance);
715
- simsimd_dot_f32(f32s, f32s, 1536, &distance);
716
- simsimd_dot_f64(f64s, f64s, 1536, &distance);
909
+ simsimd_f32_t f32s[1536];
910
+ simsimd_f64_t f64s[1536];
911
+ simsimd_bf16_t bf16s[1536];
912
+ simsimd_distance_t product;
913
+
914
+ // Inner product between two real vectors
915
+ simsimd_dot_i8(i8s, i8s, 1536, &product);
916
+ simsimd_dot_u8(u8s, u8s, 1536, &product);
917
+ simsimd_dot_f16(f16s, f16s, 1536, &product);
918
+ simsimd_dot_f32(f32s, f32s, 1536, &product);
919
+ simsimd_dot_f64(f64s, f64s, 1536, &product);
920
+ simsimd_dot_bf16(bf16s, bf16s, 1536, &product);
921
+
922
+ // SimSIMD provides complex types with `real` and `imag` fields
923
+ simsimd_f64c_t f64s[768];
924
+ simsimd_f32c_t f32s[768];
925
+ simsimd_f16c_t f16s[768];
926
+ simsimd_bf16c_t bf16s[768];
927
+ simsimd_distance_t products[2]; // real and imaginary parts
717
928
 
718
929
  // Complex inner product between two vectors
719
- simsimd_dot_f16c(f16s, f16s, 1536, &distance);
720
- simsimd_dot_f32c(f32s, f32s, 1536, &distance);
721
- simsimd_dot_f64c(f64s, f64s, 1536, &distance);
930
+ simsimd_dot_f16c(f16cs, f16cs, 768, &products[0]);
931
+ simsimd_dot_f32c(f32cs, f32cs, 768, &products[0]);
932
+ simsimd_dot_f64c(f64cs, f64cs, 768, &products[0]);
933
+ simsimd_dot_bf16c(bf16cs, bf16cs, 768, &products[0]);
722
934
 
723
935
  // Complex conjugate inner product between two vectors
724
- simsimd_vdot_f16c(f16s, f16s, 1536, &distance);
725
- simsimd_vdot_f32c(f32s, f32s, 1536, &distance);
726
- simsimd_vdot_f64c(f64s, f64s, 1536, &distance);
936
+ simsimd_vdot_f16c(f16cs, f16cs, 768, &products[0]);
937
+ simsimd_vdot_f32c(f32cs, f32cs, 768, &products[0]);
938
+ simsimd_vdot_f64c(f64cs, f64cs, 768, &products[0]);
939
+ simsimd_vdot_bf16c(bf16cs, bf16cs, 768, &products[0]);
727
940
  return 0;
728
941
  }
729
942
  ```
@@ -751,17 +964,17 @@ int main() {
751
964
  simsimd_f64_t f64s[1536];
752
965
  simsimd_f32_t f32s[1536];
753
966
  simsimd_f16_t f16s[1536];
754
- simsimd_distance_t distance;
967
+ simsimd_distance_t divergence;
755
968
 
756
969
  // Jensen-Shannon divergence between two vectors
757
- simsimd_js_f16(f16s, f16s, 1536, &distance);
758
- simsimd_js_f32(f32s, f32s, 1536, &distance);
759
- simsimd_js_f64(f64s, f64s, 1536, &distance);
970
+ simsimd_js_f16(f16s, f16s, 1536, &divergence);
971
+ simsimd_js_f32(f32s, f32s, 1536, &divergence);
972
+ simsimd_js_f64(f64s, f64s, 1536, &divergence);
760
973
 
761
974
  // Kullback-Leibler divergence between two vectors
762
- simsimd_kl_f16(f16s, f16s, 1536, &distance);
763
- simsimd_kl_f32(f32s, f32s, 1536, &distance);
764
- simsimd_kl_f64(f64s, f64s, 1536, &distance);
975
+ simsimd_kl_f16(f16s, f16s, 1536, &divergence);
976
+ simsimd_kl_f32(f32s, f32s, 1536, &divergence);
977
+ simsimd_kl_f64(f64s, f64s, 1536, &divergence);
765
978
  return 0;
766
979
  }
767
980
  ```