usearch 2.15.1 → 2.15.3
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 +2 -2
- package/binding.gyp +1 -1
- package/c/CMakeLists.txt +10 -3
- package/cpp/README.md +1 -1
- package/cpp/bench.cpp +2 -2
- package/include/usearch/index.hpp +27 -13
- package/include/usearch/index_dense.hpp +45 -88
- package/include/usearch/index_plugins.hpp +128 -40
- package/javascript/usearch.test.js +15 -13
- 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/CODE_OF_CONDUCT.md +128 -0
- package/simsimd/CONTRIBUTING.md +18 -8
- package/simsimd/Cargo.lock +1 -1
- package/simsimd/Cargo.toml +1 -1
- package/simsimd/MANIFEST.in +2 -0
- package/simsimd/README.md +446 -158
- package/simsimd/build.rs +11 -1
- package/simsimd/c/lib.c +172 -40
- package/simsimd/include/simsimd/binary.h +11 -11
- package/simsimd/include/simsimd/curved.h +804 -0
- package/simsimd/include/simsimd/dot.h +333 -334
- package/simsimd/include/simsimd/geospatial.h +9 -3
- package/simsimd/include/simsimd/mesh.h +69 -0
- package/simsimd/include/simsimd/probability.h +178 -150
- package/simsimd/include/simsimd/simsimd.h +581 -107
- package/simsimd/include/simsimd/sparse.h +807 -0
- package/simsimd/include/simsimd/spatial.h +737 -502
- package/simsimd/include/simsimd/types.h +145 -75
- package/simsimd/javascript/simsimd.ts +4 -4
- package/simsimd/package.json +1 -1
- package/simsimd/rust/lib.rs +165 -0
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
* @section Choosing Arm Target Generations
|
|
45
45
|
*
|
|
46
46
|
* Arm CPUs share design IP, but are produced by different vendors, potentially making the platform
|
|
47
|
-
* even more fragmented than x86. There are 2
|
|
47
|
+
* even more fragmented than x86. There are 2 important families of SIMD extensions - NEON and SVE.
|
|
48
48
|
*
|
|
49
49
|
* - Armv8-A: +fp, +simd
|
|
50
50
|
* - Armv8.1-A: armv8-a, +crc, +lse, +rdma
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
* Here are the most important recent families of CPU cores designed by Arm:
|
|
69
69
|
*
|
|
70
70
|
* - Neoverse N1: armv8.2-a, extended with Armv8.4 "dotprod" instructions.
|
|
71
|
-
* Used in AWS @b Graviton2 and
|
|
71
|
+
* Used in AWS @b Graviton2 and Ampere @b Altra.
|
|
72
72
|
* https://developer.arm.com/Processors/Neoverse%20N1
|
|
73
73
|
* - Neoverse V1: armv8.4-a, extended with Armv8.6 bfloat/int8 "matmul" instructions.
|
|
74
74
|
* Used in AWS @b Graviton3, which also enables `sve`, `svebf16`, and `svei8mm`.
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
#define SIMSIMD_H
|
|
88
88
|
|
|
89
89
|
#define SIMSIMD_VERSION_MAJOR 5
|
|
90
|
-
#define SIMSIMD_VERSION_MINOR
|
|
91
|
-
#define SIMSIMD_VERSION_PATCH
|
|
90
|
+
#define SIMSIMD_VERSION_MINOR 6
|
|
91
|
+
#define SIMSIMD_VERSION_PATCH 4
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* @brief Removes compile-time dispatching, and replaces it with runtime dispatching.
|
|
@@ -101,9 +101,11 @@
|
|
|
101
101
|
#endif
|
|
102
102
|
|
|
103
103
|
#include "binary.h" // Hamming, Jaccard
|
|
104
|
+
#include "curved.h" // Mahalanobis, Bilinear Forms
|
|
104
105
|
#include "dot.h" // Inner (dot) product, and its conjugate
|
|
105
106
|
#include "geospatial.h" // Haversine and Vincenty
|
|
106
107
|
#include "probability.h" // Kullback-Leibler, Jensen–Shannon
|
|
108
|
+
#include "sparse.h" // Intersect
|
|
107
109
|
#include "spatial.h" // L2, Cosine
|
|
108
110
|
|
|
109
111
|
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
@@ -132,6 +134,8 @@ typedef enum {
|
|
|
132
134
|
simsimd_metric_cosine_k = 'c', ///< Cosine similarity alias
|
|
133
135
|
simsimd_metric_angular_k = 'c', ///< Cosine similarity alias
|
|
134
136
|
|
|
137
|
+
simsimd_metric_l2_k = '2', ///< Euclidean distance alias
|
|
138
|
+
simsimd_metric_euclidean_k = '2', ///< Euclidean distance alias
|
|
135
139
|
simsimd_metric_l2sq_k = 'e', ///< Squared Euclidean distance
|
|
136
140
|
simsimd_metric_sqeuclidean_k = 'e', ///< Squared Euclidean distance alias
|
|
137
141
|
|
|
@@ -142,6 +146,13 @@ typedef enum {
|
|
|
142
146
|
simsimd_metric_jaccard_k = 'j', ///< Jaccard coefficient
|
|
143
147
|
simsimd_metric_tanimoto_k = 'j', ///< Tanimoto coefficient is same as Jaccard
|
|
144
148
|
|
|
149
|
+
// Sets:
|
|
150
|
+
simsimd_metric_intersect_k = 'x', ///< Equivalent to unnormalized Jaccard
|
|
151
|
+
|
|
152
|
+
// Curved Spaces:
|
|
153
|
+
simsimd_metric_bilinear_k = 'b', ///< Bilinear form
|
|
154
|
+
simsimd_metric_mahalanobis_k = 'm', ///< Mahalanobis distance
|
|
155
|
+
|
|
145
156
|
// Probability:
|
|
146
157
|
simsimd_metric_kl_k = 'k', ///< Kullback-Leibler divergence
|
|
147
158
|
simsimd_metric_kullback_leibler_k = 'k', ///< Kullback-Leibler divergence alias
|
|
@@ -164,14 +175,16 @@ typedef enum {
|
|
|
164
175
|
simsimd_cap_genoa_k = 1 << 13, ///< x86 AVX512 capability with `bf16` support
|
|
165
176
|
simsimd_cap_sapphire_k = 1 << 14, ///< x86 AVX512 capability with `f16` support
|
|
166
177
|
|
|
167
|
-
simsimd_cap_neon_k = 1 << 20, ///< ARM NEON capability
|
|
168
|
-
simsimd_cap_neon_f16_k = 1 << 21, ///< ARM NEON
|
|
169
|
-
simsimd_cap_neon_bf16_k = 1 << 22, ///< ARM NEON
|
|
170
|
-
simsimd_cap_neon_i8_k = 1 << 23, ///< ARM NEON
|
|
171
|
-
simsimd_cap_sve_k = 1 << 24, ///< ARM SVE capability
|
|
172
|
-
simsimd_cap_sve_f16_k = 1 << 25, ///< ARM SVE
|
|
173
|
-
simsimd_cap_sve_bf16_k = 1 << 26, ///< ARM SVE
|
|
174
|
-
simsimd_cap_sve_i8_k = 1 << 27, ///< ARM SVE
|
|
178
|
+
simsimd_cap_neon_k = 1 << 20, ///< ARM NEON baseline capability
|
|
179
|
+
simsimd_cap_neon_f16_k = 1 << 21, ///< ARM NEON `f16` capability
|
|
180
|
+
simsimd_cap_neon_bf16_k = 1 << 22, ///< ARM NEON `bf16` capability
|
|
181
|
+
simsimd_cap_neon_i8_k = 1 << 23, ///< ARM NEON `i8` capability
|
|
182
|
+
simsimd_cap_sve_k = 1 << 24, ///< ARM SVE baseline capability
|
|
183
|
+
simsimd_cap_sve_f16_k = 1 << 25, ///< ARM SVE `f16` capability
|
|
184
|
+
simsimd_cap_sve_bf16_k = 1 << 26, ///< ARM SVE `bf16` capability
|
|
185
|
+
simsimd_cap_sve_i8_k = 1 << 27, ///< ARM SVE `i8` capability
|
|
186
|
+
simsimd_cap_sve2_k = 1 << 28, ///< ARM SVE2 capability
|
|
187
|
+
simsimd_cap_sve2p1_k = 1 << 29, ///< ARM SVE2p1 capability
|
|
175
188
|
|
|
176
189
|
} simsimd_capability_t;
|
|
177
190
|
|
|
@@ -184,9 +197,17 @@ typedef enum {
|
|
|
184
197
|
*/
|
|
185
198
|
typedef enum {
|
|
186
199
|
simsimd_datatype_unknown_k = 0, ///< Unknown data type
|
|
187
|
-
|
|
188
200
|
simsimd_datatype_b8_k = 1 << 1, ///< Single-bit values packed into 8-bit words
|
|
189
|
-
|
|
201
|
+
|
|
202
|
+
simsimd_datatype_i8_k = 1 << 2, ///< 8-bit signed integer
|
|
203
|
+
simsimd_datatype_i16_k = 1 << 3, ///< 16-bit signed integer
|
|
204
|
+
simsimd_datatype_i32_k = 1 << 4, ///< 32-bit signed integer
|
|
205
|
+
simsimd_datatype_i64_k = 1 << 5, ///< 64-bit signed integer
|
|
206
|
+
|
|
207
|
+
simsimd_datatype_u8_k = 1 << 6, ///< 8-bit unsigned integer
|
|
208
|
+
simsimd_datatype_u16_k = 1 << 7, ///< 16-bit unsigned integer
|
|
209
|
+
simsimd_datatype_u32_k = 1 << 8, ///< 32-bit unsigned integer
|
|
210
|
+
simsimd_datatype_u64_k = 1 << 9, ///< 64-bit unsigned integer
|
|
190
211
|
|
|
191
212
|
simsimd_datatype_f64_k = 1 << 10, ///< Double precision floating point
|
|
192
213
|
simsimd_datatype_f32_k = 1 << 11, ///< Single precision floating point
|
|
@@ -200,21 +221,67 @@ typedef enum {
|
|
|
200
221
|
} simsimd_datatype_t;
|
|
201
222
|
|
|
202
223
|
/**
|
|
203
|
-
* @brief Type-punned function pointer
|
|
224
|
+
* @brief Type-punned function pointer for dense vector representations and simplest similarity measures.
|
|
225
|
+
*
|
|
226
|
+
* @param[in] a Pointer to the first data array.
|
|
227
|
+
* @param[in] b Pointer to the second data array.
|
|
228
|
+
* @param[in] n Number of scalar words in the input arrays.
|
|
229
|
+
* When dealing with sub-byte data types, the number of scalar words is the number of bytes.
|
|
230
|
+
* @param[out] d Output value as a double-precision float.
|
|
231
|
+
* In complex dot-products @b two scalars are exported for the real and imaginary parts.
|
|
232
|
+
*/
|
|
233
|
+
typedef void (*simsimd_metric_dense_punned_t)(void const* a, void const* b, simsimd_size_t n, simsimd_distance_t* d);
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @brief Type-punned function pointer for sparse vector representations and similarity measures.
|
|
237
|
+
*
|
|
238
|
+
* @param[in] a Pointer to the first data array, generally a sorted array of integers.
|
|
239
|
+
* @param[in] b Pointer to the second data array, generally a sorted array of integers.
|
|
240
|
+
* @param[in] a_length Number of scalar words in the first input array.
|
|
241
|
+
* @param[in] b_length Number of scalar words in the second input array.
|
|
242
|
+
* @param[out] d Output value as a double-precision float, generally without decimals.
|
|
243
|
+
*/
|
|
244
|
+
typedef void (*simsimd_metric_sparse_punned_t)(void const* a, void const* b, //
|
|
245
|
+
simsimd_size_t a_length, simsimd_size_t b_length, //
|
|
246
|
+
simsimd_distance_t* d);
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @brief Type-punned function pointer for curved vector spaces and similarity measures.
|
|
204
250
|
*
|
|
205
251
|
* @param[in] a Pointer to the first data array.
|
|
206
252
|
* @param[in] b Pointer to the second data array.
|
|
253
|
+
* @param[in] c Pointer to the metric tensor array or some covariance matrix.
|
|
207
254
|
* @param[in] n Number of scalar words in the input arrays.
|
|
208
255
|
* @param[out] d Output value as a double-precision float.
|
|
209
|
-
* In complex dot-products @b two double-precision scalars are exported
|
|
210
|
-
* for the real and imaginary parts.
|
|
211
256
|
*/
|
|
212
|
-
typedef void (*
|
|
257
|
+
typedef void (*simsimd_metric_curved_punned_t)(void const* a, void const* b, void const* c, //
|
|
258
|
+
simsimd_size_t n, simsimd_distance_t* d);
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* @brief Type-punned function pointer for a SimSIMD public interface.
|
|
262
|
+
* Can be a `simsimd_metric_dense_punned_t`, `simsimd_metric_sparse_punned_t`,
|
|
263
|
+
* or `simsimd_metric_curved_punned_t`.
|
|
264
|
+
*/
|
|
265
|
+
typedef simsimd_metric_dense_punned_t simsimd_metric_punned_t;
|
|
213
266
|
|
|
214
267
|
#if SIMSIMD_DYNAMIC_DISPATCH
|
|
215
268
|
SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
269
|
+
SIMSIMD_DYNAMIC void simsimd_find_metric_punned( //
|
|
270
|
+
simsimd_metric_kind_t kind, //
|
|
271
|
+
simsimd_datatype_t datatype, //
|
|
272
|
+
simsimd_capability_t supported, //
|
|
273
|
+
simsimd_capability_t allowed, //
|
|
274
|
+
simsimd_metric_punned_t* metric_output, //
|
|
275
|
+
simsimd_capability_t* capability_output);
|
|
216
276
|
#else
|
|
217
277
|
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void);
|
|
278
|
+
SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
279
|
+
simsimd_metric_kind_t kind, //
|
|
280
|
+
simsimd_datatype_t datatype, //
|
|
281
|
+
simsimd_capability_t supported, //
|
|
282
|
+
simsimd_capability_t allowed, //
|
|
283
|
+
simsimd_metric_punned_t* metric_output, //
|
|
284
|
+
simsimd_capability_t* capability_output);
|
|
218
285
|
#endif
|
|
219
286
|
|
|
220
287
|
#if SIMSIMD_TARGET_X86
|
|
@@ -223,7 +290,7 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void);
|
|
|
223
290
|
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
224
291
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
225
292
|
*/
|
|
226
|
-
SIMSIMD_PUBLIC simsimd_capability_t
|
|
293
|
+
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
227
294
|
|
|
228
295
|
/// The states of 4 registers populated for a specific "cpuid" assembly call
|
|
229
296
|
union four_registers_t {
|
|
@@ -300,7 +367,7 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_x86(void) {
|
|
|
300
367
|
|
|
301
368
|
/* Compiling the next section one may get: selected processor does not support system register name 'id_aa64zfr0_el1'.
|
|
302
369
|
* Suppressing assembler errors is very complicated, so when dealing with older ARM CPUs it's simpler to compile this
|
|
303
|
-
* function
|
|
370
|
+
* function targeting newer ones.
|
|
304
371
|
*/
|
|
305
372
|
#pragma GCC push_options
|
|
306
373
|
#pragma GCC target("arch=armv8.5-a+sve")
|
|
@@ -310,7 +377,7 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_x86(void) {
|
|
|
310
377
|
* @brief Function to determine the SIMD capabilities of the current 64-bit Arm machine at @b runtime.
|
|
311
378
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
312
379
|
*/
|
|
313
|
-
SIMSIMD_PUBLIC simsimd_capability_t
|
|
380
|
+
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
314
381
|
#if defined(SIMSIMD_DEFINED_APPLE)
|
|
315
382
|
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
316
383
|
uint32_t supports_neon = 0, supports_fp16 = 0, supports_bf16 = 0, supports_i8mm = 0;
|
|
@@ -388,8 +455,8 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_arm(void) {
|
|
|
388
455
|
// - 0b0001: SVE2 is implemented
|
|
389
456
|
// - 0b0010: SVE2.1 is implemented
|
|
390
457
|
// This value must match the existing indicator obtained from ID_AA64PFR0_EL1:
|
|
391
|
-
|
|
392
|
-
|
|
458
|
+
unsigned supports_sve2 = ((id_aa64zfr0_el1) & 0xF) >= 1;
|
|
459
|
+
unsigned supports_sve2p1 = ((id_aa64zfr0_el1) & 0xF) >= 2;
|
|
393
460
|
unsigned supports_neon = 1; // NEON is always supported
|
|
394
461
|
|
|
395
462
|
return (simsimd_capability_t)( //
|
|
@@ -401,6 +468,8 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_arm(void) {
|
|
|
401
468
|
(simsimd_cap_sve_f16_k * (supports_sve && supports_fp16)) | //
|
|
402
469
|
(simsimd_cap_sve_bf16_k * (supports_sve && supports_sve_bf16)) | //
|
|
403
470
|
(simsimd_cap_sve_i8_k * (supports_sve && supports_sve_i8mm)) | //
|
|
471
|
+
(simsimd_cap_sve2_k * (supports_sve2)) | //
|
|
472
|
+
(simsimd_cap_sve2p1_k * (supports_sve2p1)) | //
|
|
404
473
|
(simsimd_cap_serial_k));
|
|
405
474
|
#else // SIMSIMD_DEFINED_LINUX
|
|
406
475
|
return simsimd_cap_serial_k;
|
|
@@ -409,18 +478,19 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_arm(void) {
|
|
|
409
478
|
|
|
410
479
|
#pragma clang attribute pop
|
|
411
480
|
#pragma GCC pop_options
|
|
481
|
+
|
|
412
482
|
#endif
|
|
413
483
|
|
|
414
484
|
/**
|
|
415
485
|
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
416
486
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
417
487
|
*/
|
|
418
|
-
SIMSIMD_PUBLIC simsimd_capability_t
|
|
488
|
+
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_implementation(void) {
|
|
419
489
|
#if SIMSIMD_TARGET_X86
|
|
420
|
-
return
|
|
490
|
+
return _simsimd_capabilities_x86();
|
|
421
491
|
#endif // SIMSIMD_TARGET_X86
|
|
422
492
|
#if SIMSIMD_TARGET_ARM
|
|
423
|
-
return
|
|
493
|
+
return _simsimd_capabilities_arm();
|
|
424
494
|
#endif // SIMSIMD_TARGET_ARM
|
|
425
495
|
return simsimd_cap_serial_k;
|
|
426
496
|
}
|
|
@@ -430,6 +500,11 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_implementation(void) {
|
|
|
430
500
|
#pragma clang diagnostic push
|
|
431
501
|
#pragma clang diagnostic ignored "-Wcast-function-type"
|
|
432
502
|
|
|
503
|
+
#ifdef __cplusplus //! option ‘-Wvolatile’ is valid for C++/ObjC++ but not for C
|
|
504
|
+
#pragma GCC diagnostic ignored "-Wvolatile"
|
|
505
|
+
#pragma clang diagnostic ignored "-Wvolatile"
|
|
506
|
+
#endif
|
|
507
|
+
|
|
433
508
|
/**
|
|
434
509
|
* @brief Determines the best suited metric implementation based on the given datatype,
|
|
435
510
|
* supported and allowed by hardware capabilities.
|
|
@@ -441,17 +516,26 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities_implementation(void) {
|
|
|
441
516
|
* @param metric_output Output variable for the selected similarity function.
|
|
442
517
|
* @param capability_output Output variable for the utilized hardware capabilities.
|
|
443
518
|
*/
|
|
444
|
-
|
|
445
|
-
simsimd_metric_kind_t kind,
|
|
446
|
-
simsimd_datatype_t datatype,
|
|
447
|
-
simsimd_capability_t supported,
|
|
448
|
-
simsimd_capability_t allowed,
|
|
449
|
-
simsimd_metric_punned_t* metric_output,
|
|
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, //
|
|
450
525
|
simsimd_capability_t* capability_output) {
|
|
451
526
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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);
|
|
455
539
|
*m = (simsimd_metric_punned_t)0;
|
|
456
540
|
*c = (simsimd_capability_t)0;
|
|
457
541
|
|
|
@@ -460,15 +544,31 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
460
544
|
|
|
461
545
|
case simsimd_datatype_unknown_k: break;
|
|
462
546
|
|
|
463
|
-
//
|
|
464
|
-
case
|
|
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;
|
|
465
553
|
|
|
554
|
+
// Double-precision floating-point vectors
|
|
555
|
+
case simsimd_datatype_f64_k: {
|
|
466
556
|
#if SIMSIMD_TARGET_SVE
|
|
467
|
-
if (viable &
|
|
557
|
+
if (viable & simsimd_cap_sve_k)
|
|
468
558
|
switch (kind) {
|
|
469
559
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
470
560
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
471
561
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
562
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
563
|
+
default: break;
|
|
564
|
+
}
|
|
565
|
+
#endif
|
|
566
|
+
#if SIMSIMD_TARGET_NEON
|
|
567
|
+
if (viable & simsimd_cap_neon_k)
|
|
568
|
+
switch (kind) {
|
|
569
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
570
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
571
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
472
572
|
default: break;
|
|
473
573
|
}
|
|
474
574
|
#endif
|
|
@@ -478,6 +578,7 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
478
578
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
479
579
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
480
580
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
581
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
481
582
|
default: break;
|
|
482
583
|
}
|
|
483
584
|
#endif
|
|
@@ -486,15 +587,21 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
486
587
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
487
588
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
488
589
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
590
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
489
591
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
490
592
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
593
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
594
|
+
case simsimd_metric_mahalanobis_k:
|
|
595
|
+
*m = (m_t)&simsimd_mahalanobis_f64_serial, *c = simsimd_cap_serial_k;
|
|
596
|
+
return;
|
|
491
597
|
default: break;
|
|
492
598
|
}
|
|
493
599
|
|
|
494
600
|
break;
|
|
601
|
+
}
|
|
495
602
|
|
|
496
603
|
// Single-precision floating-point vectors
|
|
497
|
-
case simsimd_datatype_f32_k:
|
|
604
|
+
case simsimd_datatype_f32_k: {
|
|
498
605
|
|
|
499
606
|
#if SIMSIMD_TARGET_SVE
|
|
500
607
|
if (viable & simsimd_cap_sve_k)
|
|
@@ -502,6 +609,7 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
502
609
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
503
610
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
504
611
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
612
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
505
613
|
default: break;
|
|
506
614
|
}
|
|
507
615
|
#endif
|
|
@@ -511,6 +619,7 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
511
619
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
512
620
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
513
621
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
622
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
514
623
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
515
624
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
516
625
|
default: break;
|
|
@@ -522,8 +631,13 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
522
631
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
523
632
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
524
633
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
634
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
525
635
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
526
636
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
637
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
638
|
+
case simsimd_metric_mahalanobis_k:
|
|
639
|
+
*m = (m_t)&simsimd_mahalanobis_f32_skylake, *c = simsimd_cap_skylake_k;
|
|
640
|
+
return;
|
|
527
641
|
default: break;
|
|
528
642
|
}
|
|
529
643
|
#endif
|
|
@@ -533,6 +647,7 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
533
647
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
534
648
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
535
649
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
650
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
536
651
|
default: break;
|
|
537
652
|
}
|
|
538
653
|
#endif
|
|
@@ -542,33 +657,44 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
542
657
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
543
658
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
544
659
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
660
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
545
661
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
546
662
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
663
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
664
|
+
case simsimd_metric_mahalanobis_k:
|
|
665
|
+
*m = (m_t)&simsimd_mahalanobis_f32_serial, *c = simsimd_cap_serial_k;
|
|
666
|
+
return;
|
|
547
667
|
default: break;
|
|
548
668
|
}
|
|
549
669
|
|
|
550
670
|
break;
|
|
551
|
-
|
|
671
|
+
}
|
|
552
672
|
// Half-precision floating-point vectors
|
|
553
|
-
case simsimd_datatype_f16_k:
|
|
673
|
+
case simsimd_datatype_f16_k: {
|
|
554
674
|
|
|
555
|
-
#if
|
|
675
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
556
676
|
if (viable & simsimd_cap_sve_k)
|
|
557
677
|
switch (kind) {
|
|
558
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_sve, *c =
|
|
559
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_sve, *c =
|
|
560
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_sve, *c =
|
|
678
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
679
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
680
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
681
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
561
682
|
default: break;
|
|
562
683
|
}
|
|
563
684
|
#endif
|
|
564
|
-
#if
|
|
685
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
565
686
|
if (viable & simsimd_cap_neon_f16_k)
|
|
566
687
|
switch (kind) {
|
|
567
688
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
568
689
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
569
690
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
691
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
570
692
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
571
693
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
694
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
695
|
+
case simsimd_metric_mahalanobis_k:
|
|
696
|
+
*m = (m_t)&simsimd_mahalanobis_f16_neon, *c = simsimd_cap_neon_f16_k;
|
|
697
|
+
return;
|
|
572
698
|
default: break;
|
|
573
699
|
}
|
|
574
700
|
#endif
|
|
@@ -578,8 +704,15 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
578
704
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
579
705
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
580
706
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
707
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
581
708
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
582
709
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
710
|
+
case simsimd_metric_bilinear_k:
|
|
711
|
+
*m = (m_t)&simsimd_bilinear_f16_sapphire, *c = simsimd_cap_sapphire_k;
|
|
712
|
+
return;
|
|
713
|
+
case simsimd_metric_mahalanobis_k:
|
|
714
|
+
*m = (m_t)&simsimd_mahalanobis_f16_sapphire, *c = simsimd_cap_sapphire_k;
|
|
715
|
+
return;
|
|
583
716
|
default: break;
|
|
584
717
|
}
|
|
585
718
|
#endif
|
|
@@ -589,8 +722,13 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
589
722
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
590
723
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
591
724
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
725
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
592
726
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
593
727
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
728
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
729
|
+
case simsimd_metric_mahalanobis_k:
|
|
730
|
+
*m = (m_t)&simsimd_mahalanobis_f16_haswell, *c = simsimd_cap_haswell_k;
|
|
731
|
+
return;
|
|
594
732
|
default: break;
|
|
595
733
|
}
|
|
596
734
|
#endif
|
|
@@ -600,30 +738,36 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
600
738
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
601
739
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
602
740
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
741
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
603
742
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
604
743
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
744
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
745
|
+
case simsimd_metric_mahalanobis_k:
|
|
746
|
+
*m = (m_t)&simsimd_mahalanobis_f16_serial, *c = simsimd_cap_serial_k;
|
|
747
|
+
return;
|
|
605
748
|
default: break;
|
|
606
749
|
}
|
|
607
750
|
|
|
608
751
|
break;
|
|
609
|
-
|
|
752
|
+
}
|
|
610
753
|
// Brain floating-point vectors
|
|
611
|
-
case simsimd_datatype_bf16_k:
|
|
754
|
+
case simsimd_datatype_bf16_k: {
|
|
755
|
+
#if SIMSIMD_TARGET_SVE_BF16
|
|
756
|
+
if (viable & simsimd_cap_sve_bf16_k)
|
|
757
|
+
switch (kind) {
|
|
758
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
759
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
760
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
761
|
+
default: break;
|
|
762
|
+
}
|
|
763
|
+
#endif
|
|
612
764
|
#if SIMSIMD_TARGET_NEON_BF16
|
|
613
765
|
if (viable & simsimd_cap_neon_bf16_k)
|
|
614
766
|
switch (kind) {
|
|
615
767
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
616
768
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
617
769
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
#endif
|
|
621
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
622
|
-
if (viable & simsimd_cap_haswell_k)
|
|
623
|
-
switch (kind) {
|
|
624
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
625
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
626
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
770
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
627
771
|
default: break;
|
|
628
772
|
}
|
|
629
773
|
#endif
|
|
@@ -633,6 +777,27 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
633
777
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
634
778
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
635
779
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
780
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
781
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
782
|
+
case simsimd_metric_mahalanobis_k:
|
|
783
|
+
*m = (m_t)&simsimd_mahalanobis_bf16_genoa, *c = simsimd_cap_genoa_k;
|
|
784
|
+
return;
|
|
785
|
+
default: break;
|
|
786
|
+
}
|
|
787
|
+
#endif
|
|
788
|
+
#if SIMSIMD_TARGET_HASWELL
|
|
789
|
+
if (viable & simsimd_cap_haswell_k)
|
|
790
|
+
switch (kind) {
|
|
791
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
792
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
793
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
794
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
795
|
+
case simsimd_metric_bilinear_k:
|
|
796
|
+
*m = (m_t)&simsimd_bilinear_bf16_haswell, *c = simsimd_cap_haswell_k;
|
|
797
|
+
return;
|
|
798
|
+
case simsimd_metric_mahalanobis_k:
|
|
799
|
+
*m = (m_t)&simsimd_mahalanobis_bf16_haswell, *c = simsimd_cap_haswell_k;
|
|
800
|
+
return;
|
|
636
801
|
default: break;
|
|
637
802
|
}
|
|
638
803
|
#endif
|
|
@@ -641,21 +806,27 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
641
806
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
642
807
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
643
808
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
809
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
644
810
|
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
645
811
|
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
812
|
+
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
813
|
+
case simsimd_metric_mahalanobis_k:
|
|
814
|
+
*m = (m_t)&simsimd_mahalanobis_bf16_serial, *c = simsimd_cap_serial_k;
|
|
815
|
+
return;
|
|
646
816
|
default: break;
|
|
647
817
|
}
|
|
648
818
|
|
|
649
819
|
break;
|
|
650
|
-
|
|
820
|
+
}
|
|
651
821
|
// Single-byte integer vectors
|
|
652
|
-
case simsimd_datatype_i8_k:
|
|
653
|
-
#if
|
|
822
|
+
case simsimd_datatype_i8_k: {
|
|
823
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
654
824
|
if (viable & simsimd_cap_neon_i8_k)
|
|
655
825
|
switch (kind) {
|
|
656
826
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
657
827
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
658
828
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
829
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
659
830
|
default: break;
|
|
660
831
|
}
|
|
661
832
|
#endif
|
|
@@ -665,6 +836,7 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
665
836
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
666
837
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
667
838
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
839
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
668
840
|
default: break;
|
|
669
841
|
}
|
|
670
842
|
#endif
|
|
@@ -674,6 +846,7 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
674
846
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
675
847
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
676
848
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
849
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
677
850
|
default: break;
|
|
678
851
|
}
|
|
679
852
|
#endif
|
|
@@ -683,13 +856,14 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
683
856
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
684
857
|
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
685
858
|
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
859
|
+
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
686
860
|
default: break;
|
|
687
861
|
}
|
|
688
862
|
|
|
689
863
|
break;
|
|
690
|
-
|
|
864
|
+
}
|
|
691
865
|
// Binary vectors
|
|
692
|
-
case simsimd_datatype_b8_k:
|
|
866
|
+
case simsimd_datatype_b8_k: {
|
|
693
867
|
|
|
694
868
|
#if SIMSIMD_TARGET_SVE
|
|
695
869
|
if (viable & simsimd_cap_sve_k)
|
|
@@ -732,8 +906,9 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
732
906
|
}
|
|
733
907
|
|
|
734
908
|
break;
|
|
735
|
-
|
|
736
|
-
|
|
909
|
+
}
|
|
910
|
+
// Complex floating-point vectors
|
|
911
|
+
case simsimd_datatype_f32c_k: {
|
|
737
912
|
|
|
738
913
|
#if SIMSIMD_TARGET_SVE
|
|
739
914
|
if (viable & simsimd_cap_sve_k)
|
|
@@ -776,8 +951,9 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
776
951
|
}
|
|
777
952
|
|
|
778
953
|
break;
|
|
779
|
-
|
|
780
|
-
|
|
954
|
+
}
|
|
955
|
+
// Complex double-precision floating-point vectors
|
|
956
|
+
case simsimd_datatype_f64c_k: {
|
|
781
957
|
|
|
782
958
|
#if SIMSIMD_TARGET_SVE
|
|
783
959
|
if (viable & simsimd_cap_sve_k)
|
|
@@ -804,18 +980,19 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
804
980
|
}
|
|
805
981
|
|
|
806
982
|
break;
|
|
983
|
+
}
|
|
984
|
+
// Complex half-precision floating-point vectors
|
|
985
|
+
case simsimd_datatype_f16c_k: {
|
|
807
986
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
#if SIMSIMD_TARGET_SVE
|
|
987
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
811
988
|
if (viable & simsimd_cap_sve_k)
|
|
812
989
|
switch (kind) {
|
|
813
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_sve, *c =
|
|
814
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_sve, *c =
|
|
990
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
991
|
+
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
815
992
|
default: break;
|
|
816
993
|
}
|
|
817
994
|
#endif
|
|
818
|
-
#if
|
|
995
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
819
996
|
if (viable & simsimd_cap_neon_f16_k)
|
|
820
997
|
switch (kind) {
|
|
821
998
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
@@ -848,7 +1025,9 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
848
1025
|
}
|
|
849
1026
|
|
|
850
1027
|
break;
|
|
851
|
-
|
|
1028
|
+
}
|
|
1029
|
+
// Complex Brain floating-point vectors
|
|
1030
|
+
case simsimd_datatype_bf16c_k: {
|
|
852
1031
|
|
|
853
1032
|
#if SIMSIMD_TARGET_NEON_BF16
|
|
854
1033
|
if (viable & simsimd_cap_neon_bf16_k)
|
|
@@ -876,6 +1055,81 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
876
1055
|
|
|
877
1056
|
break;
|
|
878
1057
|
}
|
|
1058
|
+
|
|
1059
|
+
// Unsigned 16-bit integer vectors
|
|
1060
|
+
case simsimd_datatype_u16_k: {
|
|
1061
|
+
|
|
1062
|
+
#if SIMSIMD_TARGET_SVE2
|
|
1063
|
+
if (viable & simsimd_cap_sve_k)
|
|
1064
|
+
switch (kind) {
|
|
1065
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_sve2, *c = simsimd_cap_sve_k; return;
|
|
1066
|
+
default: break;
|
|
1067
|
+
}
|
|
1068
|
+
#endif
|
|
1069
|
+
#if SIMSIMD_TARGET_NEON
|
|
1070
|
+
if (viable & simsimd_cap_neon_k)
|
|
1071
|
+
switch (kind) {
|
|
1072
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_neon, *c = simsimd_cap_neon_k; return;
|
|
1073
|
+
default: break;
|
|
1074
|
+
}
|
|
1075
|
+
#endif
|
|
1076
|
+
#if SIMSIMD_TARGET_ICE
|
|
1077
|
+
if (viable & simsimd_cap_ice_k)
|
|
1078
|
+
switch (kind) {
|
|
1079
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_ice, *c = simsimd_cap_skylake_k; return;
|
|
1080
|
+
default: break;
|
|
1081
|
+
}
|
|
1082
|
+
#endif
|
|
1083
|
+
if (viable & simsimd_cap_serial_k)
|
|
1084
|
+
switch (kind) {
|
|
1085
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_serial, *c = simsimd_cap_serial_k; return;
|
|
1086
|
+
default: break;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
break;
|
|
1090
|
+
}
|
|
1091
|
+
// Unsigned 32-bit integer vectors
|
|
1092
|
+
case simsimd_datatype_u32_k: {
|
|
1093
|
+
|
|
1094
|
+
#if SIMSIMD_TARGET_SVE2
|
|
1095
|
+
if (viable & simsimd_cap_sve_k)
|
|
1096
|
+
switch (kind) {
|
|
1097
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_sve2, *c = simsimd_cap_sve_k; return;
|
|
1098
|
+
default: break;
|
|
1099
|
+
}
|
|
1100
|
+
#endif
|
|
1101
|
+
#if SIMSIMD_TARGET_NEON
|
|
1102
|
+
if (viable & simsimd_cap_neon_k)
|
|
1103
|
+
switch (kind) {
|
|
1104
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_neon, *c = simsimd_cap_neon_k; return;
|
|
1105
|
+
default: break;
|
|
1106
|
+
}
|
|
1107
|
+
#endif
|
|
1108
|
+
#if SIMSIMD_TARGET_ICE
|
|
1109
|
+
if (viable & simsimd_cap_ice_k)
|
|
1110
|
+
switch (kind) {
|
|
1111
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_ice, *c = simsimd_cap_skylake_k; return;
|
|
1112
|
+
default: break;
|
|
1113
|
+
}
|
|
1114
|
+
#endif
|
|
1115
|
+
if (viable & simsimd_cap_serial_k)
|
|
1116
|
+
switch (kind) {
|
|
1117
|
+
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_serial, *c = simsimd_cap_serial_k; return;
|
|
1118
|
+
default: break;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
break;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// Modern compilers abso-freaking-lutely love optimizing-out my logic!
|
|
1126
|
+
// Just marking the variables as `volatile` is not enough, so we have
|
|
1127
|
+
// to add inline assembly to further discourage them!
|
|
1128
|
+
#if defined(_MSC_VER)
|
|
1129
|
+
_ReadWriteBarrier();
|
|
1130
|
+
#else
|
|
1131
|
+
__asm__ __volatile__("" ::: "memory");
|
|
1132
|
+
#endif
|
|
879
1133
|
}
|
|
880
1134
|
|
|
881
1135
|
#pragma GCC diagnostic pop
|
|
@@ -922,12 +1176,13 @@ SIMSIMD_DYNAMIC int simsimd_uses_sve(void);
|
|
|
922
1176
|
SIMSIMD_DYNAMIC int simsimd_uses_sve_f16(void);
|
|
923
1177
|
SIMSIMD_DYNAMIC int simsimd_uses_sve_bf16(void);
|
|
924
1178
|
SIMSIMD_DYNAMIC int simsimd_uses_sve_i8(void);
|
|
1179
|
+
SIMSIMD_DYNAMIC int simsimd_uses_sve2(void);
|
|
925
1180
|
SIMSIMD_DYNAMIC int simsimd_uses_haswell(void);
|
|
926
1181
|
SIMSIMD_DYNAMIC int simsimd_uses_skylake(void);
|
|
927
1182
|
SIMSIMD_DYNAMIC int simsimd_uses_ice(void);
|
|
928
1183
|
SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void);
|
|
929
1184
|
SIMSIMD_DYNAMIC int simsimd_uses_genoa(void);
|
|
930
|
-
SIMSIMD_DYNAMIC
|
|
1185
|
+
SIMSIMD_DYNAMIC int simsimd_uses_dynamic_dispatch(void);
|
|
931
1186
|
|
|
932
1187
|
/* Inner products
|
|
933
1188
|
* - Dot product: the sum of the products of the corresponding elements of two vectors.
|
|
@@ -1024,9 +1279,9 @@ SIMSIMD_DYNAMIC void simsimd_jaccard_b8(simsimd_b8_t const* a, simsimd_b8_t cons
|
|
|
1024
1279
|
* - Jensen-Shannon divergence: a measure of similarity between two probability distributions.
|
|
1025
1280
|
* - Kullback-Leibler divergence: a measure of how one probability distribution diverges from a second.
|
|
1026
1281
|
*
|
|
1027
|
-
* @param a The first
|
|
1028
|
-
* @param b The second
|
|
1029
|
-
* @param n The number of elements in the
|
|
1282
|
+
* @param a The first discrete probability distribution.
|
|
1283
|
+
* @param b The second discrete probability distribution.
|
|
1284
|
+
* @param n The number of elements in the discrete distributions.
|
|
1030
1285
|
* @param d The output divergence value.
|
|
1031
1286
|
*
|
|
1032
1287
|
* @note The distributions are assumed to be normalized.
|
|
@@ -1066,20 +1321,31 @@ SIMSIMD_DYNAMIC void simsimd_js_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1066
1321
|
*/
|
|
1067
1322
|
|
|
1068
1323
|
// clang-format off
|
|
1324
|
+
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void) { return _simsimd_capabilities_implementation(); }
|
|
1325
|
+
SIMSIMD_PUBLIC int simsimd_uses_dynamic_dispatch(void) { return 0; }
|
|
1069
1326
|
SIMSIMD_PUBLIC int simsimd_uses_neon(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON; }
|
|
1070
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_f16(void) { return SIMSIMD_TARGET_ARM &&
|
|
1071
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_bf16(void) { return SIMSIMD_TARGET_ARM &&
|
|
1072
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_i8(void) { return SIMSIMD_TARGET_ARM &&
|
|
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; }
|
|
1073
1330
|
SIMSIMD_PUBLIC int simsimd_uses_sve(void) { return SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE; }
|
|
1074
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_f16(void) { return SIMSIMD_TARGET_ARM &&
|
|
1075
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_bf16(void) { return SIMSIMD_TARGET_ARM &&
|
|
1076
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_i8(void) { return SIMSIMD_TARGET_ARM &&
|
|
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; }
|
|
1077
1335
|
SIMSIMD_PUBLIC int simsimd_uses_haswell(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_HASWELL; }
|
|
1078
1336
|
SIMSIMD_PUBLIC int simsimd_uses_skylake(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SKYLAKE; }
|
|
1079
1337
|
SIMSIMD_PUBLIC int simsimd_uses_ice(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_ICE; }
|
|
1080
1338
|
SIMSIMD_PUBLIC int simsimd_uses_sapphire(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SAPPHIRE; }
|
|
1081
1339
|
SIMSIMD_PUBLIC int simsimd_uses_genoa(void) { return SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_GENOA; }
|
|
1082
|
-
SIMSIMD_PUBLIC
|
|
1340
|
+
SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
1341
|
+
simsimd_metric_kind_t kind, //
|
|
1342
|
+
simsimd_datatype_t datatype, //
|
|
1343
|
+
simsimd_capability_t supported, //
|
|
1344
|
+
simsimd_capability_t allowed, //
|
|
1345
|
+
simsimd_metric_punned_t* metric_output, //
|
|
1346
|
+
simsimd_capability_t* capability_output) {
|
|
1347
|
+
_simsimd_find_metric_punned_implementation(kind, datatype, supported, allowed, metric_output, capability_output);
|
|
1348
|
+
}
|
|
1083
1349
|
// clang-format on
|
|
1084
1350
|
|
|
1085
1351
|
/* Inner products
|
|
@@ -1098,9 +1364,9 @@ SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void) { return simsimd_
|
|
|
1098
1364
|
*/
|
|
1099
1365
|
SIMSIMD_PUBLIC void simsimd_dot_f16(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n,
|
|
1100
1366
|
simsimd_distance_t* d) {
|
|
1101
|
-
#if
|
|
1367
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1102
1368
|
simsimd_dot_f16_sve(a, b, n, d);
|
|
1103
|
-
#elif
|
|
1369
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1104
1370
|
simsimd_dot_f16_neon(a, b, n, d);
|
|
1105
1371
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1106
1372
|
simsimd_dot_f16_sapphire(a, b, n, d);
|
|
@@ -1117,6 +1383,8 @@ SIMSIMD_PUBLIC void simsimd_dot_bf16(simsimd_bf16_t const* a, simsimd_bf16_t con
|
|
|
1117
1383
|
simsimd_dot_bf16_genoa(a, b, n, d);
|
|
1118
1384
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1119
1385
|
simsimd_dot_bf16_haswell(a, b, n, d);
|
|
1386
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1387
|
+
simsimd_dot_bf16_neon(a, b, n, d);
|
|
1120
1388
|
#else
|
|
1121
1389
|
simsimd_dot_bf16_serial(a, b, n, d);
|
|
1122
1390
|
#endif
|
|
@@ -1148,9 +1416,9 @@ SIMSIMD_PUBLIC void simsimd_dot_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1148
1416
|
}
|
|
1149
1417
|
SIMSIMD_PUBLIC void simsimd_dot_f16c(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n,
|
|
1150
1418
|
simsimd_distance_t* d) {
|
|
1151
|
-
#if
|
|
1419
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1152
1420
|
simsimd_dot_f16c_sve(a, b, n, d);
|
|
1153
|
-
#elif
|
|
1421
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1154
1422
|
simsimd_dot_f16c_neon(a, b, n, d);
|
|
1155
1423
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1156
1424
|
simsimd_dot_f16c_sapphire(a, b, n, d);
|
|
@@ -1164,6 +1432,8 @@ SIMSIMD_PUBLIC void simsimd_dot_bf16c(simsimd_bf16_t const* a, simsimd_bf16_t co
|
|
|
1164
1432
|
simsimd_distance_t* d) {
|
|
1165
1433
|
#if SIMSIMD_TARGET_GENOA
|
|
1166
1434
|
simsimd_dot_bf16c_genoa(a, b, n, d);
|
|
1435
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1436
|
+
simsimd_dot_bf16c_neon(a, b, n, d);
|
|
1167
1437
|
#else
|
|
1168
1438
|
simsimd_dot_bf16c_serial(a, b, n, d);
|
|
1169
1439
|
#endif
|
|
@@ -1208,7 +1478,13 @@ SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16_t const* a, simsimd_f16_t cons
|
|
|
1208
1478
|
}
|
|
1209
1479
|
SIMSIMD_PUBLIC void simsimd_vdot_bf16c(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n,
|
|
1210
1480
|
simsimd_distance_t* d) {
|
|
1481
|
+
#if SIMSIMD_TARGET_GENOA
|
|
1482
|
+
simsimd_vdot_bf16c_genoa(a, b, n, d);
|
|
1483
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1484
|
+
simsimd_dot_bf16c_neon(a, b, n, d);
|
|
1485
|
+
#else
|
|
1211
1486
|
simsimd_vdot_bf16c_serial(a, b, n, d);
|
|
1487
|
+
#endif
|
|
1212
1488
|
}
|
|
1213
1489
|
SIMSIMD_PUBLIC void simsimd_vdot_f32c(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n,
|
|
1214
1490
|
simsimd_distance_t* d) {
|
|
@@ -1260,23 +1536,11 @@ SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const* a, simsimd_i8_t const* b,
|
|
|
1260
1536
|
simsimd_cos_i8_serial(a, b, n, d);
|
|
1261
1537
|
#endif
|
|
1262
1538
|
}
|
|
1263
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t n,
|
|
1264
|
-
simsimd_distance_t* d) {
|
|
1265
|
-
#if SIMSIMD_TARGET_NEON
|
|
1266
|
-
simsimd_l2sq_i8_neon(a, b, n, d);
|
|
1267
|
-
#elif SIMSIMD_TARGET_ICE
|
|
1268
|
-
simsimd_l2sq_i8_ice(a, b, n, d);
|
|
1269
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1270
|
-
simsimd_l2sq_i8_haswell(a, b, n, d);
|
|
1271
|
-
#else
|
|
1272
|
-
simsimd_l2sq_i8_serial(a, b, n, d);
|
|
1273
|
-
#endif
|
|
1274
|
-
}
|
|
1275
1539
|
SIMSIMD_PUBLIC void simsimd_cos_f16(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n,
|
|
1276
1540
|
simsimd_distance_t* d) {
|
|
1277
|
-
#if
|
|
1541
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1278
1542
|
simsimd_cos_f16_sve(a, b, n, d);
|
|
1279
|
-
#elif
|
|
1543
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1280
1544
|
simsimd_cos_f16_neon(a, b, n, d);
|
|
1281
1545
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1282
1546
|
simsimd_cos_f16_sapphire(a, b, n, d);
|
|
@@ -1292,6 +1556,10 @@ SIMSIMD_PUBLIC void simsimd_cos_bf16(simsimd_bf16_t const* a, simsimd_bf16_t con
|
|
|
1292
1556
|
simsimd_cos_bf16_genoa(a, b, n, d);
|
|
1293
1557
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1294
1558
|
simsimd_cos_bf16_haswell(a, b, n, d);
|
|
1559
|
+
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1560
|
+
simsimd_cos_bf16_sve(a, b, n, d);
|
|
1561
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1562
|
+
simsimd_cos_bf16_neon(a, b, n, d);
|
|
1295
1563
|
#else
|
|
1296
1564
|
simsimd_cos_bf16_serial(a, b, n, d);
|
|
1297
1565
|
#endif
|
|
@@ -1314,17 +1582,31 @@ SIMSIMD_PUBLIC void simsimd_cos_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1314
1582
|
simsimd_distance_t* d) {
|
|
1315
1583
|
#if SIMSIMD_TARGET_SVE
|
|
1316
1584
|
simsimd_cos_f64_sve(a, b, n, d);
|
|
1585
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1586
|
+
simsimd_cos_f64_neon(a, b, n, d);
|
|
1317
1587
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1318
1588
|
simsimd_cos_f64_skylake(a, b, n, d);
|
|
1319
1589
|
#else
|
|
1320
1590
|
simsimd_cos_f64_serial(a, b, n, d);
|
|
1321
1591
|
#endif
|
|
1322
1592
|
}
|
|
1593
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t n,
|
|
1594
|
+
simsimd_distance_t* d) {
|
|
1595
|
+
#if SIMSIMD_TARGET_NEON
|
|
1596
|
+
simsimd_l2sq_i8_neon(a, b, n, d);
|
|
1597
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1598
|
+
simsimd_l2sq_i8_ice(a, b, n, d);
|
|
1599
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1600
|
+
simsimd_l2sq_i8_haswell(a, b, n, d);
|
|
1601
|
+
#else
|
|
1602
|
+
simsimd_l2sq_i8_serial(a, b, n, d);
|
|
1603
|
+
#endif
|
|
1604
|
+
}
|
|
1323
1605
|
SIMSIMD_PUBLIC void simsimd_l2sq_f16(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n,
|
|
1324
1606
|
simsimd_distance_t* d) {
|
|
1325
|
-
#if
|
|
1607
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1326
1608
|
simsimd_l2sq_f16_sve(a, b, n, d);
|
|
1327
|
-
#elif
|
|
1609
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1328
1610
|
simsimd_l2sq_f16_neon(a, b, n, d);
|
|
1329
1611
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1330
1612
|
simsimd_l2sq_f16_sapphire(a, b, n, d);
|
|
@@ -1340,6 +1622,10 @@ SIMSIMD_PUBLIC void simsimd_l2sq_bf16(simsimd_bf16_t const* a, simsimd_bf16_t co
|
|
|
1340
1622
|
simsimd_l2sq_bf16_genoa(a, b, n, d);
|
|
1341
1623
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1342
1624
|
simsimd_l2sq_bf16_haswell(a, b, n, d);
|
|
1625
|
+
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1626
|
+
simsimd_l2sq_bf16_sve(a, b, n, d);
|
|
1627
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1628
|
+
simsimd_l2sq_bf16_neon(a, b, n, d);
|
|
1343
1629
|
#else
|
|
1344
1630
|
simsimd_l2sq_bf16_serial(a, b, n, d);
|
|
1345
1631
|
#endif
|
|
@@ -1362,12 +1648,80 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const* a, simsimd_f64_t const
|
|
|
1362
1648
|
simsimd_distance_t* d) {
|
|
1363
1649
|
#if SIMSIMD_TARGET_SVE
|
|
1364
1650
|
simsimd_l2sq_f64_sve(a, b, n, d);
|
|
1651
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1652
|
+
simsimd_l2sq_f64_neon(a, b, n, d);
|
|
1365
1653
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1366
1654
|
simsimd_l2sq_f64_skylake(a, b, n, d);
|
|
1367
1655
|
#else
|
|
1368
1656
|
simsimd_l2sq_f64_serial(a, b, n, d);
|
|
1369
1657
|
#endif
|
|
1370
1658
|
}
|
|
1659
|
+
SIMSIMD_PUBLIC void simsimd_l2_i8(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t n,
|
|
1660
|
+
simsimd_distance_t* d) {
|
|
1661
|
+
#if SIMSIMD_TARGET_NEON
|
|
1662
|
+
simsimd_l2_i8_neon(a, b, n, d);
|
|
1663
|
+
#elif SIMSIMD_TARGET_ICE
|
|
1664
|
+
simsimd_l2_i8_ice(a, b, n, d);
|
|
1665
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1666
|
+
simsimd_l2_i8_haswell(a, b, n, d);
|
|
1667
|
+
#else
|
|
1668
|
+
simsimd_l2_i8_serial(a, b, n, d);
|
|
1669
|
+
#endif
|
|
1670
|
+
}
|
|
1671
|
+
SIMSIMD_PUBLIC void simsimd_l2_f16(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n,
|
|
1672
|
+
simsimd_distance_t* d) {
|
|
1673
|
+
#if SIMSIMD_TARGET_SVE_F16
|
|
1674
|
+
simsimd_l2_f16_sve(a, b, n, d);
|
|
1675
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1676
|
+
simsimd_l2_f16_neon(a, b, n, d);
|
|
1677
|
+
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1678
|
+
simsimd_l2_f16_sapphire(a, b, n, d);
|
|
1679
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1680
|
+
simsimd_l2_f16_haswell(a, b, n, d);
|
|
1681
|
+
#else
|
|
1682
|
+
simsimd_l2_f16_serial(a, b, n, d);
|
|
1683
|
+
#endif
|
|
1684
|
+
}
|
|
1685
|
+
SIMSIMD_PUBLIC void simsimd_l2_bf16(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n,
|
|
1686
|
+
simsimd_distance_t* d) {
|
|
1687
|
+
#if SIMSIMD_TARGET_GENOA
|
|
1688
|
+
simsimd_l2_bf16_genoa(a, b, n, d);
|
|
1689
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1690
|
+
simsimd_l2_bf16_haswell(a, b, n, d);
|
|
1691
|
+
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1692
|
+
simsimd_l2_bf16_sve(a, b, n, d);
|
|
1693
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1694
|
+
simsimd_l2_bf16_neon(a, b, n, d);
|
|
1695
|
+
#else
|
|
1696
|
+
simsimd_l2_bf16_serial(a, b, n, d);
|
|
1697
|
+
#endif
|
|
1698
|
+
}
|
|
1699
|
+
SIMSIMD_PUBLIC void simsimd_l2_f32(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n,
|
|
1700
|
+
simsimd_distance_t* d) {
|
|
1701
|
+
#if SIMSIMD_TARGET_SVE
|
|
1702
|
+
simsimd_l2_f32_sve(a, b, n, d);
|
|
1703
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1704
|
+
simsimd_l2_f32_neon(a, b, n, d);
|
|
1705
|
+
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1706
|
+
simsimd_l2_f32_skylake(a, b, n, d);
|
|
1707
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1708
|
+
simsimd_l2_f32_haswell(a, b, n, d);
|
|
1709
|
+
#else
|
|
1710
|
+
simsimd_l2_f32_serial(a, b, n, d);
|
|
1711
|
+
#endif
|
|
1712
|
+
}
|
|
1713
|
+
SIMSIMD_PUBLIC void simsimd_l2_f64(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size_t n,
|
|
1714
|
+
simsimd_distance_t* d) {
|
|
1715
|
+
#if SIMSIMD_TARGET_SVE
|
|
1716
|
+
simsimd_l2_f64_sve(a, b, n, d);
|
|
1717
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1718
|
+
simsimd_l2_f64_neon(a, b, n, d);
|
|
1719
|
+
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1720
|
+
simsimd_l2_f64_skylake(a, b, n, d);
|
|
1721
|
+
#else
|
|
1722
|
+
simsimd_l2_f64_serial(a, b, n, d);
|
|
1723
|
+
#endif
|
|
1724
|
+
}
|
|
1371
1725
|
|
|
1372
1726
|
/* Binary distances
|
|
1373
1727
|
* - Hamming distance: the number of positions at which the corresponding bits are different.
|
|
@@ -1415,9 +1769,9 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const* a, simsimd_b8_t const
|
|
|
1415
1769
|
* - Jensen-Shannon divergence: a measure of similarity between two probability distributions.
|
|
1416
1770
|
* - Kullback-Leibler divergence: a measure of how one probability distribution diverges from a second.
|
|
1417
1771
|
*
|
|
1418
|
-
* @param a The first
|
|
1419
|
-
* @param b The second
|
|
1420
|
-
* @param n The number of elements in the
|
|
1772
|
+
* @param a The first discrete probability distribution.
|
|
1773
|
+
* @param b The second discrete probability distribution.
|
|
1774
|
+
* @param n The number of elements in the discrete distributions.
|
|
1421
1775
|
* @param d The output divergence value.
|
|
1422
1776
|
*
|
|
1423
1777
|
* @note The distributions are assumed to be normalized.
|
|
@@ -1482,6 +1836,126 @@ SIMSIMD_PUBLIC void simsimd_js_f64(simsimd_f64_t const* a, simsimd_f64_t const*
|
|
|
1482
1836
|
simsimd_js_f64_serial(a, b, n, d);
|
|
1483
1837
|
}
|
|
1484
1838
|
|
|
1839
|
+
/* Set operations
|
|
1840
|
+
*
|
|
1841
|
+
* @param a The first sorted array of integers.
|
|
1842
|
+
* @param b The second sorted array of integers.
|
|
1843
|
+
* @param a_length The number of elements in the first array.
|
|
1844
|
+
* @param b_length The number of elements in the second array.
|
|
1845
|
+
* @param d The output for the number of elements in the intersection.
|
|
1846
|
+
*/
|
|
1847
|
+
SIMSIMD_PUBLIC void simsimd_intersect_u16(simsimd_u16_t const* a, simsimd_u16_t const* b, simsimd_size_t a_length,
|
|
1848
|
+
simsimd_size_t b_length, simsimd_distance_t* d) {
|
|
1849
|
+
#if SIMSIMD_TARGET_SVE2
|
|
1850
|
+
simsimd_intersect_u16_sve2(a, b, a_length, b_length, d);
|
|
1851
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1852
|
+
simsimd_intersect_u16_neon(a, b, a_length, b_length, d);
|
|
1853
|
+
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1854
|
+
simsimd_intersect_u16_ice(a, b, a_length, b_length, d);
|
|
1855
|
+
#else
|
|
1856
|
+
simsimd_intersect_u16_serial(a, b, a_length, b_length, d);
|
|
1857
|
+
#endif
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
SIMSIMD_PUBLIC void simsimd_intersect_u32(simsimd_u32_t const* a, simsimd_u32_t const* b, simsimd_size_t a_length,
|
|
1861
|
+
simsimd_size_t b_length, simsimd_distance_t* d) {
|
|
1862
|
+
#if SIMSIMD_TARGET_SVE2
|
|
1863
|
+
simsimd_intersect_u32_sve2(a, b, a_length, b_length, d);
|
|
1864
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1865
|
+
simsimd_intersect_u32_neon(a, b, a_length, b_length, d);
|
|
1866
|
+
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1867
|
+
simsimd_intersect_u32_ice(a, b, a_length, b_length, d);
|
|
1868
|
+
#else
|
|
1869
|
+
simsimd_intersect_u32_serial(a, b, a_length, b_length, d);
|
|
1870
|
+
#endif
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
/* Curved space distances
|
|
1874
|
+
*
|
|
1875
|
+
* @param a The first vector of floating point values.
|
|
1876
|
+
* @param b The second vector of floating point values.
|
|
1877
|
+
* @param c The metric tensor or covariance matrix.
|
|
1878
|
+
* @param n The number of dimensions in the vectors.
|
|
1879
|
+
* @param d The output for the number of elements in the intersection.
|
|
1880
|
+
*/
|
|
1881
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f64(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_f64_t const* c,
|
|
1882
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1883
|
+
|
|
1884
|
+
simsimd_bilinear_f64_serial(a, b, c, n, d);
|
|
1885
|
+
}
|
|
1886
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f64(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_f64_t const* c,
|
|
1887
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1888
|
+
simsimd_mahalanobis_f64_serial(a, b, c, n, d);
|
|
1889
|
+
}
|
|
1890
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f32(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_f32_t const* c,
|
|
1891
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1892
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
1893
|
+
simsimd_bilinear_f32_skylake(a, b, c, n, d);
|
|
1894
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1895
|
+
simsimd_bilinear_f32_neon(a, b, c, n, d);
|
|
1896
|
+
#else
|
|
1897
|
+
simsimd_bilinear_f32_serial(a, b, c, n, d);
|
|
1898
|
+
#endif
|
|
1899
|
+
}
|
|
1900
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_f32_t const* c,
|
|
1901
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1902
|
+
#if SIMSIMD_TARGET_SKYLAKE
|
|
1903
|
+
simsimd_mahalanobis_f32_skylake(a, b, c, n, d);
|
|
1904
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1905
|
+
simsimd_mahalanobis_f32_neon(a, b, c, n, d);
|
|
1906
|
+
#else
|
|
1907
|
+
simsimd_mahalanobis_f32_serial(a, b, c, n, d);
|
|
1908
|
+
#endif
|
|
1909
|
+
}
|
|
1910
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f16(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_f16_t const* c,
|
|
1911
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1912
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
1913
|
+
simsimd_bilinear_f16_sapphire(a, b, c, n, d);
|
|
1914
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1915
|
+
simsimd_bilinear_f16_haswell(a, b, c, n, d);
|
|
1916
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1917
|
+
simsimd_bilinear_f16_neon(a, b, c, n, d);
|
|
1918
|
+
#else
|
|
1919
|
+
simsimd_bilinear_f16_serial(a, b, c, n, d);
|
|
1920
|
+
#endif
|
|
1921
|
+
}
|
|
1922
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_f16_t const* c,
|
|
1923
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1924
|
+
#if SIMSIMD_TARGET_SAPPHIRE
|
|
1925
|
+
simsimd_mahalanobis_f16_sapphire(a, b, c, n, d);
|
|
1926
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1927
|
+
simsimd_mahalanobis_f16_haswell(a, b, c, n, d);
|
|
1928
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1929
|
+
simsimd_mahalanobis_f16_neon(a, b, c, n, d);
|
|
1930
|
+
#else
|
|
1931
|
+
simsimd_mahalanobis_f16_serial(a, b, c, n, d);
|
|
1932
|
+
#endif
|
|
1933
|
+
}
|
|
1934
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_bf16(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_bf16_t const* c,
|
|
1935
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1936
|
+
#if SIMSIMD_TARGET_GENOA
|
|
1937
|
+
simsimd_bilinear_bf16_genoa(a, b, c, n, d);
|
|
1938
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1939
|
+
simsimd_bilinear_bf16_haswell(a, b, c, n, d);
|
|
1940
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1941
|
+
simsimd_bilinear_bf16_neon(a, b, c, n, d);
|
|
1942
|
+
#else
|
|
1943
|
+
simsimd_bilinear_bf16_serial(a, b, c, n, d);
|
|
1944
|
+
#endif
|
|
1945
|
+
}
|
|
1946
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_bf16_t const* c,
|
|
1947
|
+
simsimd_size_t n, simsimd_distance_t* d) {
|
|
1948
|
+
#if SIMSIMD_TARGET_GENOA
|
|
1949
|
+
simsimd_mahalanobis_bf16_genoa(a, b, c, n, d);
|
|
1950
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1951
|
+
simsimd_mahalanobis_bf16_haswell(a, b, c, n, d);
|
|
1952
|
+
#elif SIMSIMD_TARGET_NEON
|
|
1953
|
+
simsimd_mahalanobis_bf16_neon(a, b, c, n, d);
|
|
1954
|
+
#else
|
|
1955
|
+
simsimd_mahalanobis_bf16_serial(a, b, c, n, d);
|
|
1956
|
+
#endif
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1485
1959
|
#endif
|
|
1486
1960
|
|
|
1487
1961
|
#ifdef __cplusplus
|