usearch 2.15.2 → 2.16.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.
- package/README.md +1 -1
- package/binding.gyp +1 -1
- package/c/CMakeLists.txt +10 -3
- package/cpp/README.md +1 -1
- package/cpp/bench.cpp +2 -2
- package/cpp/test.cpp +16 -0
- package/include/usearch/index.hpp +44 -17
- package/include/usearch/index_dense.hpp +51 -89
- package/include/usearch/index_plugins.hpp +468 -43
- package/javascript/lib.cpp +17 -5
- package/javascript/usearch.test.js +205 -34
- package/package.json +1 -1
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/simsimd/.git-blame-ignore-revs +2 -0
- package/simsimd/CODE_OF_CONDUCT.md +128 -0
- package/simsimd/CONTRIBUTING.md +84 -26
- package/simsimd/Cargo.lock +1 -1
- package/simsimd/Cargo.toml +4 -4
- package/simsimd/MANIFEST.in +3 -0
- package/simsimd/Package.swift +15 -3
- package/simsimd/README.md +534 -177
- package/simsimd/binding.gyp +6 -2
- package/simsimd/build.rs +13 -1
- package/simsimd/c/lib.c +266 -53
- package/simsimd/include/simsimd/binary.h +321 -112
- package/simsimd/include/simsimd/curved.h +803 -0
- package/simsimd/include/simsimd/dot.h +694 -521
- package/simsimd/include/simsimd/elementwise.h +1437 -0
- package/simsimd/include/simsimd/geospatial.h +9 -3
- package/simsimd/include/simsimd/mesh.h +69 -0
- package/simsimd/include/simsimd/probability.h +234 -206
- package/simsimd/include/simsimd/simsimd.h +1476 -617
- package/simsimd/include/simsimd/sparse.h +1428 -0
- package/simsimd/include/simsimd/spatial.h +1556 -742
- package/simsimd/include/simsimd/types.h +276 -132
- package/simsimd/javascript/lib.c +1 -2
- package/simsimd/javascript/simsimd.ts +4 -4
- package/simsimd/package.json +4 -4
- package/simsimd/rust/lib.rs +179 -1
- package/simsimd/scripts/bench.cxx +1070 -0
- package/simsimd/scripts/bench.ipynb +187 -0
- package/simsimd/{javascript → scripts}/bench.js +1 -1
- package/simsimd/{rust/benches/sqeuclidean.rs → scripts/bench_sqeuclidean.rs} +6 -6
- package/simsimd/scripts/bench_vectors.py +700 -0
- package/simsimd/scripts/bench_vectors_live.py +213 -0
- package/simsimd/scripts/test.c +155 -0
- package/simsimd/{javascript → scripts}/test.mjs +2 -2
- package/simsimd/scripts/test.py +1410 -0
- package/simsimd/swift/{source/SimSIMD.swift → SimSIMD.swift} +6 -2
- package/simsimd/swift/{tests/SimSIMDTests.swift → Test.swift} +1 -1
- /package/simsimd/{rust/benches/cosine.rs → scripts/bench_cosine.rs} +0 -0
- /package/simsimd/{rust/benches/native.rs → scripts/bench_native.rs} +0 -0
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* F, CD, VL, DQ, BW, VNNI, VPOPCNTDQ, IFMA, VBMI, VAES, GFNI, VBMI2, BITALG, VPCLMULQDQ, BF16
|
|
24
24
|
* > In other words, it extends Sunny Cove with BF16 support
|
|
25
25
|
* - Intel Golden Cove (Sapphire Rapids): extends Zen4 and Sunny Cove with FP16 support
|
|
26
|
+
* - AMD Zen5 (Turin): makes VP2INTERSECT cool again
|
|
26
27
|
*
|
|
27
28
|
* Intel Palm Cove was an irrelevant intermediate release extending Skylake with IFMA and VBMI.
|
|
28
29
|
* Intel Willow Cove was an irrelevant intermediate release extending Sunny Cove with VP2INTERSECT,
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
* 2. Intel Ice Lake (2019-2021): advanced integer algorithms.
|
|
36
37
|
* 3. AMD Genoa (2023+): brain-floating point support.
|
|
37
38
|
* 4. Intel Sapphire Rapids (2023+): advanced mixed-precision float processing.
|
|
39
|
+
* 5. AMD Turin (2024+): advanced sparse algorithms.
|
|
38
40
|
*
|
|
39
41
|
* To list all available macros for x86, take a recent compiler, like GCC 12 and run:
|
|
40
42
|
* gcc-12 -march=sapphirerapids -dM -E - < /dev/null | egrep "SSE|AVX" | sort
|
|
@@ -44,7 +46,7 @@
|
|
|
44
46
|
* @section Choosing Arm Target Generations
|
|
45
47
|
*
|
|
46
48
|
* Arm CPUs share design IP, but are produced by different vendors, potentially making the platform
|
|
47
|
-
* even more fragmented than x86. There are 2
|
|
49
|
+
* even more fragmented than x86. There are 2 important families of SIMD extensions - NEON and SVE.
|
|
48
50
|
*
|
|
49
51
|
* - Armv8-A: +fp, +simd
|
|
50
52
|
* - Armv8.1-A: armv8-a, +crc, +lse, +rdma
|
|
@@ -68,7 +70,7 @@
|
|
|
68
70
|
* Here are the most important recent families of CPU cores designed by Arm:
|
|
69
71
|
*
|
|
70
72
|
* - Neoverse N1: armv8.2-a, extended with Armv8.4 "dotprod" instructions.
|
|
71
|
-
* Used in AWS @b Graviton2 and
|
|
73
|
+
* Used in AWS @b Graviton2 and Ampere @b Altra.
|
|
72
74
|
* https://developer.arm.com/Processors/Neoverse%20N1
|
|
73
75
|
* - Neoverse V1: armv8.4-a, extended with Armv8.6 bfloat/int8 "matmul" instructions.
|
|
74
76
|
* Used in AWS @b Graviton3, which also enables `sve`, `svebf16`, and `svei8mm`.
|
|
@@ -87,8 +89,8 @@
|
|
|
87
89
|
#define SIMSIMD_H
|
|
88
90
|
|
|
89
91
|
#define SIMSIMD_VERSION_MAJOR 5
|
|
90
|
-
#define SIMSIMD_VERSION_MINOR
|
|
91
|
-
#define SIMSIMD_VERSION_PATCH
|
|
92
|
+
#define SIMSIMD_VERSION_MINOR 9
|
|
93
|
+
#define SIMSIMD_VERSION_PATCH 6
|
|
92
94
|
|
|
93
95
|
/**
|
|
94
96
|
* @brief Removes compile-time dispatching, and replaces it with runtime dispatching.
|
|
@@ -101,13 +103,16 @@
|
|
|
101
103
|
#endif
|
|
102
104
|
|
|
103
105
|
#include "binary.h" // Hamming, Jaccard
|
|
106
|
+
#include "curved.h" // Mahalanobis, Bilinear Forms
|
|
104
107
|
#include "dot.h" // Inner (dot) product, and its conjugate
|
|
108
|
+
#include "elementwise.h" // Weighted Sum, Fused-Multiply-Add
|
|
105
109
|
#include "geospatial.h" // Haversine and Vincenty
|
|
106
110
|
#include "probability.h" // Kullback-Leibler, Jensen–Shannon
|
|
111
|
+
#include "sparse.h" // Intersect
|
|
107
112
|
#include "spatial.h" // L2, Cosine
|
|
108
113
|
|
|
109
114
|
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
110
|
-
#if defined(
|
|
115
|
+
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
111
116
|
#include <sys/sysctl.h>
|
|
112
117
|
#endif
|
|
113
118
|
|
|
@@ -132,6 +137,8 @@ typedef enum {
|
|
|
132
137
|
simsimd_metric_cosine_k = 'c', ///< Cosine similarity alias
|
|
133
138
|
simsimd_metric_angular_k = 'c', ///< Cosine similarity alias
|
|
134
139
|
|
|
140
|
+
simsimd_metric_l2_k = '2', ///< Euclidean distance alias
|
|
141
|
+
simsimd_metric_euclidean_k = '2', ///< Euclidean distance alias
|
|
135
142
|
simsimd_metric_l2sq_k = 'e', ///< Squared Euclidean distance
|
|
136
143
|
simsimd_metric_sqeuclidean_k = 'e', ///< Squared Euclidean distance alias
|
|
137
144
|
|
|
@@ -142,6 +149,15 @@ typedef enum {
|
|
|
142
149
|
simsimd_metric_jaccard_k = 'j', ///< Jaccard coefficient
|
|
143
150
|
simsimd_metric_tanimoto_k = 'j', ///< Tanimoto coefficient is same as Jaccard
|
|
144
151
|
|
|
152
|
+
// Sets:
|
|
153
|
+
simsimd_metric_intersect_k = 'x', ///< Equivalent to unnormalized Jaccard
|
|
154
|
+
simsimd_metric_spdot_counts_k = 'y', ///< Sparse sets with integer weights
|
|
155
|
+
simsimd_metric_spdot_weights_k = 'z', ///< Sparse sets with brain floating-point weights
|
|
156
|
+
|
|
157
|
+
// Curved Spaces:
|
|
158
|
+
simsimd_metric_bilinear_k = 'b', ///< Bilinear form
|
|
159
|
+
simsimd_metric_mahalanobis_k = 'm', ///< Mahalanobis distance
|
|
160
|
+
|
|
145
161
|
// Probability:
|
|
146
162
|
simsimd_metric_kl_k = 'k', ///< Kullback-Leibler divergence
|
|
147
163
|
simsimd_metric_kullback_leibler_k = 'k', ///< Kullback-Leibler divergence alias
|
|
@@ -149,6 +165,10 @@ typedef enum {
|
|
|
149
165
|
simsimd_metric_js_k = 's', ///< Jensen-Shannon divergence
|
|
150
166
|
simsimd_metric_jensen_shannon_k = 's', ///< Jensen-Shannon divergence alias
|
|
151
167
|
|
|
168
|
+
// BLAS-like operations:
|
|
169
|
+
simsimd_metric_fma_k = 'f', ///< Fused Multiply-Add
|
|
170
|
+
simsimd_metric_wsum_k = 'w', ///< Weighted Sum
|
|
171
|
+
|
|
152
172
|
} simsimd_metric_kind_t;
|
|
153
173
|
|
|
154
174
|
/**
|
|
@@ -163,15 +183,19 @@ typedef enum {
|
|
|
163
183
|
simsimd_cap_ice_k = 1 << 12, ///< x86 AVX512 capability with advanced integer algos
|
|
164
184
|
simsimd_cap_genoa_k = 1 << 13, ///< x86 AVX512 capability with `bf16` support
|
|
165
185
|
simsimd_cap_sapphire_k = 1 << 14, ///< x86 AVX512 capability with `f16` support
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
186
|
+
simsimd_cap_turin_k = 1 << 15, ///< x86 AVX512 capability with conflict detection
|
|
187
|
+
simsimd_cap_sierra_k = 1 << 16, ///< x86 AVX2+VNNI capability with `i8` dot-products
|
|
188
|
+
|
|
189
|
+
simsimd_cap_neon_k = 1 << 20, ///< ARM NEON baseline capability
|
|
190
|
+
simsimd_cap_neon_f16_k = 1 << 21, ///< ARM NEON `f16` capability
|
|
191
|
+
simsimd_cap_neon_bf16_k = 1 << 22, ///< ARM NEON `bf16` capability
|
|
192
|
+
simsimd_cap_neon_i8_k = 1 << 23, ///< ARM NEON `i8` capability
|
|
193
|
+
simsimd_cap_sve_k = 1 << 24, ///< ARM SVE baseline capability
|
|
194
|
+
simsimd_cap_sve_f16_k = 1 << 25, ///< ARM SVE `f16` capability
|
|
195
|
+
simsimd_cap_sve_bf16_k = 1 << 26, ///< ARM SVE `bf16` capability
|
|
196
|
+
simsimd_cap_sve_i8_k = 1 << 27, ///< ARM SVE `i8` capability
|
|
197
|
+
simsimd_cap_sve2_k = 1 << 28, ///< ARM SVE2 capability
|
|
198
|
+
simsimd_cap_sve2p1_k = 1 << 29, ///< ARM SVE2p1 capability
|
|
175
199
|
|
|
176
200
|
} simsimd_capability_t;
|
|
177
201
|
|
|
@@ -183,10 +207,20 @@ typedef enum {
|
|
|
183
207
|
* interfaces.
|
|
184
208
|
*/
|
|
185
209
|
typedef enum {
|
|
186
|
-
simsimd_datatype_unknown_k = 0,
|
|
210
|
+
simsimd_datatype_unknown_k = 0, ///< Unknown data type
|
|
211
|
+
simsimd_datatype_b8_k = 1 << 1, ///< Single-bit values packed into 8-bit words
|
|
212
|
+
simsimd_datatype_b1x8_k = simsimd_datatype_b8_k, ///< Single-bit values packed into 8-bit words
|
|
213
|
+
simsimd_datatype_i4x2_k = 1 << 19, ///< 4-bit signed integers packed into 8-bit words
|
|
187
214
|
|
|
188
|
-
|
|
189
|
-
|
|
215
|
+
simsimd_datatype_i8_k = 1 << 2, ///< 8-bit signed integer
|
|
216
|
+
simsimd_datatype_i16_k = 1 << 3, ///< 16-bit signed integer
|
|
217
|
+
simsimd_datatype_i32_k = 1 << 4, ///< 32-bit signed integer
|
|
218
|
+
simsimd_datatype_i64_k = 1 << 5, ///< 64-bit signed integer
|
|
219
|
+
|
|
220
|
+
simsimd_datatype_u8_k = 1 << 6, ///< 8-bit unsigned integer
|
|
221
|
+
simsimd_datatype_u16_k = 1 << 7, ///< 16-bit unsigned integer
|
|
222
|
+
simsimd_datatype_u32_k = 1 << 8, ///< 32-bit unsigned integer
|
|
223
|
+
simsimd_datatype_u64_k = 1 << 9, ///< 64-bit unsigned integer
|
|
190
224
|
|
|
191
225
|
simsimd_datatype_f64_k = 1 << 10, ///< Double precision floating point
|
|
192
226
|
simsimd_datatype_f32_k = 1 << 11, ///< Single precision floating point
|
|
@@ -200,30 +234,108 @@ typedef enum {
|
|
|
200
234
|
} simsimd_datatype_t;
|
|
201
235
|
|
|
202
236
|
/**
|
|
203
|
-
* @brief Type-punned function pointer
|
|
237
|
+
* @brief Type-punned function pointer for dense vector representations and simplest similarity measures.
|
|
204
238
|
*
|
|
205
239
|
* @param[in] a Pointer to the first data array.
|
|
206
240
|
* @param[in] b Pointer to the second data array.
|
|
207
241
|
* @param[in] n Number of scalar words in the input arrays.
|
|
242
|
+
* When dealing with sub-byte types, the number of scalar words is the number of bytes.
|
|
243
|
+
* When dealing with complex types, the number of scalar words is the sum of real and imaginary parts.
|
|
208
244
|
* @param[out] d Output value as a double-precision float.
|
|
209
|
-
* In complex dot-products @b two
|
|
210
|
-
|
|
245
|
+
* In complex dot-products @b two scalars are exported for the real and imaginary parts.
|
|
246
|
+
*/
|
|
247
|
+
typedef void (*simsimd_metric_dense_punned_t)(void const *a, void const *b, simsimd_size_t n, simsimd_distance_t *d);
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @brief Type-punned function pointer for sparse vector representations and similarity measures.
|
|
251
|
+
*
|
|
252
|
+
* @param[in] a Pointer to the first data array, generally a sorted array of integers.
|
|
253
|
+
* @param[in] b Pointer to the second data array, generally a sorted array of integers.
|
|
254
|
+
* @param[in] a_length Number of scalar words in the first input array.
|
|
255
|
+
* @param[in] b_length Number of scalar words in the second input array.
|
|
256
|
+
* @param[out] d Output value as a double-precision float, generally without decimals.
|
|
257
|
+
*/
|
|
258
|
+
typedef void (*simsimd_metric_sparse_punned_t)(void const *a, void const *b, //
|
|
259
|
+
simsimd_size_t a_length, simsimd_size_t b_length, //
|
|
260
|
+
simsimd_distance_t *d);
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* @brief Type-punned function pointer for curved vector spaces and similarity measures.
|
|
264
|
+
*
|
|
265
|
+
* @param[in] a Pointer to the first data array.
|
|
266
|
+
* @param[in] b Pointer to the second data array.
|
|
267
|
+
* @param[in] c Pointer to the metric tensor array or some covariance matrix.
|
|
268
|
+
* @param[in] n Number of scalar words in the input arrays.
|
|
269
|
+
* @param[out] d Output value as a double-precision float.
|
|
270
|
+
*/
|
|
271
|
+
typedef void (*simsimd_metric_curved_punned_t)(void const *a, void const *b, void const *c, //
|
|
272
|
+
simsimd_size_t n, simsimd_distance_t *d);
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* @brief Type-punned function pointer for FMA operations on dense vector representations.
|
|
276
|
+
* Implements the `y = alpha * a * b + beta * c` operation.
|
|
277
|
+
*
|
|
278
|
+
* @param[in] a Pointer to the first data array.
|
|
279
|
+
* @param[in] b Pointer to the second data array.
|
|
280
|
+
* @param[in] c Pointer to the third data array.
|
|
281
|
+
* @param[in] n Number of scalar words in the input arrays.
|
|
282
|
+
* @param[in] alpha Scaling factor for the first two arrays.
|
|
283
|
+
* @param[in] beta Scaling factor for the third array.
|
|
284
|
+
* @param[out] y Output value in the same precision as the input arrays.
|
|
285
|
+
*/
|
|
286
|
+
typedef void (*simsimd_kernel_fma_punned_t)(void const *a, void const *b, void const *c, //
|
|
287
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
288
|
+
void *y);
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @brief Type-punned function pointer for Weighted Sum operations on dense vector representations.
|
|
292
|
+
* Implements the `y = alpha * a + beta * b` operation.
|
|
293
|
+
*
|
|
294
|
+
* @param[in] a Pointer to the first data array.
|
|
295
|
+
* @param[in] b Pointer to the second data array.
|
|
296
|
+
* @param[in] n Number of scalar words in the input arrays.
|
|
297
|
+
* @param[in] alpha Scaling factor for the first array.
|
|
298
|
+
* @param[in] beta Scaling factor for the second array.
|
|
299
|
+
* @param[out] y Output value in the same precision as the input arrays.
|
|
211
300
|
*/
|
|
212
|
-
typedef void (*
|
|
301
|
+
typedef void (*simsimd_kernel_wsum_punned_t)(void const *a, void const *b, //
|
|
302
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
303
|
+
void *y);
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @brief Type-punned function pointer for a SimSIMD public interface.
|
|
307
|
+
* Can be a `simsimd_metric_dense_punned_t`, `simsimd_metric_sparse_punned_t`,
|
|
308
|
+
* or `simsimd_metric_curved_punned_t`.
|
|
309
|
+
*/
|
|
310
|
+
typedef simsimd_metric_dense_punned_t simsimd_metric_punned_t;
|
|
213
311
|
|
|
214
312
|
#if SIMSIMD_DYNAMIC_DISPATCH
|
|
215
313
|
SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
314
|
+
SIMSIMD_DYNAMIC void simsimd_find_metric_punned( //
|
|
315
|
+
simsimd_metric_kind_t kind, //
|
|
316
|
+
simsimd_datatype_t datatype, //
|
|
317
|
+
simsimd_capability_t supported, //
|
|
318
|
+
simsimd_capability_t allowed, //
|
|
319
|
+
simsimd_metric_punned_t *metric_output, //
|
|
320
|
+
simsimd_capability_t *capability_output);
|
|
216
321
|
#else
|
|
217
322
|
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void);
|
|
323
|
+
SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
324
|
+
simsimd_metric_kind_t kind, //
|
|
325
|
+
simsimd_datatype_t datatype, //
|
|
326
|
+
simsimd_capability_t supported, //
|
|
327
|
+
simsimd_capability_t allowed, //
|
|
328
|
+
simsimd_metric_punned_t *metric_output, //
|
|
329
|
+
simsimd_capability_t *capability_output);
|
|
218
330
|
#endif
|
|
219
331
|
|
|
220
|
-
#if
|
|
332
|
+
#if _SIMSIMD_TARGET_X86
|
|
221
333
|
|
|
222
334
|
/**
|
|
223
335
|
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
224
336
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
225
337
|
*/
|
|
226
|
-
SIMSIMD_PUBLIC simsimd_capability_t
|
|
338
|
+
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
227
339
|
|
|
228
340
|
/// The states of 4 registers populated for a specific "cpuid" assembly call
|
|
229
341
|
union four_registers_t {
|
|
@@ -276,6 +388,9 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_x86(void) {
|
|
|
276
388
|
// Check for AVX512BF16 (Function ID 7, Sub-leaf 1, EAX register)
|
|
277
389
|
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L205
|
|
278
390
|
unsigned supports_avx512bf16 = (info7sub1.named.eax & 0x00000020) != 0;
|
|
391
|
+
// Clang doesn't show the VP2INTERSECT flag, but we can get it from QEMU
|
|
392
|
+
// https://stackoverflow.com/a/68289220/2766161
|
|
393
|
+
unsigned supports_avx512vp2intersect = (info7.named.edx & 0x00000100) != 0;
|
|
279
394
|
|
|
280
395
|
// Convert specific features into CPU generations
|
|
281
396
|
unsigned supports_haswell = supports_avx2 && supports_f16c && supports_fma;
|
|
@@ -284,6 +399,9 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_x86(void) {
|
|
|
284
399
|
supports_avx512vbmi2 && supports_avx512vpopcntdq;
|
|
285
400
|
unsigned supports_genoa = supports_avx512bf16;
|
|
286
401
|
unsigned supports_sapphire = supports_avx512fp16;
|
|
402
|
+
// We don't want to accidently enable AVX512VP2INTERSECT on Intel Tiger Lake CPUs
|
|
403
|
+
unsigned supports_turin = supports_avx512vp2intersect && supports_avx512bf16;
|
|
404
|
+
unsigned supports_sierra = 0;
|
|
287
405
|
|
|
288
406
|
return (simsimd_capability_t)( //
|
|
289
407
|
(simsimd_cap_haswell_k * supports_haswell) | //
|
|
@@ -291,16 +409,18 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_x86(void) {
|
|
|
291
409
|
(simsimd_cap_ice_k * supports_ice) | //
|
|
292
410
|
(simsimd_cap_genoa_k * supports_genoa) | //
|
|
293
411
|
(simsimd_cap_sapphire_k * supports_sapphire) | //
|
|
412
|
+
(simsimd_cap_turin_k * supports_turin) | //
|
|
413
|
+
(simsimd_cap_sierra_k * supports_sierra) | //
|
|
294
414
|
(simsimd_cap_serial_k));
|
|
295
415
|
}
|
|
296
416
|
|
|
297
|
-
#endif //
|
|
417
|
+
#endif // _SIMSIMD_TARGET_X86
|
|
298
418
|
|
|
299
|
-
#if
|
|
419
|
+
#if _SIMSIMD_TARGET_ARM
|
|
300
420
|
|
|
301
421
|
/* Compiling the next section one may get: selected processor does not support system register name 'id_aa64zfr0_el1'.
|
|
302
422
|
* Suppressing assembler errors is very complicated, so when dealing with older ARM CPUs it's simpler to compile this
|
|
303
|
-
* function
|
|
423
|
+
* function targeting newer ones.
|
|
304
424
|
*/
|
|
305
425
|
#pragma GCC push_options
|
|
306
426
|
#pragma GCC target("arch=armv8.5-a+sve")
|
|
@@ -310,19 +430,15 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_x86(void) {
|
|
|
310
430
|
* @brief Function to determine the SIMD capabilities of the current 64-bit Arm machine at @b runtime.
|
|
311
431
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
312
432
|
*/
|
|
313
|
-
SIMSIMD_PUBLIC simsimd_capability_t
|
|
314
|
-
#if defined(
|
|
433
|
+
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
434
|
+
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
315
435
|
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
316
436
|
uint32_t supports_neon = 0, supports_fp16 = 0, supports_bf16 = 0, supports_i8mm = 0;
|
|
317
437
|
size_t size = sizeof(supports_neon);
|
|
318
|
-
if (sysctlbyname("hw.optional.neon", &supports_neon, &size, NULL, 0) != 0)
|
|
319
|
-
|
|
320
|
-
if (sysctlbyname("hw.optional.arm.
|
|
321
|
-
|
|
322
|
-
if (sysctlbyname("hw.optional.arm.FEAT_BF16", &supports_bf16, &size, NULL, 0) != 0)
|
|
323
|
-
supports_bf16 = 0;
|
|
324
|
-
if (sysctlbyname("hw.optional.arm.FEAT_I8MM", &supports_i8mm, &size, NULL, 0) != 0)
|
|
325
|
-
supports_i8mm = 0;
|
|
438
|
+
if (sysctlbyname("hw.optional.neon", &supports_neon, &size, NULL, 0) != 0) supports_neon = 0;
|
|
439
|
+
if (sysctlbyname("hw.optional.arm.FEAT_FP16", &supports_fp16, &size, NULL, 0) != 0) supports_fp16 = 0;
|
|
440
|
+
if (sysctlbyname("hw.optional.arm.FEAT_BF16", &supports_bf16, &size, NULL, 0) != 0) supports_bf16 = 0;
|
|
441
|
+
if (sysctlbyname("hw.optional.arm.FEAT_I8MM", &supports_i8mm, &size, NULL, 0) != 0) supports_i8mm = 0;
|
|
326
442
|
|
|
327
443
|
return (simsimd_capability_t)( //
|
|
328
444
|
(simsimd_cap_neon_k * (supports_neon)) | //
|
|
@@ -331,23 +447,7 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_arm(void) {
|
|
|
331
447
|
(simsimd_cap_neon_i8_k * (supports_neon && supports_i8mm)) | //
|
|
332
448
|
(simsimd_cap_serial_k));
|
|
333
449
|
|
|
334
|
-
#elif defined(
|
|
335
|
-
// This is how the `arm-cpusysregs` library does it:
|
|
336
|
-
//
|
|
337
|
-
// int ID_AA64ISAR1_EL1_BF16() const { return (int)(_aa64isar1 >> 44) & 0x0F; }
|
|
338
|
-
// int ID_AA64ZFR0_EL1_BF16() const { return (int)(_aa64zfr0 >> 20) & 0x0F; }
|
|
339
|
-
// int ID_AA64PFR0_EL1_FP() const { return (int)(_aa64pfr0 >> 16) & 0x0F; }
|
|
340
|
-
// int ID_AA64ISAR0_EL1_DP() const { return (int)(_aa64isar0 >> 44) & 0x0F; }
|
|
341
|
-
// int ID_AA64PFR0_EL1_SVE() const { return (int)(_aa64pfr0 >> 32) & 0x0F; }
|
|
342
|
-
// int ID_AA64ZFR0_EL1_SVEver() const { return (int)(_aa64zfr0) & 0x0F; }
|
|
343
|
-
// bool FEAT_BF16() const { return ID_AA64ISAR1_EL1_BF16() >= 1 || ID_AA64ZFR0_EL1_BF16() >= 1; }
|
|
344
|
-
// bool FEAT_FP16() const { return ID_AA64PFR0_EL1_FP() >= 1 && ID_AA64PFR0_EL1_FP() < 15; }
|
|
345
|
-
// bool FEAT_DotProd() const { return ID_AA64ISAR0_EL1_DP() >= 1; }
|
|
346
|
-
// bool FEAT_SVE() const { return ID_AA64PFR0_EL1_SVE() >= 1; }
|
|
347
|
-
// bool FEAT_SVE2() const { return ID_AA64ZFR0_EL1_SVEver() >= 1; }
|
|
348
|
-
// bool FEAT_I8MM() const { return ID_AA64ZFR0_EL1_I8MM() >= 1; }
|
|
349
|
-
//
|
|
350
|
-
// https://github.com/lelegard/arm-cpusysregs/tree/4837c62e619a5e5f12bf41b16a1ee1e71d62c76d
|
|
450
|
+
#elif defined(_SIMSIMD_DEFINED_LINUX)
|
|
351
451
|
|
|
352
452
|
// Read CPUID registers directly
|
|
353
453
|
unsigned long id_aa64isar0_el1 = 0, id_aa64isar1_el1 = 0, id_aa64pfr0_el1 = 0, id_aa64zfr0_el1 = 0;
|
|
@@ -377,8 +477,7 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_arm(void) {
|
|
|
377
477
|
|
|
378
478
|
// Now let's unpack the status flags from ID_AA64ZFR0_EL1
|
|
379
479
|
// https://developer.arm.com/documentation/ddi0601/2024-03/AArch64-Registers/ID-AA64ZFR0-EL1--SVE-Feature-ID-Register-0?lang=en
|
|
380
|
-
if (supports_sve)
|
|
381
|
-
__asm__ __volatile__("mrs %0, ID_AA64ZFR0_EL1" : "=r"(id_aa64zfr0_el1));
|
|
480
|
+
if (supports_sve) __asm__ __volatile__("mrs %0, ID_AA64ZFR0_EL1" : "=r"(id_aa64zfr0_el1));
|
|
382
481
|
// I8MM, bits [47:44] of ID_AA64ZFR0_EL1
|
|
383
482
|
unsigned supports_sve_i8mm = ((id_aa64zfr0_el1 >> 44) & 0xF) >= 1;
|
|
384
483
|
// BF16, bits [23:20] of ID_AA64ZFR0_EL1
|
|
@@ -388,8 +487,8 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_arm(void) {
|
|
|
388
487
|
// - 0b0001: SVE2 is implemented
|
|
389
488
|
// - 0b0010: SVE2.1 is implemented
|
|
390
489
|
// This value must match the existing indicator obtained from ID_AA64PFR0_EL1:
|
|
391
|
-
|
|
392
|
-
|
|
490
|
+
unsigned supports_sve2 = ((id_aa64zfr0_el1) & 0xF) >= 1;
|
|
491
|
+
unsigned supports_sve2p1 = ((id_aa64zfr0_el1) & 0xF) >= 2;
|
|
393
492
|
unsigned supports_neon = 1; // NEON is always supported
|
|
394
493
|
|
|
395
494
|
return (simsimd_capability_t)( //
|
|
@@ -401,27 +500,30 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_arm(void) {
|
|
|
401
500
|
(simsimd_cap_sve_f16_k * (supports_sve && supports_fp16)) | //
|
|
402
501
|
(simsimd_cap_sve_bf16_k * (supports_sve && supports_sve_bf16)) | //
|
|
403
502
|
(simsimd_cap_sve_i8_k * (supports_sve && supports_sve_i8mm)) | //
|
|
503
|
+
(simsimd_cap_sve2_k * (supports_sve2)) | //
|
|
504
|
+
(simsimd_cap_sve2p1_k * (supports_sve2p1)) | //
|
|
404
505
|
(simsimd_cap_serial_k));
|
|
405
|
-
#else //
|
|
506
|
+
#else // if !_SIMSIMD_DEFINED_LINUX
|
|
406
507
|
return simsimd_cap_serial_k;
|
|
407
508
|
#endif
|
|
408
509
|
}
|
|
409
510
|
|
|
410
511
|
#pragma clang attribute pop
|
|
411
512
|
#pragma GCC pop_options
|
|
513
|
+
|
|
412
514
|
#endif
|
|
413
515
|
|
|
414
516
|
/**
|
|
415
517
|
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
416
518
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
417
519
|
*/
|
|
418
|
-
SIMSIMD_PUBLIC simsimd_capability_t
|
|
419
|
-
#if
|
|
420
|
-
return
|
|
421
|
-
#endif //
|
|
422
|
-
#if
|
|
423
|
-
return
|
|
424
|
-
#endif //
|
|
520
|
+
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_implementation(void) {
|
|
521
|
+
#if _SIMSIMD_TARGET_X86
|
|
522
|
+
return _simsimd_capabilities_x86();
|
|
523
|
+
#endif // _SIMSIMD_TARGET_X86
|
|
524
|
+
#if _SIMSIMD_TARGET_ARM
|
|
525
|
+
return _simsimd_capabilities_arm();
|
|
526
|
+
#endif // _SIMSIMD_TARGET_ARM
|
|
425
527
|
return simsimd_cap_serial_k;
|
|
426
528
|
}
|
|
427
529
|
|
|
@@ -430,452 +532,702 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_implementation(void) {
|
|
|
430
532
|
#pragma clang diagnostic push
|
|
431
533
|
#pragma clang diagnostic ignored "-Wcast-function-type"
|
|
432
534
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
* @param kind The kind of metric to be evaluated.
|
|
438
|
-
* @param datatype The data type for which the metric needs to be evaluated.
|
|
439
|
-
* @param supported The hardware capabilities supported by the CPU.
|
|
440
|
-
* @param allowed The hardware capabilities allowed for use.
|
|
441
|
-
* @param metric_output Output variable for the selected similarity function.
|
|
442
|
-
* @param capability_output Output variable for the utilized hardware capabilities.
|
|
443
|
-
*/
|
|
444
|
-
SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
445
|
-
simsimd_metric_kind_t kind, //
|
|
446
|
-
simsimd_datatype_t datatype, //
|
|
447
|
-
simsimd_capability_t supported, //
|
|
448
|
-
simsimd_capability_t allowed, //
|
|
449
|
-
simsimd_metric_punned_t* metric_output, //
|
|
450
|
-
simsimd_capability_t* capability_output) {
|
|
451
|
-
|
|
452
|
-
simsimd_metric_punned_t* m = metric_output;
|
|
453
|
-
simsimd_capability_t* c = capability_output;
|
|
454
|
-
simsimd_capability_t viable = (simsimd_capability_t)(supported & allowed);
|
|
455
|
-
*m = (simsimd_metric_punned_t)0;
|
|
456
|
-
*c = (simsimd_capability_t)0;
|
|
535
|
+
#ifdef __cplusplus //! option ‘-Wvolatile’ is valid for C++/ObjC++ but not for C
|
|
536
|
+
#pragma GCC diagnostic ignored "-Wvolatile"
|
|
537
|
+
#pragma clang diagnostic ignored "-Wvolatile"
|
|
538
|
+
#endif
|
|
457
539
|
|
|
540
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_f64(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
541
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
458
542
|
typedef simsimd_metric_punned_t m_t;
|
|
459
|
-
switch (datatype) {
|
|
460
|
-
|
|
461
|
-
case simsimd_datatype_unknown_k: break;
|
|
462
|
-
|
|
463
|
-
// Double-precision floating-point vectors
|
|
464
|
-
case simsimd_datatype_f64_k:
|
|
465
|
-
|
|
466
543
|
#if SIMSIMD_TARGET_SVE
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
544
|
+
if (v & simsimd_cap_sve_k) switch (k) {
|
|
545
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
546
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
547
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
548
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
549
|
+
default: break;
|
|
550
|
+
}
|
|
551
|
+
#endif
|
|
552
|
+
#if SIMSIMD_TARGET_NEON
|
|
553
|
+
if (v & simsimd_cap_neon_k) switch (k) {
|
|
554
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
555
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
556
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
557
|
+
default: break;
|
|
558
|
+
}
|
|
474
559
|
#endif
|
|
475
560
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
561
|
+
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
562
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
563
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
564
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
565
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
566
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
567
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
568
|
+
default: break;
|
|
569
|
+
}
|
|
570
|
+
#endif
|
|
571
|
+
#if SIMSIMD_TARGET_HASWELL
|
|
572
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
573
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
574
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
575
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
576
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
577
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
578
|
+
default: break;
|
|
579
|
+
}
|
|
580
|
+
#endif
|
|
581
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
582
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
583
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
584
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
585
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
586
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
587
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
588
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
589
|
+
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
590
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
591
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
592
|
+
default: break;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
498
595
|
|
|
596
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_f32(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
597
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
598
|
+
typedef simsimd_metric_punned_t m_t;
|
|
499
599
|
#if SIMSIMD_TARGET_SVE
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
600
|
+
if (v & simsimd_cap_sve_k) switch (k) {
|
|
601
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
602
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
603
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
604
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
605
|
+
default: break;
|
|
606
|
+
}
|
|
507
607
|
#endif
|
|
508
608
|
#if SIMSIMD_TARGET_NEON
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
609
|
+
if (v & simsimd_cap_neon_k) switch (k) {
|
|
610
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
611
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
612
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
613
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
614
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
615
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
616
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
617
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
618
|
+
default: break;
|
|
619
|
+
}
|
|
518
620
|
#endif
|
|
519
621
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
622
|
+
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
623
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
624
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
625
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
626
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
627
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
628
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
629
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
630
|
+
case simsimd_metric_mahalanobis_k:
|
|
631
|
+
*m = (m_t)&simsimd_mahalanobis_f32_skylake, *c = simsimd_cap_skylake_k;
|
|
632
|
+
return;
|
|
633
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
634
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
635
|
+
default: break;
|
|
636
|
+
}
|
|
529
637
|
#endif
|
|
530
638
|
#if SIMSIMD_TARGET_HASWELL
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
639
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
640
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
641
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
642
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
643
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
644
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
645
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
646
|
+
default: break;
|
|
647
|
+
}
|
|
648
|
+
#endif
|
|
649
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
650
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
651
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
652
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
653
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
654
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
655
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
656
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
657
|
+
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
658
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
659
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
660
|
+
default: break;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
554
663
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
664
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_f16(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
665
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
666
|
+
typedef simsimd_metric_punned_t m_t;
|
|
667
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
668
|
+
if (v & simsimd_cap_sve_k) switch (k) {
|
|
669
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
670
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
671
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
672
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
673
|
+
default: break;
|
|
674
|
+
}
|
|
675
|
+
#endif
|
|
676
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
677
|
+
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
678
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
679
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
680
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
681
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
682
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
683
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
684
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
685
|
+
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
686
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
687
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
688
|
+
default: break;
|
|
689
|
+
}
|
|
574
690
|
#endif
|
|
575
691
|
#if SIMSIMD_TARGET_SAPPHIRE
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
692
|
+
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
693
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
694
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
695
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
696
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
697
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
698
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
699
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
700
|
+
case simsimd_metric_mahalanobis_k:
|
|
701
|
+
*m = (m_t)&simsimd_mahalanobis_f16_sapphire, *c = simsimd_cap_sapphire_k;
|
|
702
|
+
return;
|
|
703
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
704
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
705
|
+
default: break;
|
|
706
|
+
}
|
|
585
707
|
#endif
|
|
586
708
|
#if SIMSIMD_TARGET_HASWELL
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
709
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
710
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
711
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
712
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
713
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
714
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
715
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
716
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
717
|
+
case simsimd_metric_mahalanobis_k:
|
|
718
|
+
*m = (m_t)&simsimd_mahalanobis_f16_haswell, *c = simsimd_cap_haswell_k;
|
|
719
|
+
return;
|
|
720
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
721
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
722
|
+
default: break;
|
|
723
|
+
}
|
|
724
|
+
#endif
|
|
725
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
726
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
727
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
728
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
729
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
730
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
731
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
732
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
733
|
+
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
734
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
735
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
736
|
+
default: break;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_bf16(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
741
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
742
|
+
typedef simsimd_metric_punned_t m_t;
|
|
743
|
+
#if SIMSIMD_TARGET_SVE_BF16
|
|
744
|
+
if (v & simsimd_cap_sve_bf16_k) switch (k) {
|
|
745
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
746
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
747
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
748
|
+
default: break;
|
|
749
|
+
}
|
|
620
750
|
#endif
|
|
621
|
-
#if
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
751
|
+
#if SIMSIMD_TARGET_NEON_BF16
|
|
752
|
+
if (v & simsimd_cap_neon_bf16_k) switch (k) {
|
|
753
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
754
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
755
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
756
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
757
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
758
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
759
|
+
default: break;
|
|
760
|
+
}
|
|
629
761
|
#endif
|
|
630
762
|
#if SIMSIMD_TARGET_GENOA
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
763
|
+
if (v & simsimd_cap_genoa_k) switch (k) {
|
|
764
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
765
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
766
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
767
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
768
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
769
|
+
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
770
|
+
default: break;
|
|
771
|
+
}
|
|
772
|
+
#endif
|
|
773
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
774
|
+
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
775
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_skylake, *c = simsimd_cap_skylake_k; return;
|
|
776
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_skylake, *c = simsimd_cap_skylake_k; return;
|
|
777
|
+
default: break;
|
|
778
|
+
}
|
|
779
|
+
#endif
|
|
780
|
+
#if SIMSIMD_TARGET_HASWELL
|
|
781
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
782
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
783
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
784
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
785
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
786
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
787
|
+
case simsimd_metric_mahalanobis_k:
|
|
788
|
+
*m = (m_t)&simsimd_mahalanobis_bf16_haswell, *c = simsimd_cap_haswell_k;
|
|
789
|
+
return;
|
|
790
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
791
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
792
|
+
default: break;
|
|
793
|
+
}
|
|
794
|
+
#endif
|
|
795
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
796
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
797
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
798
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
799
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
800
|
+
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
801
|
+
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
802
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
803
|
+
case simsimd_metric_mahalanobis_k:
|
|
804
|
+
*m = (m_t)&simsimd_mahalanobis_bf16_serial, *c = simsimd_cap_serial_k;
|
|
805
|
+
return;
|
|
806
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
807
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
808
|
+
default: break;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_i8(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
813
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
814
|
+
typedef simsimd_metric_punned_t m_t;
|
|
815
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
816
|
+
if (v & simsimd_cap_neon_i8_k) switch (k) {
|
|
817
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
818
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
819
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
820
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
821
|
+
default: break;
|
|
822
|
+
}
|
|
823
|
+
#endif
|
|
824
|
+
#if SIMSIMD_TARGET_NEON_F16 //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
825
|
+
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
826
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
827
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
828
|
+
default: break;
|
|
829
|
+
}
|
|
830
|
+
#endif
|
|
831
|
+
#if SIMSIMD_TARGET_SAPPHIRE //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
832
|
+
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
833
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
834
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
835
|
+
default: break;
|
|
836
|
+
}
|
|
661
837
|
#endif
|
|
662
838
|
#if SIMSIMD_TARGET_ICE
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
839
|
+
if (v & simsimd_cap_ice_k) switch (k) {
|
|
840
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
841
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
842
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
843
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
844
|
+
default: break;
|
|
845
|
+
}
|
|
670
846
|
#endif
|
|
671
847
|
#if SIMSIMD_TARGET_HASWELL
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
848
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
849
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
850
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
851
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
852
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
853
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
854
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
855
|
+
default: break;
|
|
856
|
+
}
|
|
857
|
+
#endif
|
|
858
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
859
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
860
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
861
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
862
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
863
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
864
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
865
|
+
default: break;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_u8(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
869
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
870
|
+
typedef simsimd_metric_punned_t m_t;
|
|
871
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
872
|
+
if (v & simsimd_cap_neon_i8_k) switch (k) {
|
|
873
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
874
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
875
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
876
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
877
|
+
default: break;
|
|
878
|
+
}
|
|
879
|
+
#endif
|
|
880
|
+
#if SIMSIMD_TARGET_NEON_F16 //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
881
|
+
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
882
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
883
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
884
|
+
default: break;
|
|
885
|
+
}
|
|
886
|
+
#endif
|
|
887
|
+
#if SIMSIMD_TARGET_SAPPHIRE //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
888
|
+
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
889
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
890
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
891
|
+
default: break;
|
|
892
|
+
}
|
|
679
893
|
#endif
|
|
894
|
+
#if SIMSIMD_TARGET_ICE
|
|
895
|
+
if (v & simsimd_cap_ice_k) switch (k) {
|
|
896
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
897
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
898
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
899
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
900
|
+
default: break;
|
|
901
|
+
}
|
|
902
|
+
#endif
|
|
903
|
+
#if SIMSIMD_TARGET_HASWELL
|
|
904
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
905
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
906
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
907
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
908
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
909
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
910
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
911
|
+
default: break;
|
|
912
|
+
}
|
|
913
|
+
#endif
|
|
914
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
915
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
916
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
917
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
918
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
919
|
+
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
920
|
+
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
921
|
+
default: break;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
680
924
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
685
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
686
|
-
default: break;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
break;
|
|
690
|
-
|
|
691
|
-
// Binary vectors
|
|
692
|
-
case simsimd_datatype_b8_k:
|
|
693
|
-
|
|
925
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_b8(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
926
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
927
|
+
typedef simsimd_metric_punned_t m_t;
|
|
694
928
|
#if SIMSIMD_TARGET_SVE
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}
|
|
929
|
+
if (v & simsimd_cap_sve_k) switch (k) {
|
|
930
|
+
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_sve, *c = simsimd_cap_sve_k; return;
|
|
931
|
+
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_sve, *c = simsimd_cap_sve_k; return;
|
|
932
|
+
default: break;
|
|
933
|
+
}
|
|
701
934
|
#endif
|
|
702
935
|
#if SIMSIMD_TARGET_NEON
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
936
|
+
if (v & simsimd_cap_neon_k) switch (k) {
|
|
937
|
+
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_neon, *c = simsimd_cap_neon_k; return;
|
|
938
|
+
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_neon, *c = simsimd_cap_neon_k; return;
|
|
939
|
+
default: break;
|
|
940
|
+
}
|
|
709
941
|
#endif
|
|
710
942
|
#if SIMSIMD_TARGET_ICE
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
}
|
|
943
|
+
if (v & simsimd_cap_ice_k) switch (k) {
|
|
944
|
+
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_ice, *c = simsimd_cap_ice_k; return;
|
|
945
|
+
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_ice, *c = simsimd_cap_ice_k; return;
|
|
946
|
+
default: break;
|
|
947
|
+
}
|
|
717
948
|
#endif
|
|
718
949
|
#if SIMSIMD_TARGET_HASWELL
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
default: break;
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
break;
|
|
950
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
951
|
+
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
952
|
+
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
953
|
+
default: break;
|
|
954
|
+
}
|
|
955
|
+
#endif
|
|
956
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
957
|
+
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_serial, *c = simsimd_cap_serial_k; return;
|
|
958
|
+
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_serial, *c = simsimd_cap_serial_k; return;
|
|
959
|
+
default: break;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
735
962
|
|
|
736
|
-
|
|
963
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_f64c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
964
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
965
|
+
typedef simsimd_metric_punned_t m_t;
|
|
966
|
+
#if SIMSIMD_TARGET_SVE
|
|
967
|
+
if (v & simsimd_cap_sve_k) switch (k) {
|
|
968
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64c_sve, *c = simsimd_cap_sve_k; return;
|
|
969
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f64c_sve, *c = simsimd_cap_sve_k; return;
|
|
970
|
+
default: break;
|
|
971
|
+
}
|
|
972
|
+
#endif
|
|
973
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
974
|
+
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
975
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
976
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f64c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
977
|
+
default: break;
|
|
978
|
+
}
|
|
979
|
+
#endif
|
|
980
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
981
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64c_serial, *c = simsimd_cap_serial_k; return;
|
|
982
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f64c_serial, *c = simsimd_cap_serial_k; return;
|
|
983
|
+
default: break;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
737
986
|
|
|
987
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_f32c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
988
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
989
|
+
typedef simsimd_metric_punned_t m_t;
|
|
738
990
|
#if SIMSIMD_TARGET_SVE
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
}
|
|
991
|
+
if (v & simsimd_cap_sve_k) switch (k) {
|
|
992
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_sve, *c = simsimd_cap_sve_k; return;
|
|
993
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_sve, *c = simsimd_cap_sve_k; return;
|
|
994
|
+
default: break;
|
|
995
|
+
}
|
|
745
996
|
#endif
|
|
746
997
|
#if SIMSIMD_TARGET_NEON
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
}
|
|
998
|
+
if (v & simsimd_cap_neon_k) switch (k) {
|
|
999
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_neon, *c = simsimd_cap_neon_k; return;
|
|
1000
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_neon, *c = simsimd_cap_neon_k; return;
|
|
1001
|
+
default: break;
|
|
1002
|
+
}
|
|
753
1003
|
#endif
|
|
754
1004
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
}
|
|
1005
|
+
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
1006
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1007
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1008
|
+
default: break;
|
|
1009
|
+
}
|
|
761
1010
|
#endif
|
|
762
1011
|
#if SIMSIMD_TARGET_HASWELL
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
default: break;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
break;
|
|
779
|
-
|
|
780
|
-
case simsimd_datatype_f64c_k:
|
|
1012
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
1013
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1014
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1015
|
+
default: break;
|
|
1016
|
+
}
|
|
1017
|
+
#endif
|
|
1018
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1019
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_serial, *c = simsimd_cap_serial_k; return;
|
|
1020
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_serial, *c = simsimd_cap_serial_k; return;
|
|
1021
|
+
default: break;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
781
1024
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1025
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_f16c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1026
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
1027
|
+
typedef simsimd_metric_punned_t m_t;
|
|
1028
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1029
|
+
if (v & simsimd_cap_sve_k) switch (k) {
|
|
1030
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
1031
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
1032
|
+
default: break;
|
|
1033
|
+
}
|
|
1034
|
+
#endif
|
|
1035
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
1036
|
+
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
1037
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
1038
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
1039
|
+
default: break;
|
|
1040
|
+
}
|
|
789
1041
|
#endif
|
|
790
|
-
#if
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
}
|
|
1042
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
1043
|
+
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
1044
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
1045
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
1046
|
+
default: break;
|
|
1047
|
+
}
|
|
797
1048
|
#endif
|
|
1049
|
+
#if SIMSIMD_TARGET_HASWELL
|
|
1050
|
+
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
1051
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1052
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1053
|
+
default: break;
|
|
1054
|
+
}
|
|
1055
|
+
#endif
|
|
1056
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1057
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1058
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1059
|
+
default: break;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
798
1062
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
break;
|
|
1063
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_bf16c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1064
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
1065
|
+
typedef simsimd_metric_punned_t m_t;
|
|
1066
|
+
#if SIMSIMD_TARGET_NEON_BF16
|
|
1067
|
+
if (v & simsimd_cap_neon_bf16_k) switch (k) {
|
|
1068
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16c_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
1069
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_bf16c_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
1070
|
+
default: break;
|
|
1071
|
+
}
|
|
1072
|
+
#endif
|
|
1073
|
+
#if SIMSIMD_TARGET_GENOA
|
|
1074
|
+
if (v & simsimd_cap_genoa_k) switch (k) {
|
|
1075
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16c_genoa, *c = simsimd_cap_genoa_k; return;
|
|
1076
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_bf16c_genoa, *c = simsimd_cap_genoa_k; return;
|
|
1077
|
+
default: break;
|
|
1078
|
+
}
|
|
1079
|
+
#endif
|
|
1080
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1081
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1082
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_bf16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1083
|
+
default: break;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
807
1086
|
|
|
808
|
-
|
|
1087
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_u16(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1088
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
1089
|
+
typedef simsimd_metric_punned_t m_t;
|
|
1090
|
+
#if SIMSIMD_TARGET_SVE2
|
|
1091
|
+
if (v & simsimd_cap_sve2_k) switch (k) {
|
|
1092
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1093
|
+
case simsimd_metric_spdot_counts_k: *m = (m_t)&simsimd_spdot_counts_u16_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1094
|
+
#if SIMSIMD_TARGET_SVE_BF16 //! We also need `bf16` support for weights
|
|
1095
|
+
case simsimd_metric_spdot_weights_k: *m = (m_t)&simsimd_spdot_weights_u16_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1096
|
+
#endif
|
|
1097
|
+
default: break;
|
|
1098
|
+
}
|
|
1099
|
+
#endif
|
|
1100
|
+
#if SIMSIMD_TARGET_NEON
|
|
1101
|
+
if (v & simsimd_cap_neon_k) switch (k) {
|
|
1102
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_neon, *c = simsimd_cap_neon_k; return;
|
|
1103
|
+
default: break;
|
|
1104
|
+
}
|
|
1105
|
+
#endif
|
|
1106
|
+
#if SIMSIMD_TARGET_TURIN
|
|
1107
|
+
if (v & simsimd_cap_turin_k) switch (k) {
|
|
1108
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_turin, *c = simsimd_cap_turin_k; return;
|
|
1109
|
+
case simsimd_metric_spdot_counts_k: *m = (m_t)&simsimd_spdot_counts_u16_turin, *c = simsimd_cap_turin_k; return;
|
|
1110
|
+
case simsimd_metric_spdot_weights_k:
|
|
1111
|
+
*m = (m_t)&simsimd_spdot_weights_u16_turin, *c = simsimd_cap_turin_k;
|
|
1112
|
+
return;
|
|
1113
|
+
default: break;
|
|
1114
|
+
}
|
|
1115
|
+
#endif
|
|
1116
|
+
#if SIMSIMD_TARGET_ICE
|
|
1117
|
+
if (v & simsimd_cap_ice_k) switch (k) {
|
|
1118
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_ice, *c = simsimd_cap_skylake_k; return;
|
|
1119
|
+
default: break;
|
|
1120
|
+
}
|
|
1121
|
+
#endif
|
|
1122
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1123
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_serial, *c = simsimd_cap_serial_k; return;
|
|
1124
|
+
default: break;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
809
1127
|
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
1128
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_u32(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1129
|
+
simsimd_metric_punned_t *m, simsimd_capability_t *c) {
|
|
1130
|
+
typedef simsimd_metric_punned_t m_t;
|
|
1131
|
+
#if SIMSIMD_TARGET_SVE2
|
|
1132
|
+
if (v & simsimd_cap_sve2_k) switch (k) {
|
|
1133
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1134
|
+
default: break;
|
|
1135
|
+
}
|
|
817
1136
|
#endif
|
|
818
1137
|
#if SIMSIMD_TARGET_NEON
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
default: break;
|
|
824
|
-
}
|
|
1138
|
+
if (v & simsimd_cap_neon_k) switch (k) {
|
|
1139
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_neon, *c = simsimd_cap_neon_k; return;
|
|
1140
|
+
default: break;
|
|
1141
|
+
}
|
|
825
1142
|
#endif
|
|
826
|
-
#if
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
default: break;
|
|
832
|
-
}
|
|
1143
|
+
#if SIMSIMD_TARGET_TURIN
|
|
1144
|
+
if (v & simsimd_cap_turin_k) switch (k) {
|
|
1145
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_turin, *c = simsimd_cap_skylake_k; return;
|
|
1146
|
+
default: break;
|
|
1147
|
+
}
|
|
833
1148
|
#endif
|
|
834
|
-
#if
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1149
|
+
#if SIMSIMD_TARGET_ICE
|
|
1150
|
+
if (v & simsimd_cap_ice_k) switch (k) {
|
|
1151
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_ice, *c = simsimd_cap_skylake_k; return;
|
|
1152
|
+
default: break;
|
|
1153
|
+
}
|
|
1154
|
+
#endif
|
|
1155
|
+
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1156
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_serial, *c = simsimd_cap_serial_k; return;
|
|
1157
|
+
default: break;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* @brief Determines the best suited metric implementation based on the given datatype,
|
|
1163
|
+
* supported and allowed by hardware capabilities.
|
|
1164
|
+
*
|
|
1165
|
+
* @param kind The kind of metric to be evaluated.
|
|
1166
|
+
* @param datatype The data type for which the metric needs to be evaluated.
|
|
1167
|
+
* @param supported The hardware capabilities supported by the CPU.
|
|
1168
|
+
* @param allowed The hardware capabilities allowed for use.
|
|
1169
|
+
* @param metric_output Output variable for the selected similarity function.
|
|
1170
|
+
* @param capability_output Output variable for the utilized hardware capabilities.
|
|
1171
|
+
*/
|
|
1172
|
+
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_implementation( //
|
|
1173
|
+
simsimd_metric_kind_t kind, //
|
|
1174
|
+
simsimd_datatype_t datatype, //
|
|
1175
|
+
simsimd_capability_t supported, //
|
|
1176
|
+
simsimd_capability_t allowed, //
|
|
1177
|
+
simsimd_metric_punned_t *metric_output, //
|
|
1178
|
+
simsimd_capability_t *capability_output) {
|
|
1179
|
+
|
|
1180
|
+
// Modern compilers abso-freaking-lutely love optimizing-out my logic!
|
|
1181
|
+
// Just marking the variables as `volatile` is not enough, so we have
|
|
1182
|
+
// to add inline assembly to further discourage them!
|
|
1183
|
+
#if defined(_MSC_VER)
|
|
1184
|
+
_ReadWriteBarrier();
|
|
1185
|
+
#else
|
|
1186
|
+
__asm__ __volatile__("" ::: "memory");
|
|
841
1187
|
#endif
|
|
842
1188
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_serial, *c = simsimd_cap_serial_k; return;
|
|
847
|
-
default: break;
|
|
848
|
-
}
|
|
1189
|
+
simsimd_metric_punned_t *m = metric_output;
|
|
1190
|
+
simsimd_capability_t *c = capability_output;
|
|
1191
|
+
simsimd_capability_t viable = (simsimd_capability_t)(supported & allowed);
|
|
849
1192
|
|
|
850
|
-
|
|
851
|
-
case simsimd_datatype_bf16c_k:
|
|
1193
|
+
switch (datatype) {
|
|
852
1194
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
break;
|
|
1195
|
+
case simsimd_datatype_f64_k: _simsimd_find_metric_punned_f64(viable, kind, m, c); return;
|
|
1196
|
+
case simsimd_datatype_f32_k: _simsimd_find_metric_punned_f32(viable, kind, m, c); return;
|
|
1197
|
+
case simsimd_datatype_f16_k: _simsimd_find_metric_punned_f16(viable, kind, m, c); return;
|
|
1198
|
+
case simsimd_datatype_bf16_k: _simsimd_find_metric_punned_bf16(viable, kind, m, c); return;
|
|
1199
|
+
case simsimd_datatype_i8_k: _simsimd_find_metric_punned_i8(viable, kind, m, c); return;
|
|
1200
|
+
case simsimd_datatype_u8_k: _simsimd_find_metric_punned_u8(viable, kind, m, c); return;
|
|
1201
|
+
case simsimd_datatype_b8_k: _simsimd_find_metric_punned_b8(viable, kind, m, c); return;
|
|
1202
|
+
case simsimd_datatype_f32c_k: _simsimd_find_metric_punned_f32c(viable, kind, m, c); return;
|
|
1203
|
+
case simsimd_datatype_f64c_k: _simsimd_find_metric_punned_f64c(viable, kind, m, c); return;
|
|
1204
|
+
case simsimd_datatype_f16c_k: _simsimd_find_metric_punned_f16c(viable, kind, m, c); return;
|
|
1205
|
+
case simsimd_datatype_bf16c_k: _simsimd_find_metric_punned_bf16c(viable, kind, m, c); return;
|
|
1206
|
+
case simsimd_datatype_u16_k: _simsimd_find_metric_punned_u16(viable, kind, m, c); return;
|
|
1207
|
+
case simsimd_datatype_u32_k: _simsimd_find_metric_punned_u32(viable, kind, m, c); return;
|
|
1208
|
+
|
|
1209
|
+
// These data-types are not supported yet
|
|
1210
|
+
case simsimd_datatype_i4x2_k: break;
|
|
1211
|
+
case simsimd_datatype_i16_k: break;
|
|
1212
|
+
case simsimd_datatype_i32_k: break;
|
|
1213
|
+
case simsimd_datatype_i64_k: break;
|
|
1214
|
+
case simsimd_datatype_u64_k: break;
|
|
1215
|
+
case simsimd_datatype_unknown_k: break;
|
|
1216
|
+
default: break;
|
|
878
1217
|
}
|
|
1218
|
+
|
|
1219
|
+
// Replace with zeros if no suitable implementation was found
|
|
1220
|
+
*m = (simsimd_metric_punned_t)0;
|
|
1221
|
+
*c = (simsimd_capability_t)0;
|
|
1222
|
+
|
|
1223
|
+
// Modern compilers abso-freaking-lutely love optimizing-out my logic!
|
|
1224
|
+
// Just marking the variables as `volatile` is not enough, so we have
|
|
1225
|
+
// to add inline assembly to further discourage them!
|
|
1226
|
+
#if defined(_MSC_VER)
|
|
1227
|
+
_ReadWriteBarrier();
|
|
1228
|
+
#else
|
|
1229
|
+
__asm__ __volatile__("" ::: "memory");
|
|
1230
|
+
#endif
|
|
879
1231
|
}
|
|
880
1232
|
|
|
881
1233
|
#pragma GCC diagnostic pop
|
|
@@ -910,10 +1262,14 @@ SIMSIMD_PUBLIC simsimd_metric_punned_t simsimd_metric_punned( //
|
|
|
910
1262
|
* - Check if the CPU supports AVX512F and AVX512BW extensions on Skylake x86 CPUs and newer
|
|
911
1263
|
* - Check if the CPU supports AVX512VNNI, AVX512IFMA, AVX512BITALG, AVX512VBMI2, and AVX512VPOPCNTDQ
|
|
912
1264
|
* extensions on Ice Lake x86 CPUs and newer
|
|
1265
|
+
* - Check if the CPU supports AVX512BF16 extensions on Genoa x86 CPUs and newer
|
|
913
1266
|
* - Check if the CPU supports AVX512FP16 extensions on Sapphire Rapids x86 CPUs and newer
|
|
1267
|
+
* - Check if the CPU supports AVX2VP2INTERSECT extensions on Turin x86 CPUs and newer
|
|
914
1268
|
*
|
|
915
1269
|
* @return 1 if the CPU supports the SIMD instruction set, 0 otherwise.
|
|
916
1270
|
*/
|
|
1271
|
+
SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
1272
|
+
SIMSIMD_DYNAMIC int simsimd_uses_dynamic_dispatch(void);
|
|
917
1273
|
SIMSIMD_DYNAMIC int simsimd_uses_neon(void);
|
|
918
1274
|
SIMSIMD_DYNAMIC int simsimd_uses_neon_f16(void);
|
|
919
1275
|
SIMSIMD_DYNAMIC int simsimd_uses_neon_bf16(void);
|
|
@@ -922,12 +1278,14 @@ SIMSIMD_DYNAMIC int simsimd_uses_sve(void);
|
|
|
922
1278
|
SIMSIMD_DYNAMIC int simsimd_uses_sve_f16(void);
|
|
923
1279
|
SIMSIMD_DYNAMIC int simsimd_uses_sve_bf16(void);
|
|
924
1280
|
SIMSIMD_DYNAMIC int simsimd_uses_sve_i8(void);
|
|
1281
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sve2(void);
|
|
925
1282
|
SIMSIMD_DYNAMIC int simsimd_uses_haswell(void);
|
|
926
1283
|
SIMSIMD_DYNAMIC int simsimd_uses_skylake(void);
|
|
927
1284
|
SIMSIMD_DYNAMIC int simsimd_uses_ice(void);
|
|
928
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void);
|
|
929
1285
|
SIMSIMD_DYNAMIC int simsimd_uses_genoa(void);
|
|
930
|
-
SIMSIMD_DYNAMIC
|
|
1286
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void);
|
|
1287
|
+
SIMSIMD_DYNAMIC int simsimd_uses_turin(void);
|
|
1288
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sierra(void);
|
|
931
1289
|
|
|
932
1290
|
/* Inner products
|
|
933
1291
|
* - Dot product: the sum of the products of the corresponding elements of two vectors.
|
|
@@ -943,30 +1301,30 @@ SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
|
943
1301
|
* @note The dot product is zero if and only if the two vectors are orthogonal.
|
|
944
1302
|
* @note Defined only for floating-point and integer data types.
|
|
945
1303
|
*/
|
|
946
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f16(simsimd_f16_t const*
|
|
947
|
-
simsimd_distance_t*
|
|
948
|
-
SIMSIMD_DYNAMIC void simsimd_dot_bf16(simsimd_bf16_t const*
|
|
949
|
-
simsimd_distance_t*
|
|
950
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f32(simsimd_f32_t const*
|
|
951
|
-
simsimd_distance_t*
|
|
952
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f64(simsimd_f64_t const*
|
|
953
|
-
simsimd_distance_t*
|
|
954
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f16c(simsimd_f16_t const*
|
|
955
|
-
simsimd_distance_t*
|
|
956
|
-
SIMSIMD_DYNAMIC void simsimd_dot_bf16c(simsimd_bf16_t const*
|
|
957
|
-
simsimd_distance_t*
|
|
958
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f32c(simsimd_f32_t const*
|
|
959
|
-
simsimd_distance_t*
|
|
960
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f64c(simsimd_f64_t const*
|
|
961
|
-
simsimd_distance_t*
|
|
962
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f16c(simsimd_f16_t const*
|
|
963
|
-
simsimd_distance_t*
|
|
964
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_bf16c(simsimd_bf16_t const*
|
|
965
|
-
simsimd_distance_t*
|
|
966
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f32c(simsimd_f32_t const*
|
|
967
|
-
simsimd_distance_t*
|
|
968
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f64c(simsimd_f64_t const*
|
|
969
|
-
simsimd_distance_t*
|
|
1304
|
+
SIMSIMD_DYNAMIC void simsimd_dot_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1305
|
+
simsimd_distance_t *d);
|
|
1306
|
+
SIMSIMD_DYNAMIC void simsimd_dot_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1307
|
+
simsimd_distance_t *d);
|
|
1308
|
+
SIMSIMD_DYNAMIC void simsimd_dot_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1309
|
+
simsimd_distance_t *d);
|
|
1310
|
+
SIMSIMD_DYNAMIC void simsimd_dot_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1311
|
+
simsimd_distance_t *d);
|
|
1312
|
+
SIMSIMD_DYNAMIC void simsimd_dot_f16c(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1313
|
+
simsimd_distance_t *d);
|
|
1314
|
+
SIMSIMD_DYNAMIC void simsimd_dot_bf16c(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1315
|
+
simsimd_distance_t *d);
|
|
1316
|
+
SIMSIMD_DYNAMIC void simsimd_dot_f32c(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1317
|
+
simsimd_distance_t *d);
|
|
1318
|
+
SIMSIMD_DYNAMIC void simsimd_dot_f64c(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1319
|
+
simsimd_distance_t *d);
|
|
1320
|
+
SIMSIMD_DYNAMIC void simsimd_vdot_f16c(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1321
|
+
simsimd_distance_t *d);
|
|
1322
|
+
SIMSIMD_DYNAMIC void simsimd_vdot_bf16c(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1323
|
+
simsimd_distance_t *d);
|
|
1324
|
+
SIMSIMD_DYNAMIC void simsimd_vdot_f32c(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1325
|
+
simsimd_distance_t *d);
|
|
1326
|
+
SIMSIMD_DYNAMIC void simsimd_vdot_f64c(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1327
|
+
simsimd_distance_t *d);
|
|
970
1328
|
|
|
971
1329
|
/* Spatial distances
|
|
972
1330
|
* - Cosine distance: the cosine of the angle between two vectors.
|
|
@@ -981,26 +1339,42 @@ SIMSIMD_DYNAMIC void simsimd_vdot_f64c(simsimd_f64_t const* a, simsimd_f64_t con
|
|
|
981
1339
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
982
1340
|
* @note Defined only for floating-point and integer data types.
|
|
983
1341
|
*/
|
|
984
|
-
SIMSIMD_DYNAMIC void simsimd_cos_i8(simsimd_i8_t const*
|
|
985
|
-
simsimd_distance_t*
|
|
986
|
-
SIMSIMD_DYNAMIC void
|
|
987
|
-
|
|
988
|
-
SIMSIMD_DYNAMIC void
|
|
989
|
-
|
|
990
|
-
SIMSIMD_DYNAMIC void
|
|
991
|
-
|
|
992
|
-
SIMSIMD_DYNAMIC void
|
|
993
|
-
simsimd_distance_t*
|
|
994
|
-
SIMSIMD_DYNAMIC void
|
|
995
|
-
simsimd_distance_t*
|
|
996
|
-
SIMSIMD_DYNAMIC void
|
|
997
|
-
|
|
998
|
-
SIMSIMD_DYNAMIC void
|
|
999
|
-
|
|
1000
|
-
SIMSIMD_DYNAMIC void
|
|
1001
|
-
simsimd_distance_t*
|
|
1002
|
-
SIMSIMD_DYNAMIC void
|
|
1003
|
-
|
|
1342
|
+
SIMSIMD_DYNAMIC void simsimd_cos_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1343
|
+
simsimd_distance_t *d);
|
|
1344
|
+
SIMSIMD_DYNAMIC void simsimd_cos_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1345
|
+
simsimd_distance_t *d);
|
|
1346
|
+
SIMSIMD_DYNAMIC void simsimd_cos_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1347
|
+
simsimd_distance_t *d);
|
|
1348
|
+
SIMSIMD_DYNAMIC void simsimd_cos_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1349
|
+
simsimd_distance_t *d);
|
|
1350
|
+
SIMSIMD_DYNAMIC void simsimd_cos_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1351
|
+
simsimd_distance_t *d);
|
|
1352
|
+
SIMSIMD_DYNAMIC void simsimd_cos_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1353
|
+
simsimd_distance_t *d);
|
|
1354
|
+
SIMSIMD_DYNAMIC void simsimd_l2sq_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1355
|
+
simsimd_distance_t *d);
|
|
1356
|
+
SIMSIMD_DYNAMIC void simsimd_l2sq_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1357
|
+
simsimd_distance_t *d);
|
|
1358
|
+
SIMSIMD_DYNAMIC void simsimd_l2sq_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1359
|
+
simsimd_distance_t *d);
|
|
1360
|
+
SIMSIMD_DYNAMIC void simsimd_l2sq_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1361
|
+
simsimd_distance_t *d);
|
|
1362
|
+
SIMSIMD_DYNAMIC void simsimd_l2sq_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1363
|
+
simsimd_distance_t *d);
|
|
1364
|
+
SIMSIMD_DYNAMIC void simsimd_l2sq_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1365
|
+
simsimd_distance_t *d);
|
|
1366
|
+
SIMSIMD_DYNAMIC void simsimd_l2_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1367
|
+
simsimd_distance_t *d);
|
|
1368
|
+
SIMSIMD_DYNAMIC void simsimd_l2_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1369
|
+
simsimd_distance_t *d);
|
|
1370
|
+
SIMSIMD_DYNAMIC void simsimd_l2_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1371
|
+
simsimd_distance_t *d);
|
|
1372
|
+
SIMSIMD_DYNAMIC void simsimd_l2_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1373
|
+
simsimd_distance_t *d);
|
|
1374
|
+
SIMSIMD_DYNAMIC void simsimd_l2_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1375
|
+
simsimd_distance_t *d);
|
|
1376
|
+
SIMSIMD_DYNAMIC void simsimd_l2_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1377
|
+
simsimd_distance_t *d);
|
|
1004
1378
|
|
|
1005
1379
|
/* Binary distances
|
|
1006
1380
|
* - Hamming distance: the number of positions at which the corresponding bits are different.
|
|
@@ -1015,18 +1389,18 @@ SIMSIMD_DYNAMIC void simsimd_l2sq_f64(simsimd_f64_t const* a, simsimd_f64_t cons
|
|
|
1015
1389
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1016
1390
|
* @note Defined only for binary data.
|
|
1017
1391
|
*/
|
|
1018
|
-
SIMSIMD_DYNAMIC void simsimd_hamming_b8(simsimd_b8_t const*
|
|
1019
|
-
simsimd_distance_t*
|
|
1020
|
-
SIMSIMD_DYNAMIC void simsimd_jaccard_b8(simsimd_b8_t const*
|
|
1021
|
-
simsimd_distance_t*
|
|
1392
|
+
SIMSIMD_DYNAMIC void simsimd_hamming_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
1393
|
+
simsimd_distance_t *d);
|
|
1394
|
+
SIMSIMD_DYNAMIC void simsimd_jaccard_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
1395
|
+
simsimd_distance_t *d);
|
|
1022
1396
|
|
|
1023
1397
|
/* Probability distributions
|
|
1024
1398
|
* - Jensen-Shannon divergence: a measure of similarity between two probability distributions.
|
|
1025
1399
|
* - Kullback-Leibler divergence: a measure of how one probability distribution diverges from a second.
|
|
1026
1400
|
*
|
|
1027
|
-
* @param a The first
|
|
1028
|
-
* @param b The second
|
|
1029
|
-
* @param n The number of elements in the
|
|
1401
|
+
* @param a The first discrete probability distribution.
|
|
1402
|
+
* @param b The second discrete probability distribution.
|
|
1403
|
+
* @param n The number of elements in the discrete distributions.
|
|
1030
1404
|
* @param d The output divergence value.
|
|
1031
1405
|
*
|
|
1032
1406
|
* @note The distributions are assumed to be normalized.
|
|
@@ -1034,22 +1408,22 @@ SIMSIMD_DYNAMIC void simsimd_jaccard_b8(simsimd_b8_t const* a, simsimd_b8_t cons
|
|
|
1034
1408
|
* @note The output divergence value is zero if and only if the two distributions are identical.
|
|
1035
1409
|
* @note Defined only for floating-point data types.
|
|
1036
1410
|
*/
|
|
1037
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f16(simsimd_f16_t const*
|
|
1038
|
-
simsimd_distance_t*
|
|
1039
|
-
SIMSIMD_DYNAMIC void simsimd_kl_bf16(simsimd_bf16_t const*
|
|
1040
|
-
simsimd_distance_t*
|
|
1041
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f32(simsimd_f32_t const*
|
|
1042
|
-
simsimd_distance_t*
|
|
1043
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f64(simsimd_f64_t const*
|
|
1044
|
-
simsimd_distance_t*
|
|
1045
|
-
SIMSIMD_DYNAMIC void simsimd_js_f16(simsimd_f16_t const*
|
|
1046
|
-
simsimd_distance_t*
|
|
1047
|
-
SIMSIMD_DYNAMIC void simsimd_js_bf16(simsimd_bf16_t const*
|
|
1048
|
-
simsimd_distance_t*
|
|
1049
|
-
SIMSIMD_DYNAMIC void simsimd_js_f32(simsimd_f32_t const*
|
|
1050
|
-
simsimd_distance_t*
|
|
1051
|
-
SIMSIMD_DYNAMIC void simsimd_js_f64(simsimd_f64_t const*
|
|
1052
|
-
simsimd_distance_t*
|
|
1411
|
+
SIMSIMD_DYNAMIC void simsimd_kl_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1412
|
+
simsimd_distance_t *d);
|
|
1413
|
+
SIMSIMD_DYNAMIC void simsimd_kl_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1414
|
+
simsimd_distance_t *d);
|
|
1415
|
+
SIMSIMD_DYNAMIC void simsimd_kl_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1416
|
+
simsimd_distance_t *d);
|
|
1417
|
+
SIMSIMD_DYNAMIC void simsimd_kl_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1418
|
+
simsimd_distance_t *d);
|
|
1419
|
+
SIMSIMD_DYNAMIC void simsimd_js_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1420
|
+
simsimd_distance_t *d);
|
|
1421
|
+
SIMSIMD_DYNAMIC void simsimd_js_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1422
|
+
simsimd_distance_t *d);
|
|
1423
|
+
SIMSIMD_DYNAMIC void simsimd_js_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1424
|
+
simsimd_distance_t *d);
|
|
1425
|
+
SIMSIMD_DYNAMIC void simsimd_js_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1426
|
+
simsimd_distance_t *d);
|
|
1053
1427
|
|
|
1054
1428
|
#else
|
|
1055
1429
|
|
|
@@ -1066,20 +1440,33 @@ SIMSIMD_DYNAMIC void simsimd_js_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1066
1440
|
*/
|
|
1067
1441
|
|
|
1068
1442
|
// clang-format off
|
|
1069
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon(void) { return
|
|
1070
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_f16(void) { return
|
|
1071
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_bf16(void) { return
|
|
1072
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_i8(void) { return
|
|
1073
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve(void) { return
|
|
1074
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_f16(void) { return
|
|
1075
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_bf16(void) { return
|
|
1076
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_i8(void) { return
|
|
1077
|
-
SIMSIMD_PUBLIC int
|
|
1078
|
-
SIMSIMD_PUBLIC int
|
|
1079
|
-
SIMSIMD_PUBLIC int
|
|
1080
|
-
SIMSIMD_PUBLIC int
|
|
1081
|
-
SIMSIMD_PUBLIC int simsimd_uses_genoa(void) { return
|
|
1082
|
-
SIMSIMD_PUBLIC
|
|
1443
|
+
SIMSIMD_PUBLIC int simsimd_uses_neon(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON; }
|
|
1444
|
+
SIMSIMD_PUBLIC int simsimd_uses_neon_f16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_F16 ; }
|
|
1445
|
+
SIMSIMD_PUBLIC int simsimd_uses_neon_bf16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_BF16; }
|
|
1446
|
+
SIMSIMD_PUBLIC int simsimd_uses_neon_i8(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_I8; }
|
|
1447
|
+
SIMSIMD_PUBLIC int simsimd_uses_sve(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE; }
|
|
1448
|
+
SIMSIMD_PUBLIC int simsimd_uses_sve_f16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_F16; }
|
|
1449
|
+
SIMSIMD_PUBLIC int simsimd_uses_sve_bf16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_BF16; }
|
|
1450
|
+
SIMSIMD_PUBLIC int simsimd_uses_sve_i8(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_I8; }
|
|
1451
|
+
SIMSIMD_PUBLIC int simsimd_uses_sve2(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE2; }
|
|
1452
|
+
SIMSIMD_PUBLIC int simsimd_uses_haswell(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_HASWELL; }
|
|
1453
|
+
SIMSIMD_PUBLIC int simsimd_uses_skylake(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SKYLAKE; }
|
|
1454
|
+
SIMSIMD_PUBLIC int simsimd_uses_ice(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_ICE; }
|
|
1455
|
+
SIMSIMD_PUBLIC int simsimd_uses_genoa(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_GENOA; }
|
|
1456
|
+
SIMSIMD_PUBLIC int simsimd_uses_sapphire(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SAPPHIRE; }
|
|
1457
|
+
SIMSIMD_PUBLIC int simsimd_uses_turin(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_TURIN; }
|
|
1458
|
+
SIMSIMD_PUBLIC int simsimd_uses_sierra(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SIERRA; }
|
|
1459
|
+
SIMSIMD_PUBLIC int simsimd_uses_dynamic_dispatch(void) { return 0; }
|
|
1460
|
+
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void) { return _simsimd_capabilities_implementation(); }
|
|
1461
|
+
SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
1462
|
+
simsimd_metric_kind_t kind, //
|
|
1463
|
+
simsimd_datatype_t datatype, //
|
|
1464
|
+
simsimd_capability_t supported, //
|
|
1465
|
+
simsimd_capability_t allowed, //
|
|
1466
|
+
simsimd_metric_punned_t* metric_output, //
|
|
1467
|
+
simsimd_capability_t* capability_output) {
|
|
1468
|
+
_simsimd_find_metric_punned_implementation(kind, datatype, supported, allowed, metric_output, capability_output);
|
|
1469
|
+
}
|
|
1083
1470
|
// clang-format on
|
|
1084
1471
|
|
|
1085
1472
|
/* Inner products
|
|
@@ -1096,11 +1483,35 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void) { return simsimd_
|
|
|
1096
1483
|
* @note The dot product is zero if and only if the two vectors are orthogonal.
|
|
1097
1484
|
* @note Defined only for floating-point and integer data types.
|
|
1098
1485
|
*/
|
|
1099
|
-
SIMSIMD_PUBLIC void
|
|
1100
|
-
|
|
1101
|
-
#if
|
|
1486
|
+
SIMSIMD_PUBLIC void simsimd_dot_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1487
|
+
simsimd_distance_t *d) {
|
|
1488
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
1489
|
+
simsimd_dot_i8_neon(a, b, n, d);
|
|
1490
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1491
|
+
simsimd_dot_i8_ice(a, b, n, d);
|
|
1492
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1493
|
+
simsimd_dot_i8_haswell(a, b, n, d);
|
|
1494
|
+
#else
|
|
1495
|
+
simsimd_dot_i8_serial(a, b, n, d);
|
|
1496
|
+
#endif
|
|
1497
|
+
}
|
|
1498
|
+
SIMSIMD_PUBLIC void simsimd_dot_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1499
|
+
simsimd_distance_t *d) {
|
|
1500
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
1501
|
+
simsimd_dot_u8_neon(a, b, n, d);
|
|
1502
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1503
|
+
simsimd_dot_u8_ice(a, b, n, d);
|
|
1504
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1505
|
+
simsimd_dot_u8_haswell(a, b, n, d);
|
|
1506
|
+
#else
|
|
1507
|
+
simsimd_dot_u8_serial(a, b, n, d);
|
|
1508
|
+
#endif
|
|
1509
|
+
}
|
|
1510
|
+
SIMSIMD_PUBLIC void simsimd_dot_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1511
|
+
simsimd_distance_t *d) {
|
|
1512
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1102
1513
|
simsimd_dot_f16_sve(a, b, n, d);
|
|
1103
|
-
#elif
|
|
1514
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1104
1515
|
simsimd_dot_f16_neon(a, b, n, d);
|
|
1105
1516
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1106
1517
|
simsimd_dot_f16_sapphire(a, b, n, d);
|
|
@@ -1110,20 +1521,20 @@ SIMSIMD_PUBLIC void simsimd_dot_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1110
1521
|
simsimd_dot_f16_serial(a, b, n, d);
|
|
1111
1522
|
#endif
|
|
1112
1523
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
simsimd_distance_t* d) {
|
|
1524
|
+
SIMSIMD_PUBLIC void simsimd_dot_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1525
|
+
simsimd_distance_t *d) {
|
|
1116
1526
|
#if SIMSIMD_TARGET_GENOA
|
|
1117
1527
|
simsimd_dot_bf16_genoa(a, b, n, d);
|
|
1118
1528
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1119
1529
|
simsimd_dot_bf16_haswell(a, b, n, d);
|
|
1530
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1531
|
+
simsimd_dot_bf16_neon(a, b, n, d);
|
|
1120
1532
|
#else
|
|
1121
1533
|
simsimd_dot_bf16_serial(a, b, n, d);
|
|
1122
1534
|
#endif
|
|
1123
1535
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
simsimd_distance_t* d) {
|
|
1536
|
+
SIMSIMD_PUBLIC void simsimd_dot_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1537
|
+
simsimd_distance_t *d) {
|
|
1127
1538
|
#if SIMSIMD_TARGET_SVE
|
|
1128
1539
|
simsimd_dot_f32_sve(a, b, n, d);
|
|
1129
1540
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1136,8 +1547,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1136
1547
|
simsimd_dot_f32_serial(a, b, n, d);
|
|
1137
1548
|
#endif
|
|
1138
1549
|
}
|
|
1139
|
-
SIMSIMD_PUBLIC void simsimd_dot_f64(simsimd_f64_t const*
|
|
1140
|
-
simsimd_distance_t*
|
|
1550
|
+
SIMSIMD_PUBLIC void simsimd_dot_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1551
|
+
simsimd_distance_t *d) {
|
|
1141
1552
|
#if SIMSIMD_TARGET_SVE
|
|
1142
1553
|
simsimd_dot_f64_sve(a, b, n, d);
|
|
1143
1554
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1146,11 +1557,11 @@ SIMSIMD_PUBLIC void simsimd_dot_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1146
1557
|
simsimd_dot_f64_serial(a, b, n, d);
|
|
1147
1558
|
#endif
|
|
1148
1559
|
}
|
|
1149
|
-
SIMSIMD_PUBLIC void simsimd_dot_f16c(simsimd_f16_t const*
|
|
1150
|
-
simsimd_distance_t*
|
|
1151
|
-
#if
|
|
1560
|
+
SIMSIMD_PUBLIC void simsimd_dot_f16c(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1561
|
+
simsimd_distance_t *d) {
|
|
1562
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1152
1563
|
simsimd_dot_f16c_sve(a, b, n, d);
|
|
1153
|
-
#elif
|
|
1564
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1154
1565
|
simsimd_dot_f16c_neon(a, b, n, d);
|
|
1155
1566
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1156
1567
|
simsimd_dot_f16c_sapphire(a, b, n, d);
|
|
@@ -1160,16 +1571,18 @@ SIMSIMD_PUBLIC void simsimd_dot_f16c(simsimd_f16_t const* a, simsimd_f16_t const
|
|
|
1160
1571
|
simsimd_dot_f16c_serial(a, b, n, d);
|
|
1161
1572
|
#endif
|
|
1162
1573
|
}
|
|
1163
|
-
SIMSIMD_PUBLIC void simsimd_dot_bf16c(simsimd_bf16_t const*
|
|
1164
|
-
simsimd_distance_t*
|
|
1574
|
+
SIMSIMD_PUBLIC void simsimd_dot_bf16c(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1575
|
+
simsimd_distance_t *d) {
|
|
1165
1576
|
#if SIMSIMD_TARGET_GENOA
|
|
1166
1577
|
simsimd_dot_bf16c_genoa(a, b, n, d);
|
|
1578
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1579
|
+
simsimd_dot_bf16c_neon(a, b, n, d);
|
|
1167
1580
|
#else
|
|
1168
1581
|
simsimd_dot_bf16c_serial(a, b, n, d);
|
|
1169
1582
|
#endif
|
|
1170
1583
|
}
|
|
1171
|
-
SIMSIMD_PUBLIC void simsimd_dot_f32c(simsimd_f32_t const*
|
|
1172
|
-
simsimd_distance_t*
|
|
1584
|
+
SIMSIMD_PUBLIC void simsimd_dot_f32c(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1585
|
+
simsimd_distance_t *d) {
|
|
1173
1586
|
#if SIMSIMD_TARGET_SVE
|
|
1174
1587
|
simsimd_dot_f32c_sve(a, b, n, d);
|
|
1175
1588
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1182,8 +1595,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f32c(simsimd_f32_t const* a, simsimd_f32_t const
|
|
|
1182
1595
|
simsimd_dot_f32c_serial(a, b, n, d);
|
|
1183
1596
|
#endif
|
|
1184
1597
|
}
|
|
1185
|
-
SIMSIMD_PUBLIC void simsimd_dot_f64c(simsimd_f64_t const*
|
|
1186
|
-
simsimd_distance_t*
|
|
1598
|
+
SIMSIMD_PUBLIC void simsimd_dot_f64c(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1599
|
+
simsimd_distance_t *d) {
|
|
1187
1600
|
#if SIMSIMD_TARGET_SVE
|
|
1188
1601
|
simsimd_dot_f64c_sve(a, b, n, d);
|
|
1189
1602
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1192,8 +1605,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f64c(simsimd_f64_t const* a, simsimd_f64_t const
|
|
|
1192
1605
|
simsimd_dot_f64c_serial(a, b, n, d);
|
|
1193
1606
|
#endif
|
|
1194
1607
|
}
|
|
1195
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16_t const*
|
|
1196
|
-
simsimd_distance_t*
|
|
1608
|
+
SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1609
|
+
simsimd_distance_t *d) {
|
|
1197
1610
|
#if SIMSIMD_TARGET_SVE
|
|
1198
1611
|
simsimd_vdot_f16c_sve(a, b, n, d);
|
|
1199
1612
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1206,12 +1619,18 @@ SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16_t const* a, simsimd_f16_t cons
|
|
|
1206
1619
|
simsimd_vdot_f16c_serial(a, b, n, d);
|
|
1207
1620
|
#endif
|
|
1208
1621
|
}
|
|
1209
|
-
SIMSIMD_PUBLIC void simsimd_vdot_bf16c(simsimd_bf16_t const*
|
|
1210
|
-
simsimd_distance_t*
|
|
1622
|
+
SIMSIMD_PUBLIC void simsimd_vdot_bf16c(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1623
|
+
simsimd_distance_t *d) {
|
|
1624
|
+
#if SIMSIMD_TARGET_GENOA
|
|
1625
|
+
simsimd_vdot_bf16c_genoa(a, b, n, d);
|
|
1626
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1627
|
+
simsimd_dot_bf16c_neon(a, b, n, d);
|
|
1628
|
+
#else
|
|
1211
1629
|
simsimd_vdot_bf16c_serial(a, b, n, d);
|
|
1630
|
+
#endif
|
|
1212
1631
|
}
|
|
1213
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f32c(simsimd_f32_t const*
|
|
1214
|
-
simsimd_distance_t*
|
|
1632
|
+
SIMSIMD_PUBLIC void simsimd_vdot_f32c(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1633
|
+
simsimd_distance_t *d) {
|
|
1215
1634
|
#if SIMSIMD_TARGET_SVE
|
|
1216
1635
|
simsimd_vdot_f32c_sve(a, b, n, d);
|
|
1217
1636
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1224,8 +1643,8 @@ SIMSIMD_PUBLIC void simsimd_vdot_f32c(simsimd_f32_t const* a, simsimd_f32_t cons
|
|
|
1224
1643
|
simsimd_vdot_f32c_serial(a, b, n, d);
|
|
1225
1644
|
#endif
|
|
1226
1645
|
}
|
|
1227
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f64c(simsimd_f64_t const*
|
|
1228
|
-
simsimd_distance_t*
|
|
1646
|
+
SIMSIMD_PUBLIC void simsimd_vdot_f64c(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1647
|
+
simsimd_distance_t *d) {
|
|
1229
1648
|
#if SIMSIMD_TARGET_SVE
|
|
1230
1649
|
simsimd_vdot_f64c_sve(a, b, n, d);
|
|
1231
1650
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1248,8 +1667,8 @@ SIMSIMD_PUBLIC void simsimd_vdot_f64c(simsimd_f64_t const* a, simsimd_f64_t cons
|
|
|
1248
1667
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1249
1668
|
* @note Defined only for floating-point and integer data types.
|
|
1250
1669
|
*/
|
|
1251
|
-
SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const*
|
|
1252
|
-
simsimd_distance_t*
|
|
1670
|
+
SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1671
|
+
simsimd_distance_t *d) {
|
|
1253
1672
|
#if SIMSIMD_TARGET_NEON
|
|
1254
1673
|
simsimd_cos_i8_neon(a, b, n, d);
|
|
1255
1674
|
#elif SIMSIMD_TARGET_ICE
|
|
@@ -1260,23 +1679,23 @@ SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const* a, simsimd_i8_t const* b,
|
|
|
1260
1679
|
simsimd_cos_i8_serial(a, b, n, d);
|
|
1261
1680
|
#endif
|
|
1262
1681
|
}
|
|
1263
|
-
SIMSIMD_PUBLIC void
|
|
1264
|
-
|
|
1682
|
+
SIMSIMD_PUBLIC void simsimd_cos_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1683
|
+
simsimd_distance_t *d) {
|
|
1265
1684
|
#if SIMSIMD_TARGET_NEON
|
|
1266
|
-
|
|
1685
|
+
simsimd_cos_u8_neon(a, b, n, d);
|
|
1267
1686
|
#elif SIMSIMD_TARGET_ICE
|
|
1268
|
-
|
|
1687
|
+
simsimd_cos_u8_ice(a, b, n, d);
|
|
1269
1688
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1270
|
-
|
|
1689
|
+
simsimd_cos_u8_haswell(a, b, n, d);
|
|
1271
1690
|
#else
|
|
1272
|
-
|
|
1691
|
+
simsimd_cos_u8_serial(a, b, n, d);
|
|
1273
1692
|
#endif
|
|
1274
1693
|
}
|
|
1275
|
-
SIMSIMD_PUBLIC void simsimd_cos_f16(simsimd_f16_t const*
|
|
1276
|
-
simsimd_distance_t*
|
|
1277
|
-
#if
|
|
1694
|
+
SIMSIMD_PUBLIC void simsimd_cos_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1695
|
+
simsimd_distance_t *d) {
|
|
1696
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1278
1697
|
simsimd_cos_f16_sve(a, b, n, d);
|
|
1279
|
-
#elif
|
|
1698
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1280
1699
|
simsimd_cos_f16_neon(a, b, n, d);
|
|
1281
1700
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1282
1701
|
simsimd_cos_f16_sapphire(a, b, n, d);
|
|
@@ -1286,18 +1705,22 @@ SIMSIMD_PUBLIC void simsimd_cos_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1286
1705
|
simsimd_cos_f16_serial(a, b, n, d);
|
|
1287
1706
|
#endif
|
|
1288
1707
|
}
|
|
1289
|
-
SIMSIMD_PUBLIC void simsimd_cos_bf16(simsimd_bf16_t const*
|
|
1290
|
-
simsimd_distance_t*
|
|
1708
|
+
SIMSIMD_PUBLIC void simsimd_cos_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1709
|
+
simsimd_distance_t *d) {
|
|
1291
1710
|
#if SIMSIMD_TARGET_GENOA
|
|
1292
1711
|
simsimd_cos_bf16_genoa(a, b, n, d);
|
|
1293
1712
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1294
1713
|
simsimd_cos_bf16_haswell(a, b, n, d);
|
|
1714
|
+
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1715
|
+
simsimd_cos_bf16_sve(a, b, n, d);
|
|
1716
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1717
|
+
simsimd_cos_bf16_neon(a, b, n, d);
|
|
1295
1718
|
#else
|
|
1296
1719
|
simsimd_cos_bf16_serial(a, b, n, d);
|
|
1297
1720
|
#endif
|
|
1298
1721
|
}
|
|
1299
|
-
SIMSIMD_PUBLIC void simsimd_cos_f32(simsimd_f32_t const*
|
|
1300
|
-
simsimd_distance_t*
|
|
1722
|
+
SIMSIMD_PUBLIC void simsimd_cos_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1723
|
+
simsimd_distance_t *d) {
|
|
1301
1724
|
#if SIMSIMD_TARGET_SVE
|
|
1302
1725
|
simsimd_cos_f32_sve(a, b, n, d);
|
|
1303
1726
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1310,21 +1733,47 @@ SIMSIMD_PUBLIC void simsimd_cos_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1310
1733
|
simsimd_cos_f32_serial(a, b, n, d);
|
|
1311
1734
|
#endif
|
|
1312
1735
|
}
|
|
1313
|
-
SIMSIMD_PUBLIC void simsimd_cos_f64(simsimd_f64_t const*
|
|
1314
|
-
simsimd_distance_t*
|
|
1736
|
+
SIMSIMD_PUBLIC void simsimd_cos_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1737
|
+
simsimd_distance_t *d) {
|
|
1315
1738
|
#if SIMSIMD_TARGET_SVE
|
|
1316
1739
|
simsimd_cos_f64_sve(a, b, n, d);
|
|
1740
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1741
|
+
simsimd_cos_f64_neon(a, b, n, d);
|
|
1317
1742
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1318
1743
|
simsimd_cos_f64_skylake(a, b, n, d);
|
|
1319
1744
|
#else
|
|
1320
1745
|
simsimd_cos_f64_serial(a, b, n, d);
|
|
1321
1746
|
#endif
|
|
1322
1747
|
}
|
|
1323
|
-
SIMSIMD_PUBLIC void
|
|
1324
|
-
|
|
1325
|
-
#if
|
|
1748
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1749
|
+
simsimd_distance_t *d) {
|
|
1750
|
+
#if SIMSIMD_TARGET_NEON
|
|
1751
|
+
simsimd_l2sq_i8_neon(a, b, n, d);
|
|
1752
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1753
|
+
simsimd_l2sq_i8_ice(a, b, n, d);
|
|
1754
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1755
|
+
simsimd_l2sq_i8_haswell(a, b, n, d);
|
|
1756
|
+
#else
|
|
1757
|
+
simsimd_l2sq_i8_serial(a, b, n, d);
|
|
1758
|
+
#endif
|
|
1759
|
+
}
|
|
1760
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1761
|
+
simsimd_distance_t *d) {
|
|
1762
|
+
#if SIMSIMD_TARGET_NEON
|
|
1763
|
+
simsimd_l2sq_u8_neon(a, b, n, d);
|
|
1764
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1765
|
+
simsimd_l2sq_u8_ice(a, b, n, d);
|
|
1766
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1767
|
+
simsimd_l2sq_u8_haswell(a, b, n, d);
|
|
1768
|
+
#else
|
|
1769
|
+
simsimd_l2sq_u8_serial(a, b, n, d);
|
|
1770
|
+
#endif
|
|
1771
|
+
}
|
|
1772
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1773
|
+
simsimd_distance_t *d) {
|
|
1774
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1326
1775
|
simsimd_l2sq_f16_sve(a, b, n, d);
|
|
1327
|
-
#elif
|
|
1776
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1328
1777
|
simsimd_l2sq_f16_neon(a, b, n, d);
|
|
1329
1778
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1330
1779
|
simsimd_l2sq_f16_sapphire(a, b, n, d);
|
|
@@ -1334,18 +1783,22 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f16(simsimd_f16_t const* a, simsimd_f16_t const
|
|
|
1334
1783
|
simsimd_l2sq_f16_serial(a, b, n, d);
|
|
1335
1784
|
#endif
|
|
1336
1785
|
}
|
|
1337
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_bf16(simsimd_bf16_t const*
|
|
1338
|
-
simsimd_distance_t*
|
|
1786
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1787
|
+
simsimd_distance_t *d) {
|
|
1339
1788
|
#if SIMSIMD_TARGET_GENOA
|
|
1340
1789
|
simsimd_l2sq_bf16_genoa(a, b, n, d);
|
|
1341
1790
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1342
1791
|
simsimd_l2sq_bf16_haswell(a, b, n, d);
|
|
1792
|
+
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1793
|
+
simsimd_l2sq_bf16_sve(a, b, n, d);
|
|
1794
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1795
|
+
simsimd_l2sq_bf16_neon(a, b, n, d);
|
|
1343
1796
|
#else
|
|
1344
1797
|
simsimd_l2sq_bf16_serial(a, b, n, d);
|
|
1345
1798
|
#endif
|
|
1346
1799
|
}
|
|
1347
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_f32(simsimd_f32_t const*
|
|
1348
|
-
simsimd_distance_t*
|
|
1800
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1801
|
+
simsimd_distance_t *d) {
|
|
1349
1802
|
#if SIMSIMD_TARGET_SVE
|
|
1350
1803
|
simsimd_l2sq_f32_sve(a, b, n, d);
|
|
1351
1804
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1358,16 +1811,96 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f32(simsimd_f32_t const* a, simsimd_f32_t const
|
|
|
1358
1811
|
simsimd_l2sq_f32_serial(a, b, n, d);
|
|
1359
1812
|
#endif
|
|
1360
1813
|
}
|
|
1361
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const*
|
|
1362
|
-
simsimd_distance_t*
|
|
1814
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1815
|
+
simsimd_distance_t *d) {
|
|
1363
1816
|
#if SIMSIMD_TARGET_SVE
|
|
1364
1817
|
simsimd_l2sq_f64_sve(a, b, n, d);
|
|
1818
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1819
|
+
simsimd_l2sq_f64_neon(a, b, n, d);
|
|
1365
1820
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1366
1821
|
simsimd_l2sq_f64_skylake(a, b, n, d);
|
|
1367
1822
|
#else
|
|
1368
1823
|
simsimd_l2sq_f64_serial(a, b, n, d);
|
|
1369
1824
|
#endif
|
|
1370
1825
|
}
|
|
1826
|
+
SIMSIMD_PUBLIC void simsimd_l2_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1827
|
+
simsimd_distance_t *d) {
|
|
1828
|
+
#if SIMSIMD_TARGET_NEON
|
|
1829
|
+
simsimd_l2_i8_neon(a, b, n, d);
|
|
1830
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1831
|
+
simsimd_l2_i8_ice(a, b, n, d);
|
|
1832
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1833
|
+
simsimd_l2_i8_haswell(a, b, n, d);
|
|
1834
|
+
#else
|
|
1835
|
+
simsimd_l2_i8_serial(a, b, n, d);
|
|
1836
|
+
#endif
|
|
1837
|
+
}
|
|
1838
|
+
SIMSIMD_PUBLIC void simsimd_l2_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1839
|
+
simsimd_distance_t *d) {
|
|
1840
|
+
#if SIMSIMD_TARGET_NEON
|
|
1841
|
+
simsimd_l2_u8_neon(a, b, n, d);
|
|
1842
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1843
|
+
simsimd_l2_u8_ice(a, b, n, d);
|
|
1844
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1845
|
+
simsimd_l2_u8_haswell(a, b, n, d);
|
|
1846
|
+
#else
|
|
1847
|
+
simsimd_l2_u8_serial(a, b, n, d);
|
|
1848
|
+
#endif
|
|
1849
|
+
}
|
|
1850
|
+
SIMSIMD_PUBLIC void simsimd_l2_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1851
|
+
simsimd_distance_t *d) {
|
|
1852
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1853
|
+
simsimd_l2_f16_sve(a, b, n, d);
|
|
1854
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1855
|
+
simsimd_l2_f16_neon(a, b, n, d);
|
|
1856
|
+
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1857
|
+
simsimd_l2_f16_sapphire(a, b, n, d);
|
|
1858
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1859
|
+
simsimd_l2_f16_haswell(a, b, n, d);
|
|
1860
|
+
#else
|
|
1861
|
+
simsimd_l2_f16_serial(a, b, n, d);
|
|
1862
|
+
#endif
|
|
1863
|
+
}
|
|
1864
|
+
SIMSIMD_PUBLIC void simsimd_l2_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1865
|
+
simsimd_distance_t *d) {
|
|
1866
|
+
#if SIMSIMD_TARGET_GENOA
|
|
1867
|
+
simsimd_l2_bf16_genoa(a, b, n, d);
|
|
1868
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1869
|
+
simsimd_l2_bf16_haswell(a, b, n, d);
|
|
1870
|
+
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1871
|
+
simsimd_l2_bf16_sve(a, b, n, d);
|
|
1872
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1873
|
+
simsimd_l2_bf16_neon(a, b, n, d);
|
|
1874
|
+
#else
|
|
1875
|
+
simsimd_l2_bf16_serial(a, b, n, d);
|
|
1876
|
+
#endif
|
|
1877
|
+
}
|
|
1878
|
+
SIMSIMD_PUBLIC void simsimd_l2_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1879
|
+
simsimd_distance_t *d) {
|
|
1880
|
+
#if SIMSIMD_TARGET_SVE
|
|
1881
|
+
simsimd_l2_f32_sve(a, b, n, d);
|
|
1882
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1883
|
+
simsimd_l2_f32_neon(a, b, n, d);
|
|
1884
|
+
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1885
|
+
simsimd_l2_f32_skylake(a, b, n, d);
|
|
1886
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1887
|
+
simsimd_l2_f32_haswell(a, b, n, d);
|
|
1888
|
+
#else
|
|
1889
|
+
simsimd_l2_f32_serial(a, b, n, d);
|
|
1890
|
+
#endif
|
|
1891
|
+
}
|
|
1892
|
+
SIMSIMD_PUBLIC void simsimd_l2_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1893
|
+
simsimd_distance_t *d) {
|
|
1894
|
+
#if SIMSIMD_TARGET_SVE
|
|
1895
|
+
simsimd_l2_f64_sve(a, b, n, d);
|
|
1896
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1897
|
+
simsimd_l2_f64_neon(a, b, n, d);
|
|
1898
|
+
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1899
|
+
simsimd_l2_f64_skylake(a, b, n, d);
|
|
1900
|
+
#else
|
|
1901
|
+
simsimd_l2_f64_serial(a, b, n, d);
|
|
1902
|
+
#endif
|
|
1903
|
+
}
|
|
1371
1904
|
|
|
1372
1905
|
/* Binary distances
|
|
1373
1906
|
* - Hamming distance: the number of positions at which the corresponding bits are different.
|
|
@@ -1382,8 +1915,8 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const* a, simsimd_f64_t const
|
|
|
1382
1915
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1383
1916
|
* @note Defined only for binary data.
|
|
1384
1917
|
*/
|
|
1385
|
-
SIMSIMD_PUBLIC void simsimd_hamming_b8(simsimd_b8_t const*
|
|
1386
|
-
simsimd_distance_t*
|
|
1918
|
+
SIMSIMD_PUBLIC void simsimd_hamming_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
1919
|
+
simsimd_distance_t *d) {
|
|
1387
1920
|
#if SIMSIMD_TARGET_SVE
|
|
1388
1921
|
simsimd_hamming_b8_sve(a, b, n, d);
|
|
1389
1922
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1396,8 +1929,8 @@ SIMSIMD_PUBLIC void simsimd_hamming_b8(simsimd_b8_t const* a, simsimd_b8_t const
|
|
|
1396
1929
|
simsimd_hamming_b8_serial(a, b, n, d);
|
|
1397
1930
|
#endif
|
|
1398
1931
|
}
|
|
1399
|
-
SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const*
|
|
1400
|
-
simsimd_distance_t*
|
|
1932
|
+
SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
1933
|
+
simsimd_distance_t *d) {
|
|
1401
1934
|
#if SIMSIMD_TARGET_SVE
|
|
1402
1935
|
simsimd_jaccard_b8_sve(a, b, n, d);
|
|
1403
1936
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1415,9 +1948,9 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const* a, simsimd_b8_t const
|
|
|
1415
1948
|
* - Jensen-Shannon divergence: a measure of similarity between two probability distributions.
|
|
1416
1949
|
* - Kullback-Leibler divergence: a measure of how one probability distribution diverges from a second.
|
|
1417
1950
|
*
|
|
1418
|
-
* @param a The first
|
|
1419
|
-
* @param b The second
|
|
1420
|
-
* @param n The number of elements in the
|
|
1951
|
+
* @param a The first discrete probability distribution.
|
|
1952
|
+
* @param b The second discrete probability distribution.
|
|
1953
|
+
* @param n The number of elements in the discrete distributions.
|
|
1421
1954
|
* @param d The output divergence value.
|
|
1422
1955
|
*
|
|
1423
1956
|
* @note The distributions are assumed to be normalized.
|
|
@@ -1425,8 +1958,8 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const* a, simsimd_b8_t const
|
|
|
1425
1958
|
* @note The output divergence value is zero if and only if the two distributions are identical.
|
|
1426
1959
|
* @note Defined only for floating-point data types.
|
|
1427
1960
|
*/
|
|
1428
|
-
SIMSIMD_PUBLIC void simsimd_kl_f16(simsimd_f16_t const*
|
|
1429
|
-
simsimd_distance_t*
|
|
1961
|
+
SIMSIMD_PUBLIC void simsimd_kl_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1962
|
+
simsimd_distance_t *d) {
|
|
1430
1963
|
#if SIMSIMD_TARGET_NEON
|
|
1431
1964
|
simsimd_kl_f16_neon(a, b, n, d);
|
|
1432
1965
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1435,12 +1968,12 @@ SIMSIMD_PUBLIC void simsimd_kl_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1435
1968
|
simsimd_kl_f16_serial(a, b, n, d);
|
|
1436
1969
|
#endif
|
|
1437
1970
|
}
|
|
1438
|
-
SIMSIMD_PUBLIC void simsimd_kl_bf16(simsimd_bf16_t const*
|
|
1439
|
-
simsimd_distance_t*
|
|
1971
|
+
SIMSIMD_PUBLIC void simsimd_kl_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1972
|
+
simsimd_distance_t *d) {
|
|
1440
1973
|
simsimd_kl_bf16_serial(a, b, n, d);
|
|
1441
1974
|
}
|
|
1442
|
-
SIMSIMD_PUBLIC void simsimd_kl_f32(simsimd_f32_t const*
|
|
1443
|
-
simsimd_distance_t*
|
|
1975
|
+
SIMSIMD_PUBLIC void simsimd_kl_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1976
|
+
simsimd_distance_t *d) {
|
|
1444
1977
|
#if SIMSIMD_TARGET_NEON
|
|
1445
1978
|
simsimd_kl_f32_neon(a, b, n, d);
|
|
1446
1979
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1449,12 +1982,12 @@ SIMSIMD_PUBLIC void simsimd_kl_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1449
1982
|
simsimd_kl_f32_serial(a, b, n, d);
|
|
1450
1983
|
#endif
|
|
1451
1984
|
}
|
|
1452
|
-
SIMSIMD_PUBLIC void simsimd_kl_f64(simsimd_f64_t const*
|
|
1453
|
-
simsimd_distance_t*
|
|
1985
|
+
SIMSIMD_PUBLIC void simsimd_kl_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1986
|
+
simsimd_distance_t *d) {
|
|
1454
1987
|
simsimd_kl_f64_serial(a, b, n, d);
|
|
1455
1988
|
}
|
|
1456
|
-
SIMSIMD_PUBLIC void simsimd_js_f16(simsimd_f16_t const*
|
|
1457
|
-
simsimd_distance_t*
|
|
1989
|
+
SIMSIMD_PUBLIC void simsimd_js_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1990
|
+
simsimd_distance_t *d) {
|
|
1458
1991
|
#if SIMSIMD_TARGET_NEON
|
|
1459
1992
|
simsimd_js_f16_neon(a, b, n, d);
|
|
1460
1993
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1463,12 +1996,12 @@ SIMSIMD_PUBLIC void simsimd_js_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1463
1996
|
simsimd_js_f16_serial(a, b, n, d);
|
|
1464
1997
|
#endif
|
|
1465
1998
|
}
|
|
1466
|
-
SIMSIMD_PUBLIC void simsimd_js_bf16(simsimd_bf16_t const*
|
|
1467
|
-
simsimd_distance_t*
|
|
1999
|
+
SIMSIMD_PUBLIC void simsimd_js_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
2000
|
+
simsimd_distance_t *d) {
|
|
1468
2001
|
simsimd_js_bf16_serial(a, b, n, d);
|
|
1469
2002
|
}
|
|
1470
|
-
SIMSIMD_PUBLIC void simsimd_js_f32(simsimd_f32_t const*
|
|
1471
|
-
simsimd_distance_t*
|
|
2003
|
+
SIMSIMD_PUBLIC void simsimd_js_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
2004
|
+
simsimd_distance_t *d) {
|
|
1472
2005
|
#if SIMSIMD_TARGET_NEON
|
|
1473
2006
|
simsimd_js_f32_neon(a, b, n, d);
|
|
1474
2007
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1477,11 +2010,337 @@ SIMSIMD_PUBLIC void simsimd_js_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1477
2010
|
simsimd_js_f32_serial(a, b, n, d);
|
|
1478
2011
|
#endif
|
|
1479
2012
|
}
|
|
1480
|
-
SIMSIMD_PUBLIC void simsimd_js_f64(simsimd_f64_t const*
|
|
1481
|
-
simsimd_distance_t*
|
|
2013
|
+
SIMSIMD_PUBLIC void simsimd_js_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
2014
|
+
simsimd_distance_t *d) {
|
|
1482
2015
|
simsimd_js_f64_serial(a, b, n, d);
|
|
1483
2016
|
}
|
|
1484
2017
|
|
|
2018
|
+
/* Set operations
|
|
2019
|
+
*
|
|
2020
|
+
* @param a The first sorted array of integers.
|
|
2021
|
+
* @param b The second sorted array of integers.
|
|
2022
|
+
* @param a_length The number of elements in the first array.
|
|
2023
|
+
* @param b_length The number of elements in the second array.
|
|
2024
|
+
* @param d The output for the number of elements in the intersection.
|
|
2025
|
+
*/
|
|
2026
|
+
SIMSIMD_PUBLIC void simsimd_intersect_u16(simsimd_u16_t const *a, simsimd_u16_t const *b, simsimd_size_t a_length,
|
|
2027
|
+
simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2028
|
+
#if SIMSIMD_TARGET_SVE2
|
|
2029
|
+
simsimd_intersect_u16_sve2(a, b, a_length, b_length, d);
|
|
2030
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2031
|
+
simsimd_intersect_u16_neon(a, b, a_length, b_length, d);
|
|
2032
|
+
#elif SIMSIMD_TARGET_TURIN
|
|
2033
|
+
simsimd_intersect_u16_turin(a, b, a_length, b_length, d);
|
|
2034
|
+
#elif SIMSIMD_TARGET_ICE
|
|
2035
|
+
simsimd_intersect_u16_ice(a, b, a_length, b_length, d);
|
|
2036
|
+
#else
|
|
2037
|
+
simsimd_intersect_u16_serial(a, b, a_length, b_length, d);
|
|
2038
|
+
#endif
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
SIMSIMD_PUBLIC void simsimd_intersect_u32(simsimd_u32_t const *a, simsimd_u32_t const *b, simsimd_size_t a_length,
|
|
2042
|
+
simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2043
|
+
#if SIMSIMD_TARGET_SVE2
|
|
2044
|
+
simsimd_intersect_u32_sve2(a, b, a_length, b_length, d);
|
|
2045
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2046
|
+
simsimd_intersect_u32_neon(a, b, a_length, b_length, d);
|
|
2047
|
+
#elif SIMSIMD_TARGET_TURIN
|
|
2048
|
+
simsimd_intersect_u32_turin(a, b, a_length, b_length, d);
|
|
2049
|
+
#elif SIMSIMD_TARGET_ICE
|
|
2050
|
+
simsimd_intersect_u32_ice(a, b, a_length, b_length, d);
|
|
2051
|
+
#else
|
|
2052
|
+
simsimd_intersect_u32_serial(a, b, a_length, b_length, d);
|
|
2053
|
+
#endif
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
/* Weighted set operations
|
|
2057
|
+
*
|
|
2058
|
+
* @param a The first sorted array of integers.
|
|
2059
|
+
* @param b The second sorted array of integers.
|
|
2060
|
+
* @param a_weights The weights for the first array.
|
|
2061
|
+
* @param b_weights The weights for the second array.
|
|
2062
|
+
* @param a_length The number of elements in the first array.
|
|
2063
|
+
* @param b_length The number of elements in the second array.
|
|
2064
|
+
* @param d The output for the number of elements in the intersection.
|
|
2065
|
+
*/
|
|
2066
|
+
SIMSIMD_PUBLIC void simsimd_spdot_counts_u16(simsimd_u16_t const *a, simsimd_u16_t const *b,
|
|
2067
|
+
simsimd_i16_t const *a_weights, simsimd_i16_t const *b_weights,
|
|
2068
|
+
simsimd_size_t a_length, simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2069
|
+
#if SIMSIMD_TARGET_SVE2
|
|
2070
|
+
simsimd_spdot_counts_u16_sve2(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2071
|
+
#elif SIMSIMD_TARGET_TURIN
|
|
2072
|
+
simsimd_spdot_counts_u16_turin(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2073
|
+
#else
|
|
2074
|
+
simsimd_spdot_counts_u16_serial(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2075
|
+
#endif
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
SIMSIMD_PUBLIC void simsimd_spdot_weights_u16(simsimd_u16_t const *a, simsimd_u16_t const *b,
|
|
2079
|
+
simsimd_bf16_t const *a_weights, simsimd_bf16_t const *b_weights,
|
|
2080
|
+
simsimd_size_t a_length, simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2081
|
+
#if SIMSIMD_TARGET_SVE2
|
|
2082
|
+
simsimd_spdot_weights_u16_sve2(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2083
|
+
#elif SIMSIMD_TARGET_TURIN
|
|
2084
|
+
simsimd_spdot_weights_u16_turin(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2085
|
+
#else
|
|
2086
|
+
simsimd_spdot_weights_u16_serial(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2087
|
+
#endif
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
/* Curved space distances
|
|
2091
|
+
*
|
|
2092
|
+
* @param a The first vector of floating point values.
|
|
2093
|
+
* @param b The second vector of floating point values.
|
|
2094
|
+
* @param c The metric tensor or covariance matrix.
|
|
2095
|
+
* @param n The number of dimensions in the vectors.
|
|
2096
|
+
* @param d The output for the number of elements in the intersection.
|
|
2097
|
+
*/
|
|
2098
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_f64_t const *c,
|
|
2099
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2100
|
+
|
|
2101
|
+
simsimd_bilinear_f64_serial(a, b, c, n, d);
|
|
2102
|
+
}
|
|
2103
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_f64_t const *c,
|
|
2104
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2105
|
+
simsimd_mahalanobis_f64_serial(a, b, c, n, d);
|
|
2106
|
+
}
|
|
2107
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
2108
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2109
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2110
|
+
simsimd_bilinear_f32_skylake(a, b, c, n, d);
|
|
2111
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2112
|
+
simsimd_bilinear_f32_neon(a, b, c, n, d);
|
|
2113
|
+
#else
|
|
2114
|
+
simsimd_bilinear_f32_serial(a, b, c, n, d);
|
|
2115
|
+
#endif
|
|
2116
|
+
}
|
|
2117
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
2118
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2119
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2120
|
+
simsimd_mahalanobis_f32_skylake(a, b, c, n, d);
|
|
2121
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2122
|
+
simsimd_mahalanobis_f32_neon(a, b, c, n, d);
|
|
2123
|
+
#else
|
|
2124
|
+
simsimd_mahalanobis_f32_serial(a, b, c, n, d);
|
|
2125
|
+
#endif
|
|
2126
|
+
}
|
|
2127
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
2128
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2129
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2130
|
+
simsimd_bilinear_f16_sapphire(a, b, c, n, d);
|
|
2131
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2132
|
+
simsimd_bilinear_f16_haswell(a, b, c, n, d);
|
|
2133
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2134
|
+
simsimd_bilinear_f16_neon(a, b, c, n, d);
|
|
2135
|
+
#else
|
|
2136
|
+
simsimd_bilinear_f16_serial(a, b, c, n, d);
|
|
2137
|
+
#endif
|
|
2138
|
+
}
|
|
2139
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
2140
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2141
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2142
|
+
simsimd_mahalanobis_f16_sapphire(a, b, c, n, d);
|
|
2143
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2144
|
+
simsimd_mahalanobis_f16_haswell(a, b, c, n, d);
|
|
2145
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2146
|
+
simsimd_mahalanobis_f16_neon(a, b, c, n, d);
|
|
2147
|
+
#else
|
|
2148
|
+
simsimd_mahalanobis_f16_serial(a, b, c, n, d);
|
|
2149
|
+
#endif
|
|
2150
|
+
}
|
|
2151
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_bf16_t const *c,
|
|
2152
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2153
|
+
#if SIMSIMD_TARGET_GENOA
|
|
2154
|
+
simsimd_bilinear_bf16_genoa(a, b, c, n, d);
|
|
2155
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2156
|
+
simsimd_bilinear_bf16_haswell(a, b, c, n, d);
|
|
2157
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2158
|
+
simsimd_bilinear_bf16_neon(a, b, c, n, d);
|
|
2159
|
+
#else
|
|
2160
|
+
simsimd_bilinear_bf16_serial(a, b, c, n, d);
|
|
2161
|
+
#endif
|
|
2162
|
+
}
|
|
2163
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_bf16_t const *c,
|
|
2164
|
+
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2165
|
+
#if SIMSIMD_TARGET_GENOA
|
|
2166
|
+
simsimd_mahalanobis_bf16_genoa(a, b, c, n, d);
|
|
2167
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2168
|
+
simsimd_mahalanobis_bf16_haswell(a, b, c, n, d);
|
|
2169
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2170
|
+
simsimd_mahalanobis_bf16_neon(a, b, c, n, d);
|
|
2171
|
+
#else
|
|
2172
|
+
simsimd_mahalanobis_bf16_serial(a, b, c, n, d);
|
|
2173
|
+
#endif
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
/* Elementwise operations
|
|
2177
|
+
*
|
|
2178
|
+
* @param a The first vector of integral or floating point values.
|
|
2179
|
+
* @param b The second vector of integral or floating point values.
|
|
2180
|
+
* @param c The third vector of integral or floating point values.
|
|
2181
|
+
* @param n The number of dimensions in the vectors.
|
|
2182
|
+
* @param alpha The first scaling factor.
|
|
2183
|
+
* @param beta The first scaling factor.
|
|
2184
|
+
* @param r The output vector or integral or floating point values.
|
|
2185
|
+
*/
|
|
2186
|
+
SIMSIMD_PUBLIC void simsimd_wsum_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
2187
|
+
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_f64_t *r) {
|
|
2188
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2189
|
+
simsimd_wsum_f64_skylake(a, b, n, alpha, beta, r);
|
|
2190
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2191
|
+
simsimd_wsum_f64_haswell(a, b, n, alpha, beta, r);
|
|
2192
|
+
#else
|
|
2193
|
+
simsimd_wsum_f64_serial(a, b, n, alpha, beta, r);
|
|
2194
|
+
#endif
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
SIMSIMD_PUBLIC void simsimd_wsum_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
2198
|
+
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_f32_t *r) {
|
|
2199
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2200
|
+
simsimd_wsum_f32_skylake(a, b, n, alpha, beta, r);
|
|
2201
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2202
|
+
simsimd_wsum_f32_haswell(a, b, n, alpha, beta, r);
|
|
2203
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2204
|
+
simsimd_wsum_f32_neon(a, b, n, alpha, beta, r);
|
|
2205
|
+
#else
|
|
2206
|
+
simsimd_wsum_f32_serial(a, b, n, alpha, beta, r);
|
|
2207
|
+
#endif
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
SIMSIMD_PUBLIC void simsimd_wsum_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
2211
|
+
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_bf16_t *r) {
|
|
2212
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2213
|
+
simsimd_wsum_bf16_skylake(a, b, n, alpha, beta, r);
|
|
2214
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2215
|
+
simsimd_wsum_bf16_haswell(a, b, n, alpha, beta, r);
|
|
2216
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2217
|
+
simsimd_wsum_bf16_neon(a, b, n, alpha, beta, r);
|
|
2218
|
+
#else
|
|
2219
|
+
simsimd_wsum_bf16_serial(a, b, n, alpha, beta, r);
|
|
2220
|
+
#endif
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
SIMSIMD_PUBLIC void simsimd_wsum_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
2224
|
+
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_f16_t *r) {
|
|
2225
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2226
|
+
simsimd_wsum_f16_sapphire(a, b, n, alpha, beta, r);
|
|
2227
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2228
|
+
simsimd_wsum_f16_haswell(a, b, n, alpha, beta, r);
|
|
2229
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2230
|
+
simsimd_wsum_f16_neon(a, b, n, alpha, beta, r);
|
|
2231
|
+
#else
|
|
2232
|
+
simsimd_wsum_f16_serial(a, b, n, alpha, beta, r);
|
|
2233
|
+
#endif
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
SIMSIMD_PUBLIC void simsimd_wsum_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
2237
|
+
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_i8_t *r) {
|
|
2238
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2239
|
+
simsimd_wsum_i8_sapphire(a, b, n, alpha, beta, r);
|
|
2240
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2241
|
+
simsimd_wsum_i8_haswell(a, b, n, alpha, beta, r);
|
|
2242
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2243
|
+
simsimd_wsum_i8_neon(a, b, n, alpha, beta, r);
|
|
2244
|
+
#else
|
|
2245
|
+
simsimd_wsum_i8_serial(a, b, n, alpha, beta, r);
|
|
2246
|
+
#endif
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
SIMSIMD_PUBLIC void simsimd_wsum_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
2250
|
+
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_u8_t *r) {
|
|
2251
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2252
|
+
simsimd_wsum_u8_sapphire(a, b, n, alpha, beta, r);
|
|
2253
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2254
|
+
simsimd_wsum_u8_haswell(a, b, n, alpha, beta, r);
|
|
2255
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2256
|
+
simsimd_wsum_u8_neon(a, b, n, alpha, beta, r);
|
|
2257
|
+
#else
|
|
2258
|
+
simsimd_wsum_u8_serial(a, b, n, alpha, beta, r);
|
|
2259
|
+
#endif
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
SIMSIMD_PUBLIC void simsimd_fma_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_f64_t const *c,
|
|
2263
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2264
|
+
simsimd_f64_t *r) {
|
|
2265
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2266
|
+
simsimd_fma_f64_skylake(a, b, c, n, alpha, beta, r);
|
|
2267
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2268
|
+
simsimd_fma_f64_haswell(a, b, c, n, alpha, beta, r);
|
|
2269
|
+
#else
|
|
2270
|
+
simsimd_fma_f64_serial(a, b, c, n, alpha, beta, r);
|
|
2271
|
+
#endif
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
SIMSIMD_PUBLIC void simsimd_fma_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
2275
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2276
|
+
simsimd_f32_t *r) {
|
|
2277
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2278
|
+
simsimd_fma_f32_skylake(a, b, c, n, alpha, beta, r);
|
|
2279
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2280
|
+
simsimd_fma_f32_haswell(a, b, c, n, alpha, beta, r);
|
|
2281
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2282
|
+
simsimd_fma_f32_neon(a, b, c, n, alpha, beta, r);
|
|
2283
|
+
#else
|
|
2284
|
+
simsimd_fma_f32_serial(a, b, c, n, alpha, beta, r);
|
|
2285
|
+
#endif
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
SIMSIMD_PUBLIC void simsimd_fma_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_bf16_t const *c,
|
|
2289
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2290
|
+
simsimd_bf16_t *r) {
|
|
2291
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
2292
|
+
simsimd_fma_bf16_skylake(a, b, c, n, alpha, beta, r);
|
|
2293
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2294
|
+
simsimd_fma_bf16_haswell(a, b, c, n, alpha, beta, r);
|
|
2295
|
+
#elif SIMSIMD_TARGET_NEON
|
|
2296
|
+
simsimd_fma_bf16_neon(a, b, c, n, alpha, beta, r);
|
|
2297
|
+
#else
|
|
2298
|
+
simsimd_fma_bf16_serial(a, b, c, n, alpha, beta, r);
|
|
2299
|
+
#endif
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
SIMSIMD_PUBLIC void simsimd_fma_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
2303
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2304
|
+
simsimd_f16_t *r) {
|
|
2305
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2306
|
+
simsimd_fma_f16_sapphire(a, b, c, n, alpha, beta, r);
|
|
2307
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2308
|
+
simsimd_fma_f16_haswell(a, b, c, n, alpha, beta, r);
|
|
2309
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2310
|
+
simsimd_fma_f16_neon(a, b, c, n, alpha, beta, r);
|
|
2311
|
+
#else
|
|
2312
|
+
simsimd_fma_f16_serial(a, b, c, n, alpha, beta, r);
|
|
2313
|
+
#endif
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
SIMSIMD_PUBLIC void simsimd_fma_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_i8_t const *c,
|
|
2317
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2318
|
+
simsimd_i8_t *r) {
|
|
2319
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2320
|
+
simsimd_fma_i8_sapphire(a, b, c, n, alpha, beta, r);
|
|
2321
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2322
|
+
simsimd_fma_i8_haswell(a, b, c, n, alpha, beta, r);
|
|
2323
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2324
|
+
simsimd_fma_i8_neon(a, b, c, n, alpha, beta, r);
|
|
2325
|
+
#else
|
|
2326
|
+
simsimd_fma_i8_serial(a, b, c, n, alpha, beta, r);
|
|
2327
|
+
#endif
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
SIMSIMD_PUBLIC void simsimd_fma_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_u8_t const *c,
|
|
2331
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2332
|
+
simsimd_u8_t *r) {
|
|
2333
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2334
|
+
simsimd_fma_u8_sapphire(a, b, c, n, alpha, beta, r);
|
|
2335
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
2336
|
+
simsimd_fma_u8_haswell(a, b, c, n, alpha, beta, r);
|
|
2337
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2338
|
+
simsimd_fma_u8_neon(a, b, c, n, alpha, beta, r);
|
|
2339
|
+
#else
|
|
2340
|
+
simsimd_fma_u8_serial(a, b, c, n, alpha, beta, r);
|
|
2341
|
+
#endif
|
|
2342
|
+
}
|
|
2343
|
+
|
|
1485
2344
|
#endif
|
|
1486
2345
|
|
|
1487
2346
|
#ifdef __cplusplus
|