usearch 2.17.1 → 2.19.5
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 +6 -2
- package/c/lib.cpp +13 -2
- package/c/module.modulemap +4 -0
- package/c/usearch.h +13 -4
- package/cpp/README.md +1 -1
- package/cpp/bench.cpp +2 -2
- package/cpp/test.cpp +110 -16
- package/include/usearch/index.hpp +91 -35
- package/include/usearch/index_dense.hpp +34 -19
- package/include/usearch/index_plugins.hpp +29 -7
- package/javascript/README.md +8 -6
- package/javascript/dist/cjs/usearch.d.ts +9 -4
- package/javascript/dist/cjs/usearch.js +23 -8
- package/javascript/dist/esm/usearch.d.ts +9 -4
- package/javascript/dist/esm/usearch.js +21 -7
- package/javascript/lib.cpp +137 -59
- package/javascript/usearch.test.js +359 -192
- package/javascript/usearch.ts +35 -11
- 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/CONTRIBUTING.md +23 -8
- package/simsimd/Cargo.lock +1 -1
- package/simsimd/Cargo.toml +1 -1
- package/simsimd/README.md +49 -9
- package/simsimd/build.rs +7 -3
- package/simsimd/c/lib.c +6 -1
- package/simsimd/include/simsimd/binary.h +3 -3
- package/simsimd/include/simsimd/dot.h +2 -2
- package/simsimd/include/simsimd/elementwise.h +26 -17
- package/simsimd/include/simsimd/simsimd.h +125 -49
- package/simsimd/include/simsimd/sparse.h +30 -29
- package/simsimd/include/simsimd/spatial.h +4 -3
- package/simsimd/include/simsimd/types.h +19 -8
- package/simsimd/javascript/lib.c +0 -1
- package/simsimd/package-lock.json +411 -362
- package/simsimd/package.json +9 -9
- package/simsimd/rust/lib.rs +63 -29
- package/simsimd/scripts/bench.cxx +13 -0
- package/simsimd/scripts/bench_cosine.rs +8 -0
- package/simsimd/scripts/bench_native.rs +4 -0
- package/simsimd/scripts/bench_sqeuclidean.rs +8 -0
- package/simsimd/scripts/test.c +22 -0
- package/simsimd/scripts/test.py +80 -4
- package/simsimd/swift/SimSIMD.swift +17 -0
- package/simsimd/swift/Test.swift +36 -0
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* @brief SIMD-accelerated Similarity Measures and Distance Functions.
|
|
4
4
|
* @author Ash Vardanian
|
|
5
5
|
* @date March 14, 2023
|
|
6
|
-
* @copyright Copyright (c) 2023
|
|
7
6
|
*
|
|
8
7
|
* References:
|
|
9
8
|
* x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide
|
|
@@ -89,8 +88,8 @@
|
|
|
89
88
|
#define SIMSIMD_H
|
|
90
89
|
|
|
91
90
|
#define SIMSIMD_VERSION_MAJOR 6
|
|
92
|
-
#define SIMSIMD_VERSION_MINOR
|
|
93
|
-
#define SIMSIMD_VERSION_PATCH
|
|
91
|
+
#define SIMSIMD_VERSION_MINOR 4
|
|
92
|
+
#define SIMSIMD_VERSION_PATCH 10
|
|
94
93
|
|
|
95
94
|
/**
|
|
96
95
|
* @brief Removes compile-time dispatching, and replaces it with runtime dispatching.
|
|
@@ -98,7 +97,7 @@
|
|
|
98
97
|
* that runs the program, rather than the most advanced backend supported by the CPU
|
|
99
98
|
* used to compile the library or the downstream application.
|
|
100
99
|
*/
|
|
101
|
-
#
|
|
100
|
+
#if !defined(SIMSIMD_DYNAMIC_DISPATCH)
|
|
102
101
|
#define SIMSIMD_DYNAMIC_DISPATCH (0) // true or false
|
|
103
102
|
#endif
|
|
104
103
|
|
|
@@ -113,7 +112,8 @@
|
|
|
113
112
|
|
|
114
113
|
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
115
114
|
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
116
|
-
#include <
|
|
115
|
+
#include <fenv.h> // `fesetenv` - part of C 99 standard
|
|
116
|
+
#include <sys/sysctl.h> // `sysctlbyname`
|
|
117
117
|
#endif
|
|
118
118
|
|
|
119
119
|
#ifdef __cplusplus
|
|
@@ -255,9 +255,10 @@ typedef void (*simsimd_metric_dense_punned_t)(void const *a, void const *b, sims
|
|
|
255
255
|
* @param[in] b_length Number of scalar words in the second input array.
|
|
256
256
|
* @param[out] d Output value as a double-precision float, generally without decimals.
|
|
257
257
|
*/
|
|
258
|
-
typedef void (*simsimd_metric_sparse_punned_t)(
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
typedef void (*simsimd_metric_sparse_punned_t)( //
|
|
259
|
+
void const *a, void const *b, //
|
|
260
|
+
simsimd_size_t a_length, simsimd_size_t b_length, //
|
|
261
|
+
simsimd_distance_t *d);
|
|
261
262
|
|
|
262
263
|
/**
|
|
263
264
|
* @brief Type-punned function pointer for curved vector spaces and similarity measures.
|
|
@@ -268,8 +269,9 @@ typedef void (*simsimd_metric_sparse_punned_t)(void const *a, void const *b,
|
|
|
268
269
|
* @param[in] n Number of scalar words in the input arrays.
|
|
269
270
|
* @param[out] d Output value as a double-precision float.
|
|
270
271
|
*/
|
|
271
|
-
typedef void (*simsimd_metric_curved_punned_t)(
|
|
272
|
-
|
|
272
|
+
typedef void (*simsimd_metric_curved_punned_t)( //
|
|
273
|
+
void const *a, void const *b, void const *c, //
|
|
274
|
+
simsimd_size_t n, simsimd_distance_t *d);
|
|
273
275
|
|
|
274
276
|
/**
|
|
275
277
|
* @brief Type-punned function pointer for FMA operations on dense vector representations.
|
|
@@ -283,9 +285,9 @@ typedef void (*simsimd_metric_curved_punned_t)(void const *a, void const *b, voi
|
|
|
283
285
|
* @param[in] beta Scaling factor for the third array.
|
|
284
286
|
* @param[out] y Output value in the same precision as the input arrays.
|
|
285
287
|
*/
|
|
286
|
-
typedef void (*simsimd_kernel_fma_punned_t)(
|
|
287
|
-
|
|
288
|
-
|
|
288
|
+
typedef void (*simsimd_kernel_fma_punned_t)( //
|
|
289
|
+
void const *a, void const *b, void const *c, //
|
|
290
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta, void *y);
|
|
289
291
|
|
|
290
292
|
/**
|
|
291
293
|
* @brief Type-punned function pointer for Weighted Sum operations on dense vector representations.
|
|
@@ -298,9 +300,9 @@ typedef void (*simsimd_kernel_fma_punned_t)(void const *a, void const *b, void c
|
|
|
298
300
|
* @param[in] beta Scaling factor for the second array.
|
|
299
301
|
* @param[out] y Output value in the same precision as the input arrays.
|
|
300
302
|
*/
|
|
301
|
-
typedef void (*simsimd_kernel_wsum_punned_t)(
|
|
302
|
-
|
|
303
|
-
|
|
303
|
+
typedef void (*simsimd_kernel_wsum_punned_t)( //
|
|
304
|
+
void const *a, void const *b, //
|
|
305
|
+
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta, void *y);
|
|
304
306
|
|
|
305
307
|
/**
|
|
306
308
|
* @brief Type-punned function pointer for a SimSIMD public interface.
|
|
@@ -319,6 +321,7 @@ SIMSIMD_DYNAMIC void simsimd_find_kernel_punned( //
|
|
|
319
321
|
simsimd_capability_t allowed, //
|
|
320
322
|
simsimd_kernel_punned_t *kernel_output, //
|
|
321
323
|
simsimd_capability_t *capability_output);
|
|
324
|
+
SIMSIMD_DYNAMIC int simsimd_flush_denormals(void);
|
|
322
325
|
#else
|
|
323
326
|
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void);
|
|
324
327
|
SIMSIMD_PUBLIC void simsimd_find_kernel_punned( //
|
|
@@ -328,10 +331,32 @@ SIMSIMD_PUBLIC void simsimd_find_kernel_punned( //
|
|
|
328
331
|
simsimd_capability_t allowed, //
|
|
329
332
|
simsimd_kernel_punned_t *kernel_output, //
|
|
330
333
|
simsimd_capability_t *capability_output);
|
|
334
|
+
SIMSIMD_PUBLIC int simsimd_flush_denormals(void);
|
|
331
335
|
#endif
|
|
332
336
|
|
|
333
337
|
#if _SIMSIMD_TARGET_X86
|
|
334
338
|
|
|
339
|
+
/**
|
|
340
|
+
* @brief Function to flush denormalized numbers to zero on x86 CPUs.
|
|
341
|
+
* @note This should be called on each thread before any SIMD operations to avoid performance penalties.
|
|
342
|
+
* @return 1 if the operation was successful, 0 otherwise.
|
|
343
|
+
*/
|
|
344
|
+
SIMSIMD_PUBLIC int _simsimd_flush_denormals_x86(void) {
|
|
345
|
+
#if defined(_MSC_VER)
|
|
346
|
+
unsigned int mxcsr = _mm_getcsr();
|
|
347
|
+
mxcsr |= 1 << 15; // bit 15 = Flush-To-Zero (FTZ)
|
|
348
|
+
mxcsr |= 1 << 6; // bit 6 = Denormals-Are-Zero (DAZ)
|
|
349
|
+
_mm_setcsr(mxcsr);
|
|
350
|
+
#else // GCC, Clang, ICC
|
|
351
|
+
unsigned int mxcsr;
|
|
352
|
+
__asm__ __volatile__("stmxcsr %0" : "=m"(mxcsr));
|
|
353
|
+
mxcsr |= 1 << 15; // bit 15 = Flush-To-Zero (FTZ)
|
|
354
|
+
mxcsr |= 1 << 6; // bit 6 = Denormals-Are-Zero (DAZ)
|
|
355
|
+
__asm__ __volatile__("ldmxcsr %0" : : "m"(mxcsr));
|
|
356
|
+
#endif
|
|
357
|
+
return 1;
|
|
358
|
+
}
|
|
359
|
+
|
|
335
360
|
/**
|
|
336
361
|
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
337
362
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
@@ -350,17 +375,19 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
|
350
375
|
__cpuidex(info1.array, 1, 0);
|
|
351
376
|
__cpuidex(info7.array, 7, 0);
|
|
352
377
|
__cpuidex(info7sub1.array, 7, 1);
|
|
353
|
-
#else
|
|
354
|
-
__asm__ __volatile__(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
378
|
+
#else // GCC, Clang, ICC
|
|
379
|
+
__asm__ __volatile__( //
|
|
380
|
+
"cpuid"
|
|
381
|
+
: "=a"(info1.named.eax), "=b"(info1.named.ebx), "=c"(info1.named.ecx), "=d"(info1.named.edx)
|
|
382
|
+
: "a"(1), "c"(0));
|
|
383
|
+
__asm__ __volatile__( //
|
|
384
|
+
"cpuid"
|
|
385
|
+
: "=a"(info7.named.eax), "=b"(info7.named.ebx), "=c"(info7.named.ecx), "=d"(info7.named.edx)
|
|
386
|
+
: "a"(7), "c"(0));
|
|
387
|
+
__asm__ __volatile__( //
|
|
388
|
+
"cpuid"
|
|
389
|
+
: "=a"(info7sub1.named.eax), "=b"(info7sub1.named.ebx), "=c"(info7sub1.named.ecx), "=d"(info7sub1.named.edx)
|
|
390
|
+
: "a"(7), "c"(1));
|
|
364
391
|
#endif
|
|
365
392
|
|
|
366
393
|
// Check for AVX2 (Function ID 7, EBX register)
|
|
@@ -400,7 +427,7 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
|
400
427
|
supports_avx512vbmi2 && supports_avx512vpopcntdq;
|
|
401
428
|
unsigned supports_genoa = supports_avx512bf16;
|
|
402
429
|
unsigned supports_sapphire = supports_avx512fp16;
|
|
403
|
-
// We don't want to
|
|
430
|
+
// We don't want to accidentally enable AVX512VP2INTERSECT on Intel Tiger Lake CPUs
|
|
404
431
|
unsigned supports_turin = supports_avx512vp2intersect && supports_avx512bf16;
|
|
405
432
|
unsigned supports_sierra = 0;
|
|
406
433
|
|
|
@@ -427,6 +454,33 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
|
427
454
|
#pragma GCC target("arch=armv8.5-a+sve")
|
|
428
455
|
#pragma clang attribute push(__attribute__((target("arch=armv8.5-a+sve"))), apply_to = function)
|
|
429
456
|
|
|
457
|
+
/**
|
|
458
|
+
* @brief Function to flush denormalized numbers to zero on Arm CPUs.
|
|
459
|
+
* @note This should be called on each thread before any SIMD operations to avoid performance penalties.
|
|
460
|
+
* @note On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
461
|
+
* @return 1 if the operation was successful, 0 otherwise.
|
|
462
|
+
*/
|
|
463
|
+
SIMSIMD_PUBLIC int _simsimd_flush_denormals_arm(void) {
|
|
464
|
+
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
465
|
+
// https://stackoverflow.com/a/19904907/2766161
|
|
466
|
+
// https://stackoverflow.com/a/78252076/2766161
|
|
467
|
+
int is_success = fesetenv(FE_DFL_DISABLE_DENORMS_ENV) == 0;
|
|
468
|
+
return is_success;
|
|
469
|
+
#elif defined(_SIMSIMD_DEFINED_LINUX)
|
|
470
|
+
// For Linux, we can toggle bits in the Floating-point Control Register (FPCR)
|
|
471
|
+
// https://developer.arm.com/documentation/ddi0601/2024-12/AArch64-Registers/FPCR--Floating-point-Control-Register
|
|
472
|
+
uint64_t fpcr;
|
|
473
|
+
__asm__ volatile("mrs %0, fpcr" : "=r"(fpcr));
|
|
474
|
+
fpcr |= (1 << 19); // bit 19 = FZ16 (Flush half-precision to zero)
|
|
475
|
+
fpcr |= (1 << 24); // bit 24 = FZ (Flush subnormals to zero)
|
|
476
|
+
fpcr |= (1 << 25); // bit 25 = DN (Force Default NaN instead of preserving payload)
|
|
477
|
+
__asm__ volatile("msr fpcr, %0" : : "r"(fpcr));
|
|
478
|
+
return 1;
|
|
479
|
+
#else
|
|
480
|
+
return 0;
|
|
481
|
+
#endif
|
|
482
|
+
}
|
|
483
|
+
|
|
430
484
|
/**
|
|
431
485
|
* @brief Function to determine the SIMD capabilities of the current 64-bit Arm machine at @b runtime.
|
|
432
486
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
@@ -474,7 +528,11 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
|
474
528
|
// AdvSIMD, bits [23:20] of ID_AA64PFR0_EL1 can be used to check for `fp16` support
|
|
475
529
|
// - 0b0000: integers, single, double precision arithmetic
|
|
476
530
|
// - 0b0001: includes support for half-precision floating-point arithmetic
|
|
477
|
-
|
|
531
|
+
// - 0b1111: NEON is not supported?!
|
|
532
|
+
// That's a really weird way to encode lack of NEON support, but it's important to
|
|
533
|
+
// check in case we are running on R-profile CPUs.
|
|
534
|
+
unsigned supports_fp16 = ((id_aa64pfr0_el1 >> 20) & 0xF) == 0x1;
|
|
535
|
+
unsigned supports_neon = ((id_aa64pfr0_el1 >> 20) & 0xF) != 0xF;
|
|
478
536
|
|
|
479
537
|
// Now let's unpack the status flags from ID_AA64ZFR0_EL1
|
|
480
538
|
// https://developer.arm.com/documentation/ddi0601/2024-03/AArch64-Registers/ID-AA64ZFR0-EL1--SVE-Feature-ID-Register-0?lang=en
|
|
@@ -490,7 +548,6 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
|
490
548
|
// This value must match the existing indicator obtained from ID_AA64PFR0_EL1:
|
|
491
549
|
unsigned supports_sve2 = ((id_aa64zfr0_el1) & 0xF) >= 1;
|
|
492
550
|
unsigned supports_sve2p1 = ((id_aa64zfr0_el1) & 0xF) >= 2;
|
|
493
|
-
unsigned supports_neon = 1; // NEON is always supported
|
|
494
551
|
|
|
495
552
|
return (simsimd_capability_t)( //
|
|
496
553
|
(simsimd_cap_neon_k * (supports_neon)) | //
|
|
@@ -514,6 +571,23 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
|
514
571
|
|
|
515
572
|
#endif
|
|
516
573
|
|
|
574
|
+
/**
|
|
575
|
+
* @brief Function to flush @b denormalized numbers to zero to avoid performance penalties.
|
|
576
|
+
* @return 1 if the operation was successful, 0 otherwise.
|
|
577
|
+
*
|
|
578
|
+
* When facing denormalized values Fused-Multiply-Add (FMA) operations can be up to 30x slower,
|
|
579
|
+
* as measured on Intel Sapphire Rapids: https://github.com/ashvardanian/ParallelReductionsBenchmark
|
|
580
|
+
*/
|
|
581
|
+
SIMSIMD_PUBLIC int _simsimd_flush_denormals(void) {
|
|
582
|
+
#if _SIMSIMD_TARGET_X86
|
|
583
|
+
return _simsimd_flush_denormals_x86();
|
|
584
|
+
#endif // _SIMSIMD_TARGET_X86
|
|
585
|
+
#if _SIMSIMD_TARGET_ARM
|
|
586
|
+
return _simsimd_flush_denormals_arm();
|
|
587
|
+
#endif // _SIMSIMD_TARGET_ARM
|
|
588
|
+
return 0;
|
|
589
|
+
}
|
|
590
|
+
|
|
517
591
|
/**
|
|
518
592
|
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
519
593
|
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
@@ -533,7 +607,7 @@ SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_implementation(void) {
|
|
|
533
607
|
#pragma clang diagnostic push
|
|
534
608
|
#pragma clang diagnostic ignored "-Wcast-function-type"
|
|
535
609
|
|
|
536
|
-
#ifdef __cplusplus //! option
|
|
610
|
+
#ifdef __cplusplus //! option "-Wvolatile" is valid for C++/ObjC++ but not for C
|
|
537
611
|
#pragma GCC diagnostic ignored "-Wvolatile"
|
|
538
612
|
#pragma clang diagnostic ignored "-Wvolatile"
|
|
539
613
|
#endif
|
|
@@ -1281,6 +1355,7 @@ SIMSIMD_PUBLIC simsimd_kernel_punned_t simsimd_metric_punned( //
|
|
|
1281
1355
|
* @return 1 if the CPU supports the SIMD instruction set, 0 otherwise.
|
|
1282
1356
|
*/
|
|
1283
1357
|
SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
1358
|
+
SIMSIMD_DYNAMIC int simsimd_flush_denormals(void);
|
|
1284
1359
|
SIMSIMD_DYNAMIC int simsimd_uses_dynamic_dispatch(void);
|
|
1285
1360
|
SIMSIMD_DYNAMIC int simsimd_uses_neon(void);
|
|
1286
1361
|
SIMSIMD_DYNAMIC int simsimd_uses_neon_f16(void);
|
|
@@ -1473,6 +1548,7 @@ SIMSIMD_PUBLIC int simsimd_uses_sapphire(void) { return _SIMSIMD_TARGET_X86 && S
|
|
|
1473
1548
|
SIMSIMD_PUBLIC int simsimd_uses_turin(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_TURIN; }
|
|
1474
1549
|
SIMSIMD_PUBLIC int simsimd_uses_sierra(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SIERRA; }
|
|
1475
1550
|
SIMSIMD_PUBLIC int simsimd_uses_dynamic_dispatch(void) { return 0; }
|
|
1551
|
+
SIMSIMD_PUBLIC int simsimd_flush_denormals(void) { return _simsimd_flush_denormals(); }
|
|
1476
1552
|
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void) { return _simsimd_capabilities_implementation(); }
|
|
1477
1553
|
SIMSIMD_PUBLIC void simsimd_find_kernel_punned( //
|
|
1478
1554
|
simsimd_metric_kind_t kind, //
|
|
@@ -1501,7 +1577,7 @@ SIMSIMD_PUBLIC void simsimd_find_kernel_punned( //
|
|
|
1501
1577
|
*/
|
|
1502
1578
|
SIMSIMD_PUBLIC void simsimd_dot_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1503
1579
|
simsimd_distance_t *d) {
|
|
1504
|
-
#if
|
|
1580
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
1505
1581
|
simsimd_dot_i8_neon(a, b, n, d);
|
|
1506
1582
|
#elif SIMSIMD_TARGET_ICE
|
|
1507
1583
|
simsimd_dot_i8_ice(a, b, n, d);
|
|
@@ -1625,7 +1701,7 @@ SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16c_t const *a, simsimd_f16c_t co
|
|
|
1625
1701
|
simsimd_distance_t *d) {
|
|
1626
1702
|
#if SIMSIMD_TARGET_SVE
|
|
1627
1703
|
simsimd_vdot_f16c_sve(a, b, n, d);
|
|
1628
|
-
#elif
|
|
1704
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
1629
1705
|
simsimd_dot_f16c_neon(a, b, n, d);
|
|
1630
1706
|
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1631
1707
|
simsimd_dot_f16c_sapphire(a, b, n, d);
|
|
@@ -1685,7 +1761,7 @@ SIMSIMD_PUBLIC void simsimd_vdot_f64c(simsimd_f64c_t const *a, simsimd_f64c_t co
|
|
|
1685
1761
|
*/
|
|
1686
1762
|
SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1687
1763
|
simsimd_distance_t *d) {
|
|
1688
|
-
#if
|
|
1764
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
1689
1765
|
simsimd_cos_i8_neon(a, b, n, d);
|
|
1690
1766
|
#elif SIMSIMD_TARGET_ICE
|
|
1691
1767
|
simsimd_cos_i8_ice(a, b, n, d);
|
|
@@ -1697,7 +1773,7 @@ SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const *a, simsimd_i8_t const *b,
|
|
|
1697
1773
|
}
|
|
1698
1774
|
SIMSIMD_PUBLIC void simsimd_cos_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1699
1775
|
simsimd_distance_t *d) {
|
|
1700
|
-
#if
|
|
1776
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
1701
1777
|
simsimd_cos_u8_neon(a, b, n, d);
|
|
1702
1778
|
#elif SIMSIMD_TARGET_ICE
|
|
1703
1779
|
simsimd_cos_u8_ice(a, b, n, d);
|
|
@@ -1763,7 +1839,7 @@ SIMSIMD_PUBLIC void simsimd_cos_f64(simsimd_f64_t const *a, simsimd_f64_t const
|
|
|
1763
1839
|
}
|
|
1764
1840
|
SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1765
1841
|
simsimd_distance_t *d) {
|
|
1766
|
-
#if
|
|
1842
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
1767
1843
|
simsimd_l2sq_i8_neon(a, b, n, d);
|
|
1768
1844
|
#elif SIMSIMD_TARGET_ICE
|
|
1769
1845
|
simsimd_l2sq_i8_ice(a, b, n, d);
|
|
@@ -1775,7 +1851,7 @@ SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const *a, simsimd_i8_t const *b
|
|
|
1775
1851
|
}
|
|
1776
1852
|
SIMSIMD_PUBLIC void simsimd_l2sq_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1777
1853
|
simsimd_distance_t *d) {
|
|
1778
|
-
#if
|
|
1854
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
1779
1855
|
simsimd_l2sq_u8_neon(a, b, n, d);
|
|
1780
1856
|
#elif SIMSIMD_TARGET_ICE
|
|
1781
1857
|
simsimd_l2sq_u8_ice(a, b, n, d);
|
|
@@ -1841,7 +1917,7 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const *a, simsimd_f64_t const
|
|
|
1841
1917
|
}
|
|
1842
1918
|
SIMSIMD_PUBLIC void simsimd_l2_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1843
1919
|
simsimd_distance_t *d) {
|
|
1844
|
-
#if
|
|
1920
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
1845
1921
|
simsimd_l2_i8_neon(a, b, n, d);
|
|
1846
1922
|
#elif SIMSIMD_TARGET_ICE
|
|
1847
1923
|
simsimd_l2_i8_ice(a, b, n, d);
|
|
@@ -1853,7 +1929,7 @@ SIMSIMD_PUBLIC void simsimd_l2_i8(simsimd_i8_t const *a, simsimd_i8_t const *b,
|
|
|
1853
1929
|
}
|
|
1854
1930
|
SIMSIMD_PUBLIC void simsimd_l2_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1855
1931
|
simsimd_distance_t *d) {
|
|
1856
|
-
#if
|
|
1932
|
+
#if SIMSIMD_TARGET_NEON_I8
|
|
1857
1933
|
simsimd_l2_u8_neon(a, b, n, d);
|
|
1858
1934
|
#elif SIMSIMD_TARGET_ICE
|
|
1859
1935
|
simsimd_l2_u8_ice(a, b, n, d);
|
|
@@ -1976,7 +2052,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const *a, simsimd_b8_t const
|
|
|
1976
2052
|
*/
|
|
1977
2053
|
SIMSIMD_PUBLIC void simsimd_kl_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1978
2054
|
simsimd_distance_t *d) {
|
|
1979
|
-
#if
|
|
2055
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
1980
2056
|
simsimd_kl_f16_neon(a, b, n, d);
|
|
1981
2057
|
#elif SIMSIMD_TARGET_HASWELL
|
|
1982
2058
|
simsimd_kl_f16_haswell(a, b, n, d);
|
|
@@ -2004,7 +2080,7 @@ SIMSIMD_PUBLIC void simsimd_kl_f64(simsimd_f64_t const *a, simsimd_f64_t const *
|
|
|
2004
2080
|
}
|
|
2005
2081
|
SIMSIMD_PUBLIC void simsimd_js_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
2006
2082
|
simsimd_distance_t *d) {
|
|
2007
|
-
#if
|
|
2083
|
+
#if SIMSIMD_TARGET_NEON_F16
|
|
2008
2084
|
simsimd_js_f16_neon(a, b, n, d);
|
|
2009
2085
|
#elif SIMSIMD_TARGET_HASWELL
|
|
2010
2086
|
simsimd_js_f16_haswell(a, b, n, d);
|
|
@@ -2135,7 +2211,7 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16(simsimd_f16_t const *a, simsimd_f16_t c
|
|
|
2135
2211
|
simsimd_bilinear_f16_sapphire(a, b, c, n, d);
|
|
2136
2212
|
#elif SIMSIMD_TARGET_HASWELL
|
|
2137
2213
|
simsimd_bilinear_f16_haswell(a, b, c, n, d);
|
|
2138
|
-
#elif
|
|
2214
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2139
2215
|
simsimd_bilinear_f16_neon(a, b, c, n, d);
|
|
2140
2216
|
#else
|
|
2141
2217
|
simsimd_bilinear_f16_serial(a, b, c, n, d);
|
|
@@ -2147,7 +2223,7 @@ SIMSIMD_PUBLIC void simsimd_bilinear_bf16(simsimd_bf16_t const *a, simsimd_bf16_
|
|
|
2147
2223
|
simsimd_bilinear_bf16_genoa(a, b, c, n, d);
|
|
2148
2224
|
#elif SIMSIMD_TARGET_HASWELL
|
|
2149
2225
|
simsimd_bilinear_bf16_haswell(a, b, c, n, d);
|
|
2150
|
-
#elif
|
|
2226
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2151
2227
|
simsimd_bilinear_bf16_neon(a, b, c, n, d);
|
|
2152
2228
|
#else
|
|
2153
2229
|
simsimd_bilinear_bf16_serial(a, b, c, n, d);
|
|
@@ -2175,7 +2251,7 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16c(simsimd_f16c_t const *a, simsimd_f16c_
|
|
|
2175
2251
|
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2176
2252
|
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2177
2253
|
simsimd_bilinear_f16c_sapphire(a, b, c, n, d);
|
|
2178
|
-
#elif
|
|
2254
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2179
2255
|
simsimd_bilinear_f16c_neon(a, b, c, n, d);
|
|
2180
2256
|
#else
|
|
2181
2257
|
simsimd_bilinear_f16c_serial(a, b, c, n, d);
|
|
@@ -2185,7 +2261,7 @@ SIMSIMD_PUBLIC void simsimd_bilinear_bf16c(simsimd_bf16c_t const *a, simsimd_bf1
|
|
|
2185
2261
|
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2186
2262
|
#if SIMSIMD_TARGET_GENOA
|
|
2187
2263
|
simsimd_bilinear_bf16c_genoa(a, b, c, n, d);
|
|
2188
|
-
#elif
|
|
2264
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2189
2265
|
simsimd_bilinear_bf16c_neon(a, b, c, n, d);
|
|
2190
2266
|
#else
|
|
2191
2267
|
simsimd_bilinear_bf16c_serial(a, b, c, n, d);
|
|
@@ -2215,7 +2291,7 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16(simsimd_f16_t const *a, simsimd_f16_
|
|
|
2215
2291
|
simsimd_mahalanobis_f16_sapphire(a, b, c, n, d);
|
|
2216
2292
|
#elif SIMSIMD_TARGET_HASWELL
|
|
2217
2293
|
simsimd_mahalanobis_f16_haswell(a, b, c, n, d);
|
|
2218
|
-
#elif
|
|
2294
|
+
#elif SIMSIMD_TARGET_NEON_F16
|
|
2219
2295
|
simsimd_mahalanobis_f16_neon(a, b, c, n, d);
|
|
2220
2296
|
#else
|
|
2221
2297
|
simsimd_mahalanobis_f16_serial(a, b, c, n, d);
|
|
@@ -2227,7 +2303,7 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16(simsimd_bf16_t const *a, simsimd_bf
|
|
|
2227
2303
|
simsimd_mahalanobis_bf16_genoa(a, b, c, n, d);
|
|
2228
2304
|
#elif SIMSIMD_TARGET_HASWELL
|
|
2229
2305
|
simsimd_mahalanobis_bf16_haswell(a, b, c, n, d);
|
|
2230
|
-
#elif
|
|
2306
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2231
2307
|
simsimd_mahalanobis_bf16_neon(a, b, c, n, d);
|
|
2232
2308
|
#else
|
|
2233
2309
|
simsimd_mahalanobis_bf16_serial(a, b, c, n, d);
|
|
@@ -2274,7 +2350,7 @@ SIMSIMD_PUBLIC void simsimd_wsum_bf16(simsimd_bf16_t const *a, simsimd_bf16_t co
|
|
|
2274
2350
|
simsimd_wsum_bf16_skylake(a, b, n, alpha, beta, r);
|
|
2275
2351
|
#elif SIMSIMD_TARGET_HASWELL
|
|
2276
2352
|
simsimd_wsum_bf16_haswell(a, b, n, alpha, beta, r);
|
|
2277
|
-
#elif
|
|
2353
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2278
2354
|
simsimd_wsum_bf16_neon(a, b, n, alpha, beta, r);
|
|
2279
2355
|
#else
|
|
2280
2356
|
simsimd_wsum_bf16_serial(a, b, n, alpha, beta, r);
|
|
@@ -2353,7 +2429,7 @@ SIMSIMD_PUBLIC void simsimd_fma_bf16(simsimd_bf16_t const *a, simsimd_bf16_t con
|
|
|
2353
2429
|
simsimd_fma_bf16_skylake(a, b, c, n, alpha, beta, r);
|
|
2354
2430
|
#elif SIMSIMD_TARGET_HASWELL
|
|
2355
2431
|
simsimd_fma_bf16_haswell(a, b, c, n, alpha, beta, r);
|
|
2356
|
-
#elif
|
|
2432
|
+
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2357
2433
|
simsimd_fma_bf16_neon(a, b, c, n, alpha, beta, r);
|
|
2358
2434
|
#else
|
|
2359
2435
|
simsimd_fma_bf16_serial(a, b, c, n, alpha, beta, r);
|
|
@@ -187,8 +187,8 @@ SIMSIMD_MAKE_INTERSECT_LINEAR(accurate, u32, size) // simsimd_intersect_u32_accu
|
|
|
187
187
|
simsimd_##input_type##_t ai = a[i]; \
|
|
188
188
|
simsimd_##input_type##_t bj = b[j]; \
|
|
189
189
|
int matches = ai == bj; \
|
|
190
|
-
simsimd_##
|
|
191
|
-
simsimd_##
|
|
190
|
+
simsimd_##accumulator_type##_t awi = load_and_convert(a_weights + i); \
|
|
191
|
+
simsimd_##accumulator_type##_t bwi = load_and_convert(b_weights + i); \
|
|
192
192
|
weights_product += matches * awi * bwi; \
|
|
193
193
|
intersection_size += matches; \
|
|
194
194
|
i += ai < bj; \
|
|
@@ -435,6 +435,13 @@ SIMSIMD_PUBLIC void simsimd_intersect_u16_ice( //
|
|
|
435
435
|
}
|
|
436
436
|
b_min = b_vec.u16[0];
|
|
437
437
|
|
|
438
|
+
__m512i a_last_broadcasted = _mm512_set1_epi16(*(short const *)&a_max);
|
|
439
|
+
__m512i b_last_broadcasted = _mm512_set1_epi16(*(short const *)&b_max);
|
|
440
|
+
__mmask32 a_step_mask = _mm512_cmple_epu16_mask(a_vec.zmm, b_last_broadcasted);
|
|
441
|
+
__mmask32 b_step_mask = _mm512_cmple_epu16_mask(b_vec.zmm, a_last_broadcasted);
|
|
442
|
+
a += 32 - _lzcnt_u32((simsimd_u32_t)a_step_mask);
|
|
443
|
+
b += 32 - _lzcnt_u32((simsimd_u32_t)b_step_mask);
|
|
444
|
+
|
|
438
445
|
// Now we are likely to have some overlap, so we can intersect the registers
|
|
439
446
|
__mmask32 a_matches = _simsimd_intersect_u16x32_ice(a_vec.zmm, b_vec.zmm);
|
|
440
447
|
|
|
@@ -442,13 +449,6 @@ SIMSIMD_PUBLIC void simsimd_intersect_u16_ice( //
|
|
|
442
449
|
// but we don't need it here:
|
|
443
450
|
// _mm512_mask_compressstoreu_epi16(c, a_matches, a_vec);
|
|
444
451
|
c += _mm_popcnt_u32(a_matches); // MSVC has no `_popcnt32`
|
|
445
|
-
|
|
446
|
-
__m512i a_last_broadcasted = _mm512_set1_epi16(*(short const *)&a_max);
|
|
447
|
-
__m512i b_last_broadcasted = _mm512_set1_epi16(*(short const *)&b_max);
|
|
448
|
-
__mmask32 a_step_mask = _mm512_cmple_epu16_mask(a_vec.zmm, b_last_broadcasted);
|
|
449
|
-
__mmask32 b_step_mask = _mm512_cmple_epu16_mask(b_vec.zmm, a_last_broadcasted);
|
|
450
|
-
a += 32 - _lzcnt_u32((simsimd_u32_t)a_step_mask);
|
|
451
|
-
b += 32 - _lzcnt_u32((simsimd_u32_t)b_step_mask);
|
|
452
452
|
}
|
|
453
453
|
|
|
454
454
|
simsimd_intersect_u16_serial(a, b, a_end - a, b_end - b, results);
|
|
@@ -500,6 +500,13 @@ SIMSIMD_PUBLIC void simsimd_intersect_u32_ice( //
|
|
|
500
500
|
}
|
|
501
501
|
b_min = b_vec.u32[0];
|
|
502
502
|
|
|
503
|
+
__m512i a_last_broadcasted = _mm512_set1_epi32(*(int const *)&a_max);
|
|
504
|
+
__m512i b_last_broadcasted = _mm512_set1_epi32(*(int const *)&b_max);
|
|
505
|
+
__mmask16 a_step_mask = _mm512_cmple_epu32_mask(a_vec.zmm, b_last_broadcasted);
|
|
506
|
+
__mmask16 b_step_mask = _mm512_cmple_epu32_mask(b_vec.zmm, a_last_broadcasted);
|
|
507
|
+
a += 32 - _lzcnt_u32((simsimd_u32_t)a_step_mask);
|
|
508
|
+
b += 32 - _lzcnt_u32((simsimd_u32_t)b_step_mask);
|
|
509
|
+
|
|
503
510
|
// Now we are likely to have some overlap, so we can intersect the registers
|
|
504
511
|
__mmask16 a_matches = _simsimd_intersect_u32x16_ice(a_vec.zmm, b_vec.zmm);
|
|
505
512
|
|
|
@@ -507,13 +514,6 @@ SIMSIMD_PUBLIC void simsimd_intersect_u32_ice( //
|
|
|
507
514
|
// but we don't need it here:
|
|
508
515
|
// _mm512_mask_compressstoreu_epi32(c, a_matches, a_vec);
|
|
509
516
|
c += _mm_popcnt_u32(a_matches); // MSVC has no `_popcnt32`
|
|
510
|
-
|
|
511
|
-
__m512i a_last_broadcasted = _mm512_set1_epi32(*(int const *)&a_max);
|
|
512
|
-
__m512i b_last_broadcasted = _mm512_set1_epi32(*(int const *)&b_max);
|
|
513
|
-
__mmask16 a_step_mask = _mm512_cmple_epu32_mask(a_vec.zmm, b_last_broadcasted);
|
|
514
|
-
__mmask16 b_step_mask = _mm512_cmple_epu32_mask(b_vec.zmm, a_last_broadcasted);
|
|
515
|
-
a += 32 - _lzcnt_u32((simsimd_u32_t)a_step_mask);
|
|
516
|
-
b += 32 - _lzcnt_u32((simsimd_u32_t)b_step_mask);
|
|
517
517
|
}
|
|
518
518
|
|
|
519
519
|
simsimd_intersect_u32_serial(a, b, a_end - a, b_end - b, results);
|
|
@@ -527,10 +527,10 @@ SIMSIMD_PUBLIC void simsimd_intersect_u32_ice( //
|
|
|
527
527
|
#if SIMSIMD_TARGET_TURIN
|
|
528
528
|
#pragma GCC push_options
|
|
529
529
|
#pragma GCC target("avx2", "avx512f", "avx512vl", "bmi2", "lzcnt", "popcnt", "avx512bw", "avx512vbmi2", "avx512bf16", \
|
|
530
|
-
"avx512vnni", "avx512vp2intersect")
|
|
531
|
-
#pragma clang attribute push(
|
|
532
|
-
__attribute__((target(
|
|
533
|
-
"avx2,avx512f,avx512vl,bmi2,lzcnt,popcnt,avx512bw,avx512vbmi2,avx512bf16,avx512vnni,avx512vp2intersect"))), \
|
|
530
|
+
"avx512vnni", "avx512vp2intersect", "avx512dq")
|
|
531
|
+
#pragma clang attribute push( \
|
|
532
|
+
__attribute__((target( \
|
|
533
|
+
"avx2,avx512f,avx512vl,bmi2,lzcnt,popcnt,avx512bw,avx512vbmi2,avx512bf16,avx512vnni,avx512vp2intersect,avx512dq"))), \
|
|
534
534
|
apply_to = function)
|
|
535
535
|
|
|
536
536
|
SIMSIMD_PUBLIC void simsimd_intersect_u16_turin( //
|
|
@@ -678,7 +678,7 @@ SIMSIMD_PUBLIC void simsimd_spdot_weights_u16_turin( //
|
|
|
678
678
|
|
|
679
679
|
// The baseline implementation for very small arrays (2 registers or less) can be quite simple:
|
|
680
680
|
if (a_length < 64 && b_length < 64) {
|
|
681
|
-
|
|
681
|
+
simsimd_spdot_weights_u16_serial(a, b, a_weights, b_weights, a_length, b_length, results);
|
|
682
682
|
return;
|
|
683
683
|
}
|
|
684
684
|
|
|
@@ -751,9 +751,9 @@ SIMSIMD_PUBLIC void simsimd_spdot_weights_u16_turin( //
|
|
|
751
751
|
a += a_step, a_weights += a_step;
|
|
752
752
|
b += b_step, b_weights += b_step;
|
|
753
753
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
754
|
+
simsimd_spdot_weights_u16_serial(a, b, a_weights, b_weights, a_end - a, b_end - b, results);
|
|
755
|
+
results[0] += intersection_size;
|
|
756
|
+
results[1] += _mm512_reduce_add_ps(_mm512_insertf32x8(_mm512_setzero_ps(), product_vec.ymmps, 0));
|
|
757
757
|
}
|
|
758
758
|
|
|
759
759
|
SIMSIMD_PUBLIC void simsimd_spdot_counts_u16_turin( //
|
|
@@ -764,7 +764,7 @@ SIMSIMD_PUBLIC void simsimd_spdot_counts_u16_turin( //
|
|
|
764
764
|
|
|
765
765
|
// The baseline implementation for very small arrays (2 registers or less) can be quite simple:
|
|
766
766
|
if (a_length < 64 && b_length < 64) {
|
|
767
|
-
|
|
767
|
+
simsimd_spdot_counts_u16_serial(a, b, a_weights, b_weights, a_length, b_length, results);
|
|
768
768
|
return;
|
|
769
769
|
}
|
|
770
770
|
|
|
@@ -837,8 +837,9 @@ SIMSIMD_PUBLIC void simsimd_spdot_counts_u16_turin( //
|
|
|
837
837
|
b += b_step, b_weights += b_step;
|
|
838
838
|
}
|
|
839
839
|
|
|
840
|
-
|
|
841
|
-
|
|
840
|
+
simsimd_spdot_counts_u16_serial(a, b, a_weights, b_weights, a_end - a, b_end - b, results);
|
|
841
|
+
results[0] += intersection_size;
|
|
842
|
+
results[1] += _mm512_reduce_add_epi32(_mm512_inserti64x4(_mm512_setzero_si512(), product_vec.ymm, 0));
|
|
842
843
|
}
|
|
843
844
|
|
|
844
845
|
#pragma clang attribute pop
|
|
@@ -849,8 +850,8 @@ SIMSIMD_PUBLIC void simsimd_spdot_counts_u16_turin( //
|
|
|
849
850
|
#if _SIMSIMD_TARGET_ARM
|
|
850
851
|
#if SIMSIMD_TARGET_NEON
|
|
851
852
|
#pragma GCC push_options
|
|
852
|
-
#pragma GCC target("arch=armv8
|
|
853
|
-
#pragma clang attribute push(__attribute__((target("arch=armv8
|
|
853
|
+
#pragma GCC target("arch=armv8-a")
|
|
854
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8-a"))), apply_to = function)
|
|
854
855
|
|
|
855
856
|
/**
|
|
856
857
|
* @brief Uses `vshrn` to produce a bitmask, similar to `movemask` in SSE.
|
|
@@ -263,8 +263,8 @@ SIMSIMD_MAKE_L2(accurate, bf16, f64, SIMSIMD_BF16_TO_F32) // simsimd_l2_bf16_a
|
|
|
263
263
|
#if _SIMSIMD_TARGET_ARM
|
|
264
264
|
#if SIMSIMD_TARGET_NEON
|
|
265
265
|
#pragma GCC push_options
|
|
266
|
-
#pragma GCC target("arch=armv8
|
|
267
|
-
#pragma clang attribute push(__attribute__((target("arch=armv8
|
|
266
|
+
#pragma GCC target("arch=armv8-a+simd")
|
|
267
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8-a+simd"))), apply_to = function)
|
|
268
268
|
|
|
269
269
|
SIMSIMD_INTERNAL simsimd_f32_t _simsimd_sqrt_f32_neon(simsimd_f32_t x) {
|
|
270
270
|
return vget_lane_f32(vsqrt_f32(vdup_n_f32(x)), 0);
|
|
@@ -970,7 +970,7 @@ SIMSIMD_PUBLIC void simsimd_l2sq_bf16_sve(simsimd_bf16_t const *a_enum, simsimd_
|
|
|
970
970
|
svfloat32_t a_minus_b_low_vec = svsub_f32_x(pg_low_vec, a_low_vec, b_low_vec);
|
|
971
971
|
svfloat32_t a_minus_b_high_vec = svsub_f32_x(pg_high_vec, a_high_vec, b_high_vec);
|
|
972
972
|
d2_low_vec = svmla_f32_x(pg_vec, d2_low_vec, a_minus_b_low_vec, a_minus_b_low_vec);
|
|
973
|
-
d2_high_vec = svmla_f32_x(pg_vec, d2_high_vec,
|
|
973
|
+
d2_high_vec = svmla_f32_x(pg_vec, d2_high_vec, a_minus_b_high_vec, a_minus_b_high_vec);
|
|
974
974
|
i += svcnth();
|
|
975
975
|
} while (i < n);
|
|
976
976
|
simsimd_f32_t d2 = svaddv_f32(svptrue_b32(), d2_low_vec) + svaddv_f32(svptrue_b32(), d2_high_vec);
|
|
@@ -2278,6 +2278,7 @@ simsimd_cos_i4x2_ice_cycle:
|
|
|
2278
2278
|
int ab = _mm512_reduce_add_epi32(_mm512_add_epi32(ab_i32_low_vec, ab_i32_high_vec));
|
|
2279
2279
|
unsigned short a2_u16[32], b2_u16[32];
|
|
2280
2280
|
_mm512_storeu_si512(a2_u16, _mm512_add_epi16(a2_u16_low_vec, a2_u16_high_vec));
|
|
2281
|
+
_mm512_storeu_si512(b2_u16, _mm512_add_epi16(b2_u16_low_vec, b2_u16_high_vec));
|
|
2281
2282
|
unsigned int a2 = 0, b2 = 0;
|
|
2282
2283
|
for (int i = 0; i < 32; ++i) a2 += a2_u16[i], b2 += b2_u16[i];
|
|
2283
2284
|
*result = _simsimd_cos_normalize_f32_haswell(ab, a2, b2);
|