usearch 2.15.3 → 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/cpp/test.cpp +16 -0
- package/include/usearch/index.hpp +21 -5
- package/include/usearch/index_dense.hpp +6 -1
- package/include/usearch/index_plugins.hpp +345 -8
- package/javascript/lib.cpp +17 -5
- package/javascript/usearch.test.js +190 -21
- 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/CONTRIBUTING.md +71 -23
- package/simsimd/Cargo.lock +1 -1
- package/simsimd/Cargo.toml +4 -4
- package/simsimd/MANIFEST.in +2 -1
- package/simsimd/Package.swift +15 -3
- package/simsimd/README.md +104 -35
- package/simsimd/binding.gyp +6 -2
- package/simsimd/build.rs +2 -0
- package/simsimd/c/lib.c +180 -99
- package/simsimd/include/simsimd/binary.h +311 -102
- package/simsimd/include/simsimd/curved.h +134 -135
- package/simsimd/include/simsimd/dot.h +448 -274
- package/simsimd/include/simsimd/elementwise.h +1437 -0
- package/simsimd/include/simsimd/geospatial.h +2 -2
- package/simsimd/include/simsimd/mesh.h +2 -2
- package/simsimd/include/simsimd/probability.h +88 -88
- package/simsimd/include/simsimd/simsimd.h +1157 -772
- package/simsimd/include/simsimd/sparse.h +768 -147
- package/simsimd/include/simsimd/spatial.h +955 -376
- package/simsimd/include/simsimd/types.h +145 -71
- package/simsimd/javascript/lib.c +1 -2
- package/simsimd/package.json +4 -4
- package/simsimd/rust/lib.rs +14 -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
|
|
@@ -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.
|
|
@@ -103,13 +105,14 @@
|
|
|
103
105
|
#include "binary.h" // Hamming, Jaccard
|
|
104
106
|
#include "curved.h" // Mahalanobis, Bilinear Forms
|
|
105
107
|
#include "dot.h" // Inner (dot) product, and its conjugate
|
|
108
|
+
#include "elementwise.h" // Weighted Sum, Fused-Multiply-Add
|
|
106
109
|
#include "geospatial.h" // Haversine and Vincenty
|
|
107
110
|
#include "probability.h" // Kullback-Leibler, Jensen–Shannon
|
|
108
111
|
#include "sparse.h" // Intersect
|
|
109
112
|
#include "spatial.h" // L2, Cosine
|
|
110
113
|
|
|
111
114
|
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
112
|
-
#if defined(
|
|
115
|
+
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
113
116
|
#include <sys/sysctl.h>
|
|
114
117
|
#endif
|
|
115
118
|
|
|
@@ -147,7 +150,9 @@ typedef enum {
|
|
|
147
150
|
simsimd_metric_tanimoto_k = 'j', ///< Tanimoto coefficient is same as Jaccard
|
|
148
151
|
|
|
149
152
|
// Sets:
|
|
150
|
-
simsimd_metric_intersect_k = 'x',
|
|
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
|
|
151
156
|
|
|
152
157
|
// Curved Spaces:
|
|
153
158
|
simsimd_metric_bilinear_k = 'b', ///< Bilinear form
|
|
@@ -160,6 +165,10 @@ typedef enum {
|
|
|
160
165
|
simsimd_metric_js_k = 's', ///< Jensen-Shannon divergence
|
|
161
166
|
simsimd_metric_jensen_shannon_k = 's', ///< Jensen-Shannon divergence alias
|
|
162
167
|
|
|
168
|
+
// BLAS-like operations:
|
|
169
|
+
simsimd_metric_fma_k = 'f', ///< Fused Multiply-Add
|
|
170
|
+
simsimd_metric_wsum_k = 'w', ///< Weighted Sum
|
|
171
|
+
|
|
163
172
|
} simsimd_metric_kind_t;
|
|
164
173
|
|
|
165
174
|
/**
|
|
@@ -174,6 +183,8 @@ typedef enum {
|
|
|
174
183
|
simsimd_cap_ice_k = 1 << 12, ///< x86 AVX512 capability with advanced integer algos
|
|
175
184
|
simsimd_cap_genoa_k = 1 << 13, ///< x86 AVX512 capability with `bf16` support
|
|
176
185
|
simsimd_cap_sapphire_k = 1 << 14, ///< x86 AVX512 capability with `f16` support
|
|
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
|
|
177
188
|
|
|
178
189
|
simsimd_cap_neon_k = 1 << 20, ///< ARM NEON baseline capability
|
|
179
190
|
simsimd_cap_neon_f16_k = 1 << 21, ///< ARM NEON `f16` capability
|
|
@@ -196,8 +207,10 @@ typedef enum {
|
|
|
196
207
|
* interfaces.
|
|
197
208
|
*/
|
|
198
209
|
typedef enum {
|
|
199
|
-
simsimd_datatype_unknown_k = 0,
|
|
200
|
-
simsimd_datatype_b8_k = 1 << 1,
|
|
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
|
|
201
214
|
|
|
202
215
|
simsimd_datatype_i8_k = 1 << 2, ///< 8-bit signed integer
|
|
203
216
|
simsimd_datatype_i16_k = 1 << 3, ///< 16-bit signed integer
|
|
@@ -226,11 +239,12 @@ typedef enum {
|
|
|
226
239
|
* @param[in] a Pointer to the first data array.
|
|
227
240
|
* @param[in] b Pointer to the second data array.
|
|
228
241
|
* @param[in] n Number of scalar words in the input arrays.
|
|
229
|
-
* When dealing with sub-byte
|
|
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.
|
|
230
244
|
* @param[out] d Output value as a double-precision float.
|
|
231
245
|
* In complex dot-products @b two scalars are exported for the real and imaginary parts.
|
|
232
246
|
*/
|
|
233
|
-
typedef void (*simsimd_metric_dense_punned_t)(void const*
|
|
247
|
+
typedef void (*simsimd_metric_dense_punned_t)(void const *a, void const *b, simsimd_size_t n, simsimd_distance_t *d);
|
|
234
248
|
|
|
235
249
|
/**
|
|
236
250
|
* @brief Type-punned function pointer for sparse vector representations and similarity measures.
|
|
@@ -241,9 +255,9 @@ typedef void (*simsimd_metric_dense_punned_t)(void const* a, void const* b, sims
|
|
|
241
255
|
* @param[in] b_length Number of scalar words in the second input array.
|
|
242
256
|
* @param[out] d Output value as a double-precision float, generally without decimals.
|
|
243
257
|
*/
|
|
244
|
-
typedef void (*simsimd_metric_sparse_punned_t)(void const*
|
|
258
|
+
typedef void (*simsimd_metric_sparse_punned_t)(void const *a, void const *b, //
|
|
245
259
|
simsimd_size_t a_length, simsimd_size_t b_length, //
|
|
246
|
-
simsimd_distance_t*
|
|
260
|
+
simsimd_distance_t *d);
|
|
247
261
|
|
|
248
262
|
/**
|
|
249
263
|
* @brief Type-punned function pointer for curved vector spaces and similarity measures.
|
|
@@ -254,8 +268,39 @@ typedef void (*simsimd_metric_sparse_punned_t)(void const* a, void const* b,
|
|
|
254
268
|
* @param[in] n Number of scalar words in the input arrays.
|
|
255
269
|
* @param[out] d Output value as a double-precision float.
|
|
256
270
|
*/
|
|
257
|
-
typedef void (*simsimd_metric_curved_punned_t)(void const*
|
|
258
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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.
|
|
300
|
+
*/
|
|
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);
|
|
259
304
|
|
|
260
305
|
/**
|
|
261
306
|
* @brief Type-punned function pointer for a SimSIMD public interface.
|
|
@@ -271,8 +316,8 @@ SIMSIMD_DYNAMIC void simsimd_find_metric_punned( //
|
|
|
271
316
|
simsimd_datatype_t datatype, //
|
|
272
317
|
simsimd_capability_t supported, //
|
|
273
318
|
simsimd_capability_t allowed, //
|
|
274
|
-
simsimd_metric_punned_t*
|
|
275
|
-
simsimd_capability_t*
|
|
319
|
+
simsimd_metric_punned_t *metric_output, //
|
|
320
|
+
simsimd_capability_t *capability_output);
|
|
276
321
|
#else
|
|
277
322
|
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void);
|
|
278
323
|
SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
@@ -280,11 +325,11 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
280
325
|
simsimd_datatype_t datatype, //
|
|
281
326
|
simsimd_capability_t supported, //
|
|
282
327
|
simsimd_capability_t allowed, //
|
|
283
|
-
simsimd_metric_punned_t*
|
|
284
|
-
simsimd_capability_t*
|
|
328
|
+
simsimd_metric_punned_t *metric_output, //
|
|
329
|
+
simsimd_capability_t *capability_output);
|
|
285
330
|
#endif
|
|
286
331
|
|
|
287
|
-
#if
|
|
332
|
+
#if _SIMSIMD_TARGET_X86
|
|
288
333
|
|
|
289
334
|
/**
|
|
290
335
|
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
@@ -343,6 +388,9 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
|
343
388
|
// Check for AVX512BF16 (Function ID 7, Sub-leaf 1, EAX register)
|
|
344
389
|
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L205
|
|
345
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;
|
|
346
394
|
|
|
347
395
|
// Convert specific features into CPU generations
|
|
348
396
|
unsigned supports_haswell = supports_avx2 && supports_f16c && supports_fma;
|
|
@@ -351,6 +399,9 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
|
351
399
|
supports_avx512vbmi2 && supports_avx512vpopcntdq;
|
|
352
400
|
unsigned supports_genoa = supports_avx512bf16;
|
|
353
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;
|
|
354
405
|
|
|
355
406
|
return (simsimd_capability_t)( //
|
|
356
407
|
(simsimd_cap_haswell_k * supports_haswell) | //
|
|
@@ -358,12 +409,14 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
|
358
409
|
(simsimd_cap_ice_k * supports_ice) | //
|
|
359
410
|
(simsimd_cap_genoa_k * supports_genoa) | //
|
|
360
411
|
(simsimd_cap_sapphire_k * supports_sapphire) | //
|
|
412
|
+
(simsimd_cap_turin_k * supports_turin) | //
|
|
413
|
+
(simsimd_cap_sierra_k * supports_sierra) | //
|
|
361
414
|
(simsimd_cap_serial_k));
|
|
362
415
|
}
|
|
363
416
|
|
|
364
|
-
#endif //
|
|
417
|
+
#endif // _SIMSIMD_TARGET_X86
|
|
365
418
|
|
|
366
|
-
#if
|
|
419
|
+
#if _SIMSIMD_TARGET_ARM
|
|
367
420
|
|
|
368
421
|
/* Compiling the next section one may get: selected processor does not support system register name 'id_aa64zfr0_el1'.
|
|
369
422
|
* Suppressing assembler errors is very complicated, so when dealing with older ARM CPUs it's simpler to compile this
|
|
@@ -378,18 +431,14 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
|
378
431
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
379
432
|
*/
|
|
380
433
|
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
381
|
-
#if defined(
|
|
434
|
+
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
382
435
|
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
383
436
|
uint32_t supports_neon = 0, supports_fp16 = 0, supports_bf16 = 0, supports_i8mm = 0;
|
|
384
437
|
size_t size = sizeof(supports_neon);
|
|
385
|
-
if (sysctlbyname("hw.optional.neon", &supports_neon, &size, NULL, 0) != 0)
|
|
386
|
-
|
|
387
|
-
if (sysctlbyname("hw.optional.arm.
|
|
388
|
-
|
|
389
|
-
if (sysctlbyname("hw.optional.arm.FEAT_BF16", &supports_bf16, &size, NULL, 0) != 0)
|
|
390
|
-
supports_bf16 = 0;
|
|
391
|
-
if (sysctlbyname("hw.optional.arm.FEAT_I8MM", &supports_i8mm, &size, NULL, 0) != 0)
|
|
392
|
-
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;
|
|
393
442
|
|
|
394
443
|
return (simsimd_capability_t)( //
|
|
395
444
|
(simsimd_cap_neon_k * (supports_neon)) | //
|
|
@@ -398,23 +447,7 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
|
398
447
|
(simsimd_cap_neon_i8_k * (supports_neon && supports_i8mm)) | //
|
|
399
448
|
(simsimd_cap_serial_k));
|
|
400
449
|
|
|
401
|
-
#elif defined(
|
|
402
|
-
// This is how the `arm-cpusysregs` library does it:
|
|
403
|
-
//
|
|
404
|
-
// int ID_AA64ISAR1_EL1_BF16() const { return (int)(_aa64isar1 >> 44) & 0x0F; }
|
|
405
|
-
// int ID_AA64ZFR0_EL1_BF16() const { return (int)(_aa64zfr0 >> 20) & 0x0F; }
|
|
406
|
-
// int ID_AA64PFR0_EL1_FP() const { return (int)(_aa64pfr0 >> 16) & 0x0F; }
|
|
407
|
-
// int ID_AA64ISAR0_EL1_DP() const { return (int)(_aa64isar0 >> 44) & 0x0F; }
|
|
408
|
-
// int ID_AA64PFR0_EL1_SVE() const { return (int)(_aa64pfr0 >> 32) & 0x0F; }
|
|
409
|
-
// int ID_AA64ZFR0_EL1_SVEver() const { return (int)(_aa64zfr0) & 0x0F; }
|
|
410
|
-
// bool FEAT_BF16() const { return ID_AA64ISAR1_EL1_BF16() >= 1 || ID_AA64ZFR0_EL1_BF16() >= 1; }
|
|
411
|
-
// bool FEAT_FP16() const { return ID_AA64PFR0_EL1_FP() >= 1 && ID_AA64PFR0_EL1_FP() < 15; }
|
|
412
|
-
// bool FEAT_DotProd() const { return ID_AA64ISAR0_EL1_DP() >= 1; }
|
|
413
|
-
// bool FEAT_SVE() const { return ID_AA64PFR0_EL1_SVE() >= 1; }
|
|
414
|
-
// bool FEAT_SVE2() const { return ID_AA64ZFR0_EL1_SVEver() >= 1; }
|
|
415
|
-
// bool FEAT_I8MM() const { return ID_AA64ZFR0_EL1_I8MM() >= 1; }
|
|
416
|
-
//
|
|
417
|
-
// https://github.com/lelegard/arm-cpusysregs/tree/4837c62e619a5e5f12bf41b16a1ee1e71d62c76d
|
|
450
|
+
#elif defined(_SIMSIMD_DEFINED_LINUX)
|
|
418
451
|
|
|
419
452
|
// Read CPUID registers directly
|
|
420
453
|
unsigned long id_aa64isar0_el1 = 0, id_aa64isar1_el1 = 0, id_aa64pfr0_el1 = 0, id_aa64zfr0_el1 = 0;
|
|
@@ -444,8 +477,7 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
|
444
477
|
|
|
445
478
|
// Now let's unpack the status flags from ID_AA64ZFR0_EL1
|
|
446
479
|
// https://developer.arm.com/documentation/ddi0601/2024-03/AArch64-Registers/ID-AA64ZFR0-EL1--SVE-Feature-ID-Register-0?lang=en
|
|
447
|
-
if (supports_sve)
|
|
448
|
-
__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));
|
|
449
481
|
// I8MM, bits [47:44] of ID_AA64ZFR0_EL1
|
|
450
482
|
unsigned supports_sve_i8mm = ((id_aa64zfr0_el1 >> 44) & 0xF) >= 1;
|
|
451
483
|
// BF16, bits [23:20] of ID_AA64ZFR0_EL1
|
|
@@ -471,7 +503,7 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
|
471
503
|
(simsimd_cap_sve2_k * (supports_sve2)) | //
|
|
472
504
|
(simsimd_cap_sve2p1_k * (supports_sve2p1)) | //
|
|
473
505
|
(simsimd_cap_serial_k));
|
|
474
|
-
#else //
|
|
506
|
+
#else // if !_SIMSIMD_DEFINED_LINUX
|
|
475
507
|
return simsimd_cap_serial_k;
|
|
476
508
|
#endif
|
|
477
509
|
}
|
|
@@ -486,12 +518,12 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
|
486
518
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
487
519
|
*/
|
|
488
520
|
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_implementation(void) {
|
|
489
|
-
#if
|
|
521
|
+
#if _SIMSIMD_TARGET_X86
|
|
490
522
|
return _simsimd_capabilities_x86();
|
|
491
|
-
#endif //
|
|
492
|
-
#if
|
|
523
|
+
#endif // _SIMSIMD_TARGET_X86
|
|
524
|
+
#if _SIMSIMD_TARGET_ARM
|
|
493
525
|
return _simsimd_capabilities_arm();
|
|
494
|
-
#endif //
|
|
526
|
+
#endif // _SIMSIMD_TARGET_ARM
|
|
495
527
|
return simsimd_cap_serial_k;
|
|
496
528
|
}
|
|
497
529
|
|
|
@@ -505,623 +537,689 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_implementation(void) {
|
|
|
505
537
|
#pragma clang diagnostic ignored "-Wvolatile"
|
|
506
538
|
#endif
|
|
507
539
|
|
|
508
|
-
|
|
509
|
-
*
|
|
510
|
-
* supported and allowed by hardware capabilities.
|
|
511
|
-
*
|
|
512
|
-
* @param kind The kind of metric to be evaluated.
|
|
513
|
-
* @param datatype The data type for which the metric needs to be evaluated.
|
|
514
|
-
* @param supported The hardware capabilities supported by the CPU.
|
|
515
|
-
* @param allowed The hardware capabilities allowed for use.
|
|
516
|
-
* @param metric_output Output variable for the selected similarity function.
|
|
517
|
-
* @param capability_output Output variable for the utilized hardware capabilities.
|
|
518
|
-
*/
|
|
519
|
-
SIMSIMD_INTERNAL void _simsimd_find_metric_punned_implementation( //
|
|
520
|
-
simsimd_metric_kind_t kind, //
|
|
521
|
-
simsimd_datatype_t datatype, //
|
|
522
|
-
simsimd_capability_t supported, //
|
|
523
|
-
simsimd_capability_t allowed, //
|
|
524
|
-
simsimd_metric_punned_t* metric_output, //
|
|
525
|
-
simsimd_capability_t* capability_output) {
|
|
526
|
-
|
|
527
|
-
// Modern compilers abso-freaking-lutely love optimizing-out my logic!
|
|
528
|
-
// Just marking the variables as `volatile` is not enough, so we have
|
|
529
|
-
// to add inline assembly to further discourage them!
|
|
530
|
-
#if defined(_MSC_VER)
|
|
531
|
-
_ReadWriteBarrier();
|
|
532
|
-
#else
|
|
533
|
-
__asm__ __volatile__("" ::: "memory");
|
|
534
|
-
#endif
|
|
535
|
-
|
|
536
|
-
volatile simsimd_metric_punned_t* m = metric_output;
|
|
537
|
-
volatile simsimd_capability_t* c = capability_output;
|
|
538
|
-
volatile simsimd_capability_t viable = (simsimd_capability_t)(supported & allowed);
|
|
539
|
-
*m = (simsimd_metric_punned_t)0;
|
|
540
|
-
*c = (simsimd_capability_t)0;
|
|
541
|
-
|
|
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) {
|
|
542
542
|
typedef simsimd_metric_punned_t m_t;
|
|
543
|
-
switch (datatype) {
|
|
544
|
-
|
|
545
|
-
case simsimd_datatype_unknown_k: break;
|
|
546
|
-
|
|
547
|
-
// These data-types are not supported yet
|
|
548
|
-
case simsimd_datatype_i16_k: break;
|
|
549
|
-
case simsimd_datatype_i32_k: break;
|
|
550
|
-
case simsimd_datatype_i64_k: break;
|
|
551
|
-
case simsimd_datatype_u8_k: break;
|
|
552
|
-
case simsimd_datatype_u64_k: break;
|
|
553
|
-
|
|
554
|
-
// Double-precision floating-point vectors
|
|
555
|
-
case simsimd_datatype_f64_k: {
|
|
556
543
|
#if SIMSIMD_TARGET_SVE
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
}
|
|
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
|
+
}
|
|
565
551
|
#endif
|
|
566
552
|
#if SIMSIMD_TARGET_NEON
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
}
|
|
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
|
+
}
|
|
574
559
|
#endif
|
|
575
560
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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
|
+
}
|
|
605
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;
|
|
606
599
|
#if SIMSIMD_TARGET_SVE
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
}
|
|
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
|
+
}
|
|
615
607
|
#endif
|
|
616
608
|
#if SIMSIMD_TARGET_NEON
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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
|
+
}
|
|
627
620
|
#endif
|
|
628
621
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
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
|
+
}
|
|
643
637
|
#endif
|
|
644
638
|
#if SIMSIMD_TARGET_HASWELL
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
break;
|
|
671
|
-
}
|
|
672
|
-
// Half-precision floating-point vectors
|
|
673
|
-
case simsimd_datatype_f16_k: {
|
|
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
|
+
}
|
|
674
663
|
|
|
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;
|
|
675
667
|
#if SIMSIMD_TARGET_SVE_F16
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
}
|
|
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
|
+
}
|
|
684
675
|
#endif
|
|
685
676
|
#if SIMSIMD_TARGET_NEON_F16
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
}
|
|
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
|
+
}
|
|
700
690
|
#endif
|
|
701
691
|
#if SIMSIMD_TARGET_SAPPHIRE
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
}
|
|
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
|
+
}
|
|
718
707
|
#endif
|
|
719
708
|
#if SIMSIMD_TARGET_HASWELL
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
case simsimd_datatype_bf16_k: {
|
|
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;
|
|
755
743
|
#if SIMSIMD_TARGET_SVE_BF16
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
}
|
|
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
|
+
}
|
|
763
750
|
#endif
|
|
764
751
|
#if SIMSIMD_TARGET_NEON_BF16
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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
|
+
}
|
|
773
761
|
#endif
|
|
774
762
|
#if SIMSIMD_TARGET_GENOA
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
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
|
+
}
|
|
787
779
|
#endif
|
|
788
780
|
#if SIMSIMD_TARGET_HASWELL
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
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;
|
|
823
815
|
#if SIMSIMD_TARGET_NEON_I8
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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
|
+
}
|
|
832
837
|
#endif
|
|
833
838
|
#if SIMSIMD_TARGET_ICE
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
}
|
|
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
|
+
}
|
|
842
846
|
#endif
|
|
843
847
|
#if SIMSIMD_TARGET_HASWELL
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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
|
+
}
|
|
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
|
+
}
|
|
867
924
|
|
|
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;
|
|
868
928
|
#if SIMSIMD_TARGET_SVE
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
}
|
|
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
|
+
}
|
|
875
934
|
#endif
|
|
876
935
|
#if SIMSIMD_TARGET_NEON
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
}
|
|
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
|
+
}
|
|
883
941
|
#endif
|
|
884
942
|
#if SIMSIMD_TARGET_ICE
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
}
|
|
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
|
+
}
|
|
891
948
|
#endif
|
|
892
949
|
#if SIMSIMD_TARGET_HASWELL
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
default: break;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
break;
|
|
909
|
-
}
|
|
910
|
-
// Complex floating-point vectors
|
|
911
|
-
case simsimd_datatype_f32c_k: {
|
|
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
|
+
}
|
|
912
962
|
|
|
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;
|
|
913
966
|
#if SIMSIMD_TARGET_SVE
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
}
|
|
920
|
-
#endif
|
|
921
|
-
#if SIMSIMD_TARGET_NEON
|
|
922
|
-
if (viable & simsimd_cap_neon_k)
|
|
923
|
-
switch (kind) {
|
|
924
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_neon, *c = simsimd_cap_neon_k; return;
|
|
925
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_neon, *c = simsimd_cap_neon_k; return;
|
|
926
|
-
default: break;
|
|
927
|
-
}
|
|
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
|
+
}
|
|
928
972
|
#endif
|
|
929
973
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
default: break;
|
|
943
|
-
}
|
|
944
|
-
#endif
|
|
945
|
-
|
|
946
|
-
if (viable & simsimd_cap_serial_k)
|
|
947
|
-
switch (kind) {
|
|
948
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_serial, *c = simsimd_cap_serial_k; return;
|
|
949
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_serial, *c = simsimd_cap_serial_k; return;
|
|
950
|
-
default: break;
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
break;
|
|
954
|
-
}
|
|
955
|
-
// Complex double-precision floating-point vectors
|
|
956
|
-
case simsimd_datatype_f64c_k: {
|
|
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
|
+
}
|
|
957
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;
|
|
958
990
|
#if SIMSIMD_TARGET_SVE
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
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
|
+
}
|
|
996
|
+
#endif
|
|
997
|
+
#if SIMSIMD_TARGET_NEON
|
|
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
|
+
}
|
|
965
1003
|
#endif
|
|
966
1004
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
#
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
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
|
+
}
|
|
1010
|
+
#endif
|
|
1011
|
+
#if SIMSIMD_TARGET_HASWELL
|
|
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
|
+
}
|
|
986
1024
|
|
|
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;
|
|
987
1028
|
#if SIMSIMD_TARGET_SVE_F16
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
}
|
|
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
|
+
}
|
|
994
1034
|
#endif
|
|
995
1035
|
#if SIMSIMD_TARGET_NEON_F16
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
}
|
|
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
|
+
}
|
|
1002
1041
|
#endif
|
|
1003
1042
|
#if SIMSIMD_TARGET_SAPPHIRE
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
}
|
|
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
|
+
}
|
|
1010
1048
|
#endif
|
|
1011
1049
|
#if SIMSIMD_TARGET_HASWELL
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
default: break;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
break;
|
|
1028
|
-
}
|
|
1029
|
-
// Complex Brain floating-point vectors
|
|
1030
|
-
case simsimd_datatype_bf16c_k: {
|
|
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
|
+
}
|
|
1031
1062
|
|
|
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;
|
|
1032
1066
|
#if SIMSIMD_TARGET_NEON_BF16
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
}
|
|
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
|
+
}
|
|
1039
1072
|
#endif
|
|
1040
1073
|
#if SIMSIMD_TARGET_GENOA
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
default: break;
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
break;
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
// Unsigned 16-bit integer vectors
|
|
1060
|
-
case simsimd_datatype_u16_k: {
|
|
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
|
+
}
|
|
1061
1086
|
|
|
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;
|
|
1062
1090
|
#if SIMSIMD_TARGET_SVE2
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
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
|
+
}
|
|
1068
1099
|
#endif
|
|
1069
1100
|
#if SIMSIMD_TARGET_NEON
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
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
|
+
}
|
|
1075
1115
|
#endif
|
|
1076
1116
|
#if SIMSIMD_TARGET_ICE
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
break;
|
|
1090
|
-
}
|
|
1091
|
-
// Unsigned 32-bit integer vectors
|
|
1092
|
-
case simsimd_datatype_u32_k: {
|
|
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
|
+
}
|
|
1093
1127
|
|
|
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;
|
|
1094
1131
|
#if SIMSIMD_TARGET_SVE2
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
}
|
|
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
|
+
}
|
|
1100
1136
|
#endif
|
|
1101
1137
|
#if SIMSIMD_TARGET_NEON
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
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
|
+
}
|
|
1142
|
+
#endif
|
|
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
|
+
}
|
|
1107
1148
|
#endif
|
|
1108
1149
|
#if SIMSIMD_TARGET_ICE
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
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");
|
|
1187
|
+
#endif
|
|
1188
|
+
|
|
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);
|
|
1192
|
+
|
|
1193
|
+
switch (datatype) {
|
|
1194
|
+
|
|
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;
|
|
1123
1217
|
}
|
|
1124
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
|
+
|
|
1125
1223
|
// Modern compilers abso-freaking-lutely love optimizing-out my logic!
|
|
1126
1224
|
// Just marking the variables as `volatile` is not enough, so we have
|
|
1127
1225
|
// to add inline assembly to further discourage them!
|
|
@@ -1164,10 +1262,14 @@ SIMSIMD_PUBLIC simsimd_metric_punned_t simsimd_metric_punned( //
|
|
|
1164
1262
|
* - Check if the CPU supports AVX512F and AVX512BW extensions on Skylake x86 CPUs and newer
|
|
1165
1263
|
* - Check if the CPU supports AVX512VNNI, AVX512IFMA, AVX512BITALG, AVX512VBMI2, and AVX512VPOPCNTDQ
|
|
1166
1264
|
* extensions on Ice Lake x86 CPUs and newer
|
|
1265
|
+
* - Check if the CPU supports AVX512BF16 extensions on Genoa x86 CPUs and newer
|
|
1167
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
|
|
1168
1268
|
*
|
|
1169
1269
|
* @return 1 if the CPU supports the SIMD instruction set, 0 otherwise.
|
|
1170
1270
|
*/
|
|
1271
|
+
SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
1272
|
+
SIMSIMD_DYNAMIC int simsimd_uses_dynamic_dispatch(void);
|
|
1171
1273
|
SIMSIMD_DYNAMIC int simsimd_uses_neon(void);
|
|
1172
1274
|
SIMSIMD_DYNAMIC int simsimd_uses_neon_f16(void);
|
|
1173
1275
|
SIMSIMD_DYNAMIC int simsimd_uses_neon_bf16(void);
|
|
@@ -1180,9 +1282,10 @@ SIMSIMD_DYNAMIC int simsimd_uses_sve2(void);
|
|
|
1180
1282
|
SIMSIMD_DYNAMIC int simsimd_uses_haswell(void);
|
|
1181
1283
|
SIMSIMD_DYNAMIC int simsimd_uses_skylake(void);
|
|
1182
1284
|
SIMSIMD_DYNAMIC int simsimd_uses_ice(void);
|
|
1183
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void);
|
|
1184
1285
|
SIMSIMD_DYNAMIC int simsimd_uses_genoa(void);
|
|
1185
|
-
SIMSIMD_DYNAMIC int
|
|
1286
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void);
|
|
1287
|
+
SIMSIMD_DYNAMIC int simsimd_uses_turin(void);
|
|
1288
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sierra(void);
|
|
1186
1289
|
|
|
1187
1290
|
/* Inner products
|
|
1188
1291
|
* - Dot product: the sum of the products of the corresponding elements of two vectors.
|
|
@@ -1198,30 +1301,30 @@ SIMSIMD_DYNAMIC int simsimd_uses_dynamic_dispatch(void);
|
|
|
1198
1301
|
* @note The dot product is zero if and only if the two vectors are orthogonal.
|
|
1199
1302
|
* @note Defined only for floating-point and integer data types.
|
|
1200
1303
|
*/
|
|
1201
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f16(simsimd_f16_t const*
|
|
1202
|
-
simsimd_distance_t*
|
|
1203
|
-
SIMSIMD_DYNAMIC void simsimd_dot_bf16(simsimd_bf16_t const*
|
|
1204
|
-
simsimd_distance_t*
|
|
1205
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f32(simsimd_f32_t const*
|
|
1206
|
-
simsimd_distance_t*
|
|
1207
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f64(simsimd_f64_t const*
|
|
1208
|
-
simsimd_distance_t*
|
|
1209
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f16c(simsimd_f16_t const*
|
|
1210
|
-
simsimd_distance_t*
|
|
1211
|
-
SIMSIMD_DYNAMIC void simsimd_dot_bf16c(simsimd_bf16_t const*
|
|
1212
|
-
simsimd_distance_t*
|
|
1213
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f32c(simsimd_f32_t const*
|
|
1214
|
-
simsimd_distance_t*
|
|
1215
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f64c(simsimd_f64_t const*
|
|
1216
|
-
simsimd_distance_t*
|
|
1217
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f16c(simsimd_f16_t const*
|
|
1218
|
-
simsimd_distance_t*
|
|
1219
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_bf16c(simsimd_bf16_t const*
|
|
1220
|
-
simsimd_distance_t*
|
|
1221
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f32c(simsimd_f32_t const*
|
|
1222
|
-
simsimd_distance_t*
|
|
1223
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f64c(simsimd_f64_t const*
|
|
1224
|
-
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);
|
|
1225
1328
|
|
|
1226
1329
|
/* Spatial distances
|
|
1227
1330
|
* - Cosine distance: the cosine of the angle between two vectors.
|
|
@@ -1236,26 +1339,42 @@ SIMSIMD_DYNAMIC void simsimd_vdot_f64c(simsimd_f64_t const* a, simsimd_f64_t con
|
|
|
1236
1339
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1237
1340
|
* @note Defined only for floating-point and integer data types.
|
|
1238
1341
|
*/
|
|
1239
|
-
SIMSIMD_DYNAMIC void simsimd_cos_i8(simsimd_i8_t const*
|
|
1240
|
-
simsimd_distance_t*
|
|
1241
|
-
SIMSIMD_DYNAMIC void
|
|
1242
|
-
|
|
1243
|
-
SIMSIMD_DYNAMIC void
|
|
1244
|
-
|
|
1245
|
-
SIMSIMD_DYNAMIC void
|
|
1246
|
-
|
|
1247
|
-
SIMSIMD_DYNAMIC void
|
|
1248
|
-
simsimd_distance_t*
|
|
1249
|
-
SIMSIMD_DYNAMIC void
|
|
1250
|
-
simsimd_distance_t*
|
|
1251
|
-
SIMSIMD_DYNAMIC void
|
|
1252
|
-
|
|
1253
|
-
SIMSIMD_DYNAMIC void
|
|
1254
|
-
|
|
1255
|
-
SIMSIMD_DYNAMIC void
|
|
1256
|
-
simsimd_distance_t*
|
|
1257
|
-
SIMSIMD_DYNAMIC void
|
|
1258
|
-
|
|
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);
|
|
1259
1378
|
|
|
1260
1379
|
/* Binary distances
|
|
1261
1380
|
* - Hamming distance: the number of positions at which the corresponding bits are different.
|
|
@@ -1270,10 +1389,10 @@ SIMSIMD_DYNAMIC void simsimd_l2sq_f64(simsimd_f64_t const* a, simsimd_f64_t cons
|
|
|
1270
1389
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1271
1390
|
* @note Defined only for binary data.
|
|
1272
1391
|
*/
|
|
1273
|
-
SIMSIMD_DYNAMIC void simsimd_hamming_b8(simsimd_b8_t const*
|
|
1274
|
-
simsimd_distance_t*
|
|
1275
|
-
SIMSIMD_DYNAMIC void simsimd_jaccard_b8(simsimd_b8_t const*
|
|
1276
|
-
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);
|
|
1277
1396
|
|
|
1278
1397
|
/* Probability distributions
|
|
1279
1398
|
* - Jensen-Shannon divergence: a measure of similarity between two probability distributions.
|
|
@@ -1289,22 +1408,22 @@ SIMSIMD_DYNAMIC void simsimd_jaccard_b8(simsimd_b8_t const* a, simsimd_b8_t cons
|
|
|
1289
1408
|
* @note The output divergence value is zero if and only if the two distributions are identical.
|
|
1290
1409
|
* @note Defined only for floating-point data types.
|
|
1291
1410
|
*/
|
|
1292
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f16(simsimd_f16_t const*
|
|
1293
|
-
simsimd_distance_t*
|
|
1294
|
-
SIMSIMD_DYNAMIC void simsimd_kl_bf16(simsimd_bf16_t const*
|
|
1295
|
-
simsimd_distance_t*
|
|
1296
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f32(simsimd_f32_t const*
|
|
1297
|
-
simsimd_distance_t*
|
|
1298
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f64(simsimd_f64_t const*
|
|
1299
|
-
simsimd_distance_t*
|
|
1300
|
-
SIMSIMD_DYNAMIC void simsimd_js_f16(simsimd_f16_t const*
|
|
1301
|
-
simsimd_distance_t*
|
|
1302
|
-
SIMSIMD_DYNAMIC void simsimd_js_bf16(simsimd_bf16_t const*
|
|
1303
|
-
simsimd_distance_t*
|
|
1304
|
-
SIMSIMD_DYNAMIC void simsimd_js_f32(simsimd_f32_t const*
|
|
1305
|
-
simsimd_distance_t*
|
|
1306
|
-
SIMSIMD_DYNAMIC void simsimd_js_f64(simsimd_f64_t const*
|
|
1307
|
-
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);
|
|
1308
1427
|
|
|
1309
1428
|
#else
|
|
1310
1429
|
|
|
@@ -1321,22 +1440,24 @@ SIMSIMD_DYNAMIC void simsimd_js_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1321
1440
|
*/
|
|
1322
1441
|
|
|
1323
1442
|
// clang-format off
|
|
1324
|
-
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; }
|
|
1325
1459
|
SIMSIMD_PUBLIC int simsimd_uses_dynamic_dispatch(void) { return 0; }
|
|
1326
|
-
SIMSIMD_PUBLIC
|
|
1327
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_f16(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_F16 ; }
|
|
1328
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_bf16(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_BF16; }
|
|
1329
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_i8(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_I8; }
|
|
1330
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE; }
|
|
1331
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_f16(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_F16; }
|
|
1332
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_bf16(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_BF16; }
|
|
1333
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_i8(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_I8; }
|
|
1334
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve2(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE2; }
|
|
1335
|
-
SIMSIMD_PUBLIC int simsimd_uses_haswell(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_HASWELL; }
|
|
1336
|
-
SIMSIMD_PUBLIC int simsimd_uses_skylake(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SKYLAKE; }
|
|
1337
|
-
SIMSIMD_PUBLIC int simsimd_uses_ice(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_ICE; }
|
|
1338
|
-
SIMSIMD_PUBLIC int simsimd_uses_sapphire(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SAPPHIRE; }
|
|
1339
|
-
SIMSIMD_PUBLIC int simsimd_uses_genoa(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_GENOA; }
|
|
1460
|
+
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void) { return _simsimd_capabilities_implementation(); }
|
|
1340
1461
|
SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
1341
1462
|
simsimd_metric_kind_t kind, //
|
|
1342
1463
|
simsimd_datatype_t datatype, //
|
|
@@ -1362,8 +1483,32 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
1362
1483
|
* @note The dot product is zero if and only if the two vectors are orthogonal.
|
|
1363
1484
|
* @note Defined only for floating-point and integer data types.
|
|
1364
1485
|
*/
|
|
1365
|
-
SIMSIMD_PUBLIC void
|
|
1366
|
-
|
|
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) {
|
|
1367
1512
|
#if SIMSIMD_TARGET_SVE_F16
|
|
1368
1513
|
simsimd_dot_f16_sve(a, b, n, d);
|
|
1369
1514
|
#elif SIMSIMD_TARGET_NEON_F16
|
|
@@ -1376,9 +1521,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1376
1521
|
simsimd_dot_f16_serial(a, b, n, d);
|
|
1377
1522
|
#endif
|
|
1378
1523
|
}
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
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) {
|
|
1382
1526
|
#if SIMSIMD_TARGET_GENOA
|
|
1383
1527
|
simsimd_dot_bf16_genoa(a, b, n, d);
|
|
1384
1528
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1389,9 +1533,8 @@ SIMSIMD_PUBLIC void simsimd_dot_bf16(simsimd_bf16_t const* a, simsimd_bf16_t con
|
|
|
1389
1533
|
simsimd_dot_bf16_serial(a, b, n, d);
|
|
1390
1534
|
#endif
|
|
1391
1535
|
}
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
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) {
|
|
1395
1538
|
#if SIMSIMD_TARGET_SVE
|
|
1396
1539
|
simsimd_dot_f32_sve(a, b, n, d);
|
|
1397
1540
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1404,8 +1547,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1404
1547
|
simsimd_dot_f32_serial(a, b, n, d);
|
|
1405
1548
|
#endif
|
|
1406
1549
|
}
|
|
1407
|
-
SIMSIMD_PUBLIC void simsimd_dot_f64(simsimd_f64_t const*
|
|
1408
|
-
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) {
|
|
1409
1552
|
#if SIMSIMD_TARGET_SVE
|
|
1410
1553
|
simsimd_dot_f64_sve(a, b, n, d);
|
|
1411
1554
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1414,8 +1557,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1414
1557
|
simsimd_dot_f64_serial(a, b, n, d);
|
|
1415
1558
|
#endif
|
|
1416
1559
|
}
|
|
1417
|
-
SIMSIMD_PUBLIC void simsimd_dot_f16c(simsimd_f16_t const*
|
|
1418
|
-
simsimd_distance_t*
|
|
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) {
|
|
1419
1562
|
#if SIMSIMD_TARGET_SVE_F16
|
|
1420
1563
|
simsimd_dot_f16c_sve(a, b, n, d);
|
|
1421
1564
|
#elif SIMSIMD_TARGET_NEON_F16
|
|
@@ -1428,8 +1571,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f16c(simsimd_f16_t const* a, simsimd_f16_t const
|
|
|
1428
1571
|
simsimd_dot_f16c_serial(a, b, n, d);
|
|
1429
1572
|
#endif
|
|
1430
1573
|
}
|
|
1431
|
-
SIMSIMD_PUBLIC void simsimd_dot_bf16c(simsimd_bf16_t const*
|
|
1432
|
-
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) {
|
|
1433
1576
|
#if SIMSIMD_TARGET_GENOA
|
|
1434
1577
|
simsimd_dot_bf16c_genoa(a, b, n, d);
|
|
1435
1578
|
#elif SIMSIMD_TARGET_NEON_BF16
|
|
@@ -1438,8 +1581,8 @@ SIMSIMD_PUBLIC void simsimd_dot_bf16c(simsimd_bf16_t const* a, simsimd_bf16_t co
|
|
|
1438
1581
|
simsimd_dot_bf16c_serial(a, b, n, d);
|
|
1439
1582
|
#endif
|
|
1440
1583
|
}
|
|
1441
|
-
SIMSIMD_PUBLIC void simsimd_dot_f32c(simsimd_f32_t const*
|
|
1442
|
-
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) {
|
|
1443
1586
|
#if SIMSIMD_TARGET_SVE
|
|
1444
1587
|
simsimd_dot_f32c_sve(a, b, n, d);
|
|
1445
1588
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1452,8 +1595,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f32c(simsimd_f32_t const* a, simsimd_f32_t const
|
|
|
1452
1595
|
simsimd_dot_f32c_serial(a, b, n, d);
|
|
1453
1596
|
#endif
|
|
1454
1597
|
}
|
|
1455
|
-
SIMSIMD_PUBLIC void simsimd_dot_f64c(simsimd_f64_t const*
|
|
1456
|
-
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) {
|
|
1457
1600
|
#if SIMSIMD_TARGET_SVE
|
|
1458
1601
|
simsimd_dot_f64c_sve(a, b, n, d);
|
|
1459
1602
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1462,8 +1605,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f64c(simsimd_f64_t const* a, simsimd_f64_t const
|
|
|
1462
1605
|
simsimd_dot_f64c_serial(a, b, n, d);
|
|
1463
1606
|
#endif
|
|
1464
1607
|
}
|
|
1465
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16_t const*
|
|
1466
|
-
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) {
|
|
1467
1610
|
#if SIMSIMD_TARGET_SVE
|
|
1468
1611
|
simsimd_vdot_f16c_sve(a, b, n, d);
|
|
1469
1612
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1476,8 +1619,8 @@ SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16_t const* a, simsimd_f16_t cons
|
|
|
1476
1619
|
simsimd_vdot_f16c_serial(a, b, n, d);
|
|
1477
1620
|
#endif
|
|
1478
1621
|
}
|
|
1479
|
-
SIMSIMD_PUBLIC void simsimd_vdot_bf16c(simsimd_bf16_t const*
|
|
1480
|
-
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) {
|
|
1481
1624
|
#if SIMSIMD_TARGET_GENOA
|
|
1482
1625
|
simsimd_vdot_bf16c_genoa(a, b, n, d);
|
|
1483
1626
|
#elif SIMSIMD_TARGET_NEON_BF16
|
|
@@ -1486,8 +1629,8 @@ SIMSIMD_PUBLIC void simsimd_vdot_bf16c(simsimd_bf16_t const* a, simsimd_bf16_t c
|
|
|
1486
1629
|
simsimd_vdot_bf16c_serial(a, b, n, d);
|
|
1487
1630
|
#endif
|
|
1488
1631
|
}
|
|
1489
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f32c(simsimd_f32_t const*
|
|
1490
|
-
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) {
|
|
1491
1634
|
#if SIMSIMD_TARGET_SVE
|
|
1492
1635
|
simsimd_vdot_f32c_sve(a, b, n, d);
|
|
1493
1636
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1500,8 +1643,8 @@ SIMSIMD_PUBLIC void simsimd_vdot_f32c(simsimd_f32_t const* a, simsimd_f32_t cons
|
|
|
1500
1643
|
simsimd_vdot_f32c_serial(a, b, n, d);
|
|
1501
1644
|
#endif
|
|
1502
1645
|
}
|
|
1503
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f64c(simsimd_f64_t const*
|
|
1504
|
-
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) {
|
|
1505
1648
|
#if SIMSIMD_TARGET_SVE
|
|
1506
1649
|
simsimd_vdot_f64c_sve(a, b, n, d);
|
|
1507
1650
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1524,8 +1667,8 @@ SIMSIMD_PUBLIC void simsimd_vdot_f64c(simsimd_f64_t const* a, simsimd_f64_t cons
|
|
|
1524
1667
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1525
1668
|
* @note Defined only for floating-point and integer data types.
|
|
1526
1669
|
*/
|
|
1527
|
-
SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const*
|
|
1528
|
-
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) {
|
|
1529
1672
|
#if SIMSIMD_TARGET_NEON
|
|
1530
1673
|
simsimd_cos_i8_neon(a, b, n, d);
|
|
1531
1674
|
#elif SIMSIMD_TARGET_ICE
|
|
@@ -1536,8 +1679,20 @@ SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const* a, simsimd_i8_t const* b,
|
|
|
1536
1679
|
simsimd_cos_i8_serial(a, b, n, d);
|
|
1537
1680
|
#endif
|
|
1538
1681
|
}
|
|
1539
|
-
SIMSIMD_PUBLIC void
|
|
1540
|
-
|
|
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) {
|
|
1684
|
+
#if SIMSIMD_TARGET_NEON
|
|
1685
|
+
simsimd_cos_u8_neon(a, b, n, d);
|
|
1686
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1687
|
+
simsimd_cos_u8_ice(a, b, n, d);
|
|
1688
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1689
|
+
simsimd_cos_u8_haswell(a, b, n, d);
|
|
1690
|
+
#else
|
|
1691
|
+
simsimd_cos_u8_serial(a, b, n, d);
|
|
1692
|
+
#endif
|
|
1693
|
+
}
|
|
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) {
|
|
1541
1696
|
#if SIMSIMD_TARGET_SVE_F16
|
|
1542
1697
|
simsimd_cos_f16_sve(a, b, n, d);
|
|
1543
1698
|
#elif SIMSIMD_TARGET_NEON_F16
|
|
@@ -1550,8 +1705,8 @@ SIMSIMD_PUBLIC void simsimd_cos_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1550
1705
|
simsimd_cos_f16_serial(a, b, n, d);
|
|
1551
1706
|
#endif
|
|
1552
1707
|
}
|
|
1553
|
-
SIMSIMD_PUBLIC void simsimd_cos_bf16(simsimd_bf16_t const*
|
|
1554
|
-
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) {
|
|
1555
1710
|
#if SIMSIMD_TARGET_GENOA
|
|
1556
1711
|
simsimd_cos_bf16_genoa(a, b, n, d);
|
|
1557
1712
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1564,8 +1719,8 @@ SIMSIMD_PUBLIC void simsimd_cos_bf16(simsimd_bf16_t const* a, simsimd_bf16_t con
|
|
|
1564
1719
|
simsimd_cos_bf16_serial(a, b, n, d);
|
|
1565
1720
|
#endif
|
|
1566
1721
|
}
|
|
1567
|
-
SIMSIMD_PUBLIC void simsimd_cos_f32(simsimd_f32_t const*
|
|
1568
|
-
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) {
|
|
1569
1724
|
#if SIMSIMD_TARGET_SVE
|
|
1570
1725
|
simsimd_cos_f32_sve(a, b, n, d);
|
|
1571
1726
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1578,8 +1733,8 @@ SIMSIMD_PUBLIC void simsimd_cos_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1578
1733
|
simsimd_cos_f32_serial(a, b, n, d);
|
|
1579
1734
|
#endif
|
|
1580
1735
|
}
|
|
1581
|
-
SIMSIMD_PUBLIC void simsimd_cos_f64(simsimd_f64_t const*
|
|
1582
|
-
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) {
|
|
1583
1738
|
#if SIMSIMD_TARGET_SVE
|
|
1584
1739
|
simsimd_cos_f64_sve(a, b, n, d);
|
|
1585
1740
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1590,8 +1745,8 @@ SIMSIMD_PUBLIC void simsimd_cos_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1590
1745
|
simsimd_cos_f64_serial(a, b, n, d);
|
|
1591
1746
|
#endif
|
|
1592
1747
|
}
|
|
1593
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const*
|
|
1594
|
-
simsimd_distance_t*
|
|
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) {
|
|
1595
1750
|
#if SIMSIMD_TARGET_NEON
|
|
1596
1751
|
simsimd_l2sq_i8_neon(a, b, n, d);
|
|
1597
1752
|
#elif SIMSIMD_TARGET_ICE
|
|
@@ -1602,8 +1757,20 @@ SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const* a, simsimd_i8_t const* b
|
|
|
1602
1757
|
simsimd_l2sq_i8_serial(a, b, n, d);
|
|
1603
1758
|
#endif
|
|
1604
1759
|
}
|
|
1605
|
-
SIMSIMD_PUBLIC void
|
|
1606
|
-
|
|
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) {
|
|
1607
1774
|
#if SIMSIMD_TARGET_SVE_F16
|
|
1608
1775
|
simsimd_l2sq_f16_sve(a, b, n, d);
|
|
1609
1776
|
#elif SIMSIMD_TARGET_NEON_F16
|
|
@@ -1616,8 +1783,8 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f16(simsimd_f16_t const* a, simsimd_f16_t const
|
|
|
1616
1783
|
simsimd_l2sq_f16_serial(a, b, n, d);
|
|
1617
1784
|
#endif
|
|
1618
1785
|
}
|
|
1619
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_bf16(simsimd_bf16_t const*
|
|
1620
|
-
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) {
|
|
1621
1788
|
#if SIMSIMD_TARGET_GENOA
|
|
1622
1789
|
simsimd_l2sq_bf16_genoa(a, b, n, d);
|
|
1623
1790
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1630,8 +1797,8 @@ SIMSIMD_PUBLIC void simsimd_l2sq_bf16(simsimd_bf16_t const* a, simsimd_bf16_t co
|
|
|
1630
1797
|
simsimd_l2sq_bf16_serial(a, b, n, d);
|
|
1631
1798
|
#endif
|
|
1632
1799
|
}
|
|
1633
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_f32(simsimd_f32_t const*
|
|
1634
|
-
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) {
|
|
1635
1802
|
#if SIMSIMD_TARGET_SVE
|
|
1636
1803
|
simsimd_l2sq_f32_sve(a, b, n, d);
|
|
1637
1804
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1644,8 +1811,8 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f32(simsimd_f32_t const* a, simsimd_f32_t const
|
|
|
1644
1811
|
simsimd_l2sq_f32_serial(a, b, n, d);
|
|
1645
1812
|
#endif
|
|
1646
1813
|
}
|
|
1647
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const*
|
|
1648
|
-
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) {
|
|
1649
1816
|
#if SIMSIMD_TARGET_SVE
|
|
1650
1817
|
simsimd_l2sq_f64_sve(a, b, n, d);
|
|
1651
1818
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1656,8 +1823,8 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const* a, simsimd_f64_t const
|
|
|
1656
1823
|
simsimd_l2sq_f64_serial(a, b, n, d);
|
|
1657
1824
|
#endif
|
|
1658
1825
|
}
|
|
1659
|
-
SIMSIMD_PUBLIC void simsimd_l2_i8(simsimd_i8_t const*
|
|
1660
|
-
simsimd_distance_t*
|
|
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) {
|
|
1661
1828
|
#if SIMSIMD_TARGET_NEON
|
|
1662
1829
|
simsimd_l2_i8_neon(a, b, n, d);
|
|
1663
1830
|
#elif SIMSIMD_TARGET_ICE
|
|
@@ -1668,8 +1835,20 @@ SIMSIMD_PUBLIC void simsimd_l2_i8(simsimd_i8_t const* a, simsimd_i8_t const* b,
|
|
|
1668
1835
|
simsimd_l2_i8_serial(a, b, n, d);
|
|
1669
1836
|
#endif
|
|
1670
1837
|
}
|
|
1671
|
-
SIMSIMD_PUBLIC void
|
|
1672
|
-
|
|
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) {
|
|
1673
1852
|
#if SIMSIMD_TARGET_SVE_F16
|
|
1674
1853
|
simsimd_l2_f16_sve(a, b, n, d);
|
|
1675
1854
|
#elif SIMSIMD_TARGET_NEON_F16
|
|
@@ -1682,8 +1861,8 @@ SIMSIMD_PUBLIC void simsimd_l2_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1682
1861
|
simsimd_l2_f16_serial(a, b, n, d);
|
|
1683
1862
|
#endif
|
|
1684
1863
|
}
|
|
1685
|
-
SIMSIMD_PUBLIC void simsimd_l2_bf16(simsimd_bf16_t const*
|
|
1686
|
-
simsimd_distance_t*
|
|
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) {
|
|
1687
1866
|
#if SIMSIMD_TARGET_GENOA
|
|
1688
1867
|
simsimd_l2_bf16_genoa(a, b, n, d);
|
|
1689
1868
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1696,8 +1875,8 @@ SIMSIMD_PUBLIC void simsimd_l2_bf16(simsimd_bf16_t const* a, simsimd_bf16_t cons
|
|
|
1696
1875
|
simsimd_l2_bf16_serial(a, b, n, d);
|
|
1697
1876
|
#endif
|
|
1698
1877
|
}
|
|
1699
|
-
SIMSIMD_PUBLIC void simsimd_l2_f32(simsimd_f32_t const*
|
|
1700
|
-
simsimd_distance_t*
|
|
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) {
|
|
1701
1880
|
#if SIMSIMD_TARGET_SVE
|
|
1702
1881
|
simsimd_l2_f32_sve(a, b, n, d);
|
|
1703
1882
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1710,8 +1889,8 @@ SIMSIMD_PUBLIC void simsimd_l2_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1710
1889
|
simsimd_l2_f32_serial(a, b, n, d);
|
|
1711
1890
|
#endif
|
|
1712
1891
|
}
|
|
1713
|
-
SIMSIMD_PUBLIC void simsimd_l2_f64(simsimd_f64_t const*
|
|
1714
|
-
simsimd_distance_t*
|
|
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) {
|
|
1715
1894
|
#if SIMSIMD_TARGET_SVE
|
|
1716
1895
|
simsimd_l2_f64_sve(a, b, n, d);
|
|
1717
1896
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1736,8 +1915,8 @@ SIMSIMD_PUBLIC void simsimd_l2_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1736
1915
|
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1737
1916
|
* @note Defined only for binary data.
|
|
1738
1917
|
*/
|
|
1739
|
-
SIMSIMD_PUBLIC void simsimd_hamming_b8(simsimd_b8_t const*
|
|
1740
|
-
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) {
|
|
1741
1920
|
#if SIMSIMD_TARGET_SVE
|
|
1742
1921
|
simsimd_hamming_b8_sve(a, b, n, d);
|
|
1743
1922
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1750,8 +1929,8 @@ SIMSIMD_PUBLIC void simsimd_hamming_b8(simsimd_b8_t const* a, simsimd_b8_t const
|
|
|
1750
1929
|
simsimd_hamming_b8_serial(a, b, n, d);
|
|
1751
1930
|
#endif
|
|
1752
1931
|
}
|
|
1753
|
-
SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const*
|
|
1754
|
-
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) {
|
|
1755
1934
|
#if SIMSIMD_TARGET_SVE
|
|
1756
1935
|
simsimd_jaccard_b8_sve(a, b, n, d);
|
|
1757
1936
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1779,8 +1958,8 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const* a, simsimd_b8_t const
|
|
|
1779
1958
|
* @note The output divergence value is zero if and only if the two distributions are identical.
|
|
1780
1959
|
* @note Defined only for floating-point data types.
|
|
1781
1960
|
*/
|
|
1782
|
-
SIMSIMD_PUBLIC void simsimd_kl_f16(simsimd_f16_t const*
|
|
1783
|
-
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) {
|
|
1784
1963
|
#if SIMSIMD_TARGET_NEON
|
|
1785
1964
|
simsimd_kl_f16_neon(a, b, n, d);
|
|
1786
1965
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1789,12 +1968,12 @@ SIMSIMD_PUBLIC void simsimd_kl_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1789
1968
|
simsimd_kl_f16_serial(a, b, n, d);
|
|
1790
1969
|
#endif
|
|
1791
1970
|
}
|
|
1792
|
-
SIMSIMD_PUBLIC void simsimd_kl_bf16(simsimd_bf16_t const*
|
|
1793
|
-
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) {
|
|
1794
1973
|
simsimd_kl_bf16_serial(a, b, n, d);
|
|
1795
1974
|
}
|
|
1796
|
-
SIMSIMD_PUBLIC void simsimd_kl_f32(simsimd_f32_t const*
|
|
1797
|
-
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) {
|
|
1798
1977
|
#if SIMSIMD_TARGET_NEON
|
|
1799
1978
|
simsimd_kl_f32_neon(a, b, n, d);
|
|
1800
1979
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1803,12 +1982,12 @@ SIMSIMD_PUBLIC void simsimd_kl_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1803
1982
|
simsimd_kl_f32_serial(a, b, n, d);
|
|
1804
1983
|
#endif
|
|
1805
1984
|
}
|
|
1806
|
-
SIMSIMD_PUBLIC void simsimd_kl_f64(simsimd_f64_t const*
|
|
1807
|
-
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) {
|
|
1808
1987
|
simsimd_kl_f64_serial(a, b, n, d);
|
|
1809
1988
|
}
|
|
1810
|
-
SIMSIMD_PUBLIC void simsimd_js_f16(simsimd_f16_t const*
|
|
1811
|
-
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) {
|
|
1812
1991
|
#if SIMSIMD_TARGET_NEON
|
|
1813
1992
|
simsimd_js_f16_neon(a, b, n, d);
|
|
1814
1993
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1817,12 +1996,12 @@ SIMSIMD_PUBLIC void simsimd_js_f16(simsimd_f16_t const* a, simsimd_f16_t const*
|
|
|
1817
1996
|
simsimd_js_f16_serial(a, b, n, d);
|
|
1818
1997
|
#endif
|
|
1819
1998
|
}
|
|
1820
|
-
SIMSIMD_PUBLIC void simsimd_js_bf16(simsimd_bf16_t const*
|
|
1821
|
-
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) {
|
|
1822
2001
|
simsimd_js_bf16_serial(a, b, n, d);
|
|
1823
2002
|
}
|
|
1824
|
-
SIMSIMD_PUBLIC void simsimd_js_f32(simsimd_f32_t const*
|
|
1825
|
-
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) {
|
|
1826
2005
|
#if SIMSIMD_TARGET_NEON
|
|
1827
2006
|
simsimd_js_f32_neon(a, b, n, d);
|
|
1828
2007
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
@@ -1831,8 +2010,8 @@ SIMSIMD_PUBLIC void simsimd_js_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1831
2010
|
simsimd_js_f32_serial(a, b, n, d);
|
|
1832
2011
|
#endif
|
|
1833
2012
|
}
|
|
1834
|
-
SIMSIMD_PUBLIC void simsimd_js_f64(simsimd_f64_t const*
|
|
1835
|
-
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) {
|
|
1836
2015
|
simsimd_js_f64_serial(a, b, n, d);
|
|
1837
2016
|
}
|
|
1838
2017
|
|
|
@@ -1844,32 +2023,70 @@ SIMSIMD_PUBLIC void simsimd_js_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1844
2023
|
* @param b_length The number of elements in the second array.
|
|
1845
2024
|
* @param d The output for the number of elements in the intersection.
|
|
1846
2025
|
*/
|
|
1847
|
-
SIMSIMD_PUBLIC void simsimd_intersect_u16(simsimd_u16_t const*
|
|
1848
|
-
simsimd_size_t b_length, simsimd_distance_t*
|
|
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) {
|
|
1849
2028
|
#if SIMSIMD_TARGET_SVE2
|
|
1850
2029
|
simsimd_intersect_u16_sve2(a, b, a_length, b_length, d);
|
|
1851
2030
|
#elif SIMSIMD_TARGET_NEON
|
|
1852
2031
|
simsimd_intersect_u16_neon(a, b, a_length, b_length, d);
|
|
1853
|
-
#elif
|
|
2032
|
+
#elif SIMSIMD_TARGET_TURIN
|
|
2033
|
+
simsimd_intersect_u16_turin(a, b, a_length, b_length, d);
|
|
2034
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1854
2035
|
simsimd_intersect_u16_ice(a, b, a_length, b_length, d);
|
|
1855
2036
|
#else
|
|
1856
2037
|
simsimd_intersect_u16_serial(a, b, a_length, b_length, d);
|
|
1857
2038
|
#endif
|
|
1858
2039
|
}
|
|
1859
2040
|
|
|
1860
|
-
SIMSIMD_PUBLIC void simsimd_intersect_u32(simsimd_u32_t const*
|
|
1861
|
-
simsimd_size_t b_length, simsimd_distance_t*
|
|
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) {
|
|
1862
2043
|
#if SIMSIMD_TARGET_SVE2
|
|
1863
2044
|
simsimd_intersect_u32_sve2(a, b, a_length, b_length, d);
|
|
1864
2045
|
#elif SIMSIMD_TARGET_NEON
|
|
1865
2046
|
simsimd_intersect_u32_neon(a, b, a_length, b_length, d);
|
|
1866
|
-
#elif
|
|
2047
|
+
#elif SIMSIMD_TARGET_TURIN
|
|
2048
|
+
simsimd_intersect_u32_turin(a, b, a_length, b_length, d);
|
|
2049
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1867
2050
|
simsimd_intersect_u32_ice(a, b, a_length, b_length, d);
|
|
1868
2051
|
#else
|
|
1869
2052
|
simsimd_intersect_u32_serial(a, b, a_length, b_length, d);
|
|
1870
2053
|
#endif
|
|
1871
2054
|
}
|
|
1872
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
|
+
|
|
1873
2090
|
/* Curved space distances
|
|
1874
2091
|
*
|
|
1875
2092
|
* @param a The first vector of floating point values.
|
|
@@ -1878,17 +2095,17 @@ SIMSIMD_PUBLIC void simsimd_intersect_u32(simsimd_u32_t const* a, simsimd_u32_t
|
|
|
1878
2095
|
* @param n The number of dimensions in the vectors.
|
|
1879
2096
|
* @param d The output for the number of elements in the intersection.
|
|
1880
2097
|
*/
|
|
1881
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f64(simsimd_f64_t const*
|
|
1882
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1883
2100
|
|
|
1884
2101
|
simsimd_bilinear_f64_serial(a, b, c, n, d);
|
|
1885
2102
|
}
|
|
1886
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f64(simsimd_f64_t const*
|
|
1887
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1888
2105
|
simsimd_mahalanobis_f64_serial(a, b, c, n, d);
|
|
1889
2106
|
}
|
|
1890
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f32(simsimd_f32_t const*
|
|
1891
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1892
2109
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
1893
2110
|
simsimd_bilinear_f32_skylake(a, b, c, n, d);
|
|
1894
2111
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1897,8 +2114,8 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f32(simsimd_f32_t const* a, simsimd_f32_t c
|
|
|
1897
2114
|
simsimd_bilinear_f32_serial(a, b, c, n, d);
|
|
1898
2115
|
#endif
|
|
1899
2116
|
}
|
|
1900
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32(simsimd_f32_t const*
|
|
1901
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1902
2119
|
#if SIMSIMD_TARGET_SKYLAKE
|
|
1903
2120
|
simsimd_mahalanobis_f32_skylake(a, b, c, n, d);
|
|
1904
2121
|
#elif SIMSIMD_TARGET_NEON
|
|
@@ -1907,8 +2124,8 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f32(simsimd_f32_t const* a, simsimd_f32_
|
|
|
1907
2124
|
simsimd_mahalanobis_f32_serial(a, b, c, n, d);
|
|
1908
2125
|
#endif
|
|
1909
2126
|
}
|
|
1910
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f16(simsimd_f16_t const*
|
|
1911
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1912
2129
|
#if SIMSIMD_TARGET_SAPPHIRE
|
|
1913
2130
|
simsimd_bilinear_f16_sapphire(a, b, c, n, d);
|
|
1914
2131
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1919,8 +2136,8 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16(simsimd_f16_t const* a, simsimd_f16_t c
|
|
|
1919
2136
|
simsimd_bilinear_f16_serial(a, b, c, n, d);
|
|
1920
2137
|
#endif
|
|
1921
2138
|
}
|
|
1922
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16(simsimd_f16_t const*
|
|
1923
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1924
2141
|
#if SIMSIMD_TARGET_SAPPHIRE
|
|
1925
2142
|
simsimd_mahalanobis_f16_sapphire(a, b, c, n, d);
|
|
1926
2143
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1931,8 +2148,8 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16(simsimd_f16_t const* a, simsimd_f16_
|
|
|
1931
2148
|
simsimd_mahalanobis_f16_serial(a, b, c, n, d);
|
|
1932
2149
|
#endif
|
|
1933
2150
|
}
|
|
1934
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_bf16(simsimd_bf16_t const*
|
|
1935
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1936
2153
|
#if SIMSIMD_TARGET_GENOA
|
|
1937
2154
|
simsimd_bilinear_bf16_genoa(a, b, c, n, d);
|
|
1938
2155
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1943,8 +2160,8 @@ SIMSIMD_PUBLIC void simsimd_bilinear_bf16(simsimd_bf16_t const* a, simsimd_bf16_
|
|
|
1943
2160
|
simsimd_bilinear_bf16_serial(a, b, c, n, d);
|
|
1944
2161
|
#endif
|
|
1945
2162
|
}
|
|
1946
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16(simsimd_bf16_t const*
|
|
1947
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
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) {
|
|
1948
2165
|
#if SIMSIMD_TARGET_GENOA
|
|
1949
2166
|
simsimd_mahalanobis_bf16_genoa(a, b, c, n, d);
|
|
1950
2167
|
#elif SIMSIMD_TARGET_HASWELL
|
|
@@ -1956,6 +2173,174 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16(simsimd_bf16_t const* a, simsimd_bf
|
|
|
1956
2173
|
#endif
|
|
1957
2174
|
}
|
|
1958
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
|
+
|
|
1959
2344
|
#endif
|
|
1960
2345
|
|
|
1961
2346
|
#ifdef __cplusplus
|