usearch 2.8.0 → 2.8.2
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/.github/workflows/release.yml +9 -1
- package/CITATION.cff +1 -1
- package/Cargo.toml +1 -1
- package/README.md +1 -1
- package/conanfile.py +1 -1
- package/csharp/nuget/nuget-package.props +1 -1
- package/include/usearch/index.hpp +1 -1
- package/package.json +1 -1
- package/pyproject.toml +10 -8
- package/rust/lib.rs +1 -0
- package/simsimd/.github/workflows/prerelease.yml +20 -11
- package/simsimd/.github/workflows/release.yml +24 -8
- package/simsimd/CMakeLists.txt +2 -2
- package/simsimd/README.md +1 -1
- package/simsimd/cpp/bench.cxx +11 -6
- package/simsimd/include/simsimd/binary.h +36 -22
- package/simsimd/include/simsimd/probability.h +94 -70
- package/simsimd/include/simsimd/simsimd.h +30 -21
- package/simsimd/include/simsimd/spatial.h +199 -117
- package/simsimd/package-ci.json +10 -0
- package/simsimd/package.json +1 -5
- package/simsimd/python/lib.c +1 -0
- package/simsimd/python/test.py +47 -22
- package/wasmer.toml +1 -1
|
@@ -370,58 +370,70 @@ simsimd_avx512_f32_log2(__m512 x) {
|
|
|
370
370
|
return _mm512_add_ps(_mm512_mul_ps(p, _mm512_sub_ps(m, one)), e);
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
-
__attribute__((target("avx512f,avx512vl"))) //
|
|
373
|
+
__attribute__((target("avx512f,avx512vl,bmi2"))) //
|
|
374
374
|
inline static simsimd_f32_t
|
|
375
375
|
simsimd_avx512_f32_kl(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
|
|
376
376
|
__m512 sum_vec = _mm512_set1_ps(0);
|
|
377
377
|
simsimd_f32_t epsilon = 1e-6;
|
|
378
378
|
__m512 epsilon_vec = _mm512_set1_ps(epsilon);
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
379
|
+
__m512 a_vec, b_vec;
|
|
380
|
+
|
|
381
|
+
simsimd_avx512_f32_kl_cycle:
|
|
382
|
+
if (n < 16) {
|
|
383
|
+
__mmask16 mask = _bzhi_u32(0xFFFFFFFF, n);
|
|
384
|
+
a_vec = _mm512_add_ps(_mm512_maskz_loadu_ps(mask, a), epsilon_vec);
|
|
385
|
+
b_vec = _mm512_add_ps(_mm512_maskz_loadu_ps(mask, b), epsilon_vec);
|
|
386
|
+
n = 0;
|
|
387
|
+
} else {
|
|
388
|
+
a_vec = _mm512_add_ps(_mm512_loadu_ps(a), epsilon_vec);
|
|
389
|
+
b_vec = _mm512_add_ps(_mm512_loadu_ps(b), epsilon_vec);
|
|
390
|
+
a += 16, b += 16, n -= 16;
|
|
387
391
|
}
|
|
392
|
+
__m512 ratio_vec = _mm512_div_ps(a_vec, b_vec);
|
|
393
|
+
__m512 log_ratio_vec = simsimd_avx512_f32_log2(ratio_vec);
|
|
394
|
+
__m512 prod_vec = _mm512_mul_ps(a_vec, log_ratio_vec);
|
|
395
|
+
sum_vec = _mm512_add_ps(sum_vec, prod_vec);
|
|
396
|
+
if (n)
|
|
397
|
+
goto simsimd_avx512_f32_kl_cycle;
|
|
398
|
+
|
|
388
399
|
simsimd_f32_t log2_normalizer = 0.693147181f;
|
|
389
400
|
return _mm512_reduce_add_ps(sum_vec) * log2_normalizer;
|
|
390
401
|
}
|
|
391
402
|
|
|
392
|
-
__attribute__((target("avx512f,avx512vl"))) //
|
|
403
|
+
__attribute__((target("avx512f,avx512vl,bmi2"))) //
|
|
393
404
|
inline static simsimd_f32_t
|
|
394
405
|
simsimd_avx512_f32_js(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
|
|
395
406
|
__m512 sum_a_vec = _mm512_set1_ps(0);
|
|
396
407
|
__m512 sum_b_vec = _mm512_set1_ps(0);
|
|
397
408
|
simsimd_f32_t epsilon = 1e-6;
|
|
398
409
|
__m512 epsilon_vec = _mm512_set1_ps(epsilon);
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
// Division is an expensive operation. Instead of doing it twice,
|
|
412
|
-
// we can approximate the reciprocal of `m` and multiply instead.
|
|
413
|
-
__m512 m_recip_approx = _mm512_rcp14_ps(m_vec); // or `_mm512_rcp28_ps` for slightly better precision
|
|
414
|
-
__m512 ratio_a_vec = _mm512_mul_ps(a_vec, m_recip_approx);
|
|
415
|
-
__m512 ratio_b_vec = _mm512_mul_ps(b_vec, m_recip_approx);
|
|
416
|
-
|
|
417
|
-
// The natural logarithm is equivalent to `log2`, multiplied by the `loge(2)`
|
|
418
|
-
__m512 log_ratio_a_vec = simsimd_avx512_f32_log2(ratio_a_vec);
|
|
419
|
-
__m512 log_ratio_b_vec = simsimd_avx512_f32_log2(ratio_b_vec);
|
|
420
|
-
|
|
421
|
-
// Instead of separate multiplication and addition, invoke the FMA
|
|
422
|
-
sum_a_vec = _mm512_maskz_fmadd_ps(nonzero_mask, a_vec, log_ratio_a_vec, sum_a_vec);
|
|
423
|
-
sum_b_vec = _mm512_maskz_fmadd_ps(nonzero_mask, b_vec, log_ratio_b_vec, sum_b_vec);
|
|
410
|
+
__m512 a_vec, b_vec;
|
|
411
|
+
|
|
412
|
+
simsimd_avx512_f32_js_cycle:
|
|
413
|
+
if (n < 16) {
|
|
414
|
+
__mmask16 mask = _bzhi_u32(0xFFFFFFFF, n);
|
|
415
|
+
a_vec = _mm512_maskz_loadu_ps(mask, a);
|
|
416
|
+
b_vec = _mm512_maskz_loadu_ps(mask, b);
|
|
417
|
+
n = 0;
|
|
418
|
+
} else {
|
|
419
|
+
a_vec = _mm512_loadu_ps(a);
|
|
420
|
+
b_vec = _mm512_loadu_ps(b);
|
|
421
|
+
a += 16, b += 16, n -= 16;
|
|
424
422
|
}
|
|
423
|
+
__m512 m_vec = _mm512_mul_ps(_mm512_add_ps(a_vec, b_vec), _mm512_set1_ps(0.5f));
|
|
424
|
+
__mmask16 nonzero_mask_a = _mm512_cmp_ps_mask(a_vec, epsilon_vec, _CMP_GE_OQ);
|
|
425
|
+
__mmask16 nonzero_mask_b = _mm512_cmp_ps_mask(b_vec, epsilon_vec, _CMP_GE_OQ);
|
|
426
|
+
__mmask16 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
|
|
427
|
+
__m512 m_recip_approx = _mm512_rcp14_ps(m_vec);
|
|
428
|
+
__m512 ratio_a_vec = _mm512_mul_ps(a_vec, m_recip_approx);
|
|
429
|
+
__m512 ratio_b_vec = _mm512_mul_ps(b_vec, m_recip_approx);
|
|
430
|
+
__m512 log_ratio_a_vec = simsimd_avx512_f32_log2(ratio_a_vec);
|
|
431
|
+
__m512 log_ratio_b_vec = simsimd_avx512_f32_log2(ratio_b_vec);
|
|
432
|
+
sum_a_vec = _mm512_maskz_fmadd_ps(nonzero_mask, a_vec, log_ratio_a_vec, sum_a_vec);
|
|
433
|
+
sum_b_vec = _mm512_maskz_fmadd_ps(nonzero_mask, b_vec, log_ratio_b_vec, sum_b_vec);
|
|
434
|
+
if (n)
|
|
435
|
+
goto simsimd_avx512_f32_js_cycle;
|
|
436
|
+
|
|
425
437
|
simsimd_f32_t log2_normalizer = 0.693147181f;
|
|
426
438
|
return _mm512_reduce_add_ps(_mm512_add_ps(sum_a_vec, sum_b_vec)) * 0.5f * log2_normalizer;
|
|
427
439
|
}
|
|
@@ -456,56 +468,68 @@ simsimd_avx512_f16_log2(__m512h x) {
|
|
|
456
468
|
return _mm512_add_ph(_mm512_mul_ph(p, _mm512_sub_ph(m, one)), e);
|
|
457
469
|
}
|
|
458
470
|
|
|
459
|
-
__attribute__((target("avx512f,avx512vl,avx512fp16"))) //
|
|
471
|
+
__attribute__((target("avx512f,avx512vl,avx512fp16,bmi2"))) //
|
|
460
472
|
inline static simsimd_f32_t
|
|
461
473
|
simsimd_avx512_f16_kl(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
462
474
|
__m512h sum_vec = _mm512_set1_ph((_Float16)0);
|
|
463
475
|
__m512h epsilon_vec = _mm512_set1_ph((_Float16)1e-6f);
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
476
|
+
__m512h a_vec, b_vec;
|
|
477
|
+
|
|
478
|
+
simsimd_avx512_f16_kl_cycle:
|
|
479
|
+
if (n < 32) {
|
|
480
|
+
__mmask32 mask = _bzhi_u32(0xFFFFFFFF, n);
|
|
481
|
+
a_vec = _mm512_maskz_add_ph(mask, _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, a)), epsilon_vec);
|
|
482
|
+
b_vec = _mm512_maskz_add_ph(mask, _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, b)), epsilon_vec);
|
|
483
|
+
n = 0;
|
|
484
|
+
} else {
|
|
485
|
+
a_vec = _mm512_add_ph(_mm512_castsi512_ph(_mm512_loadu_epi16(a)), epsilon_vec);
|
|
486
|
+
b_vec = _mm512_add_ph(_mm512_castsi512_ph(_mm512_loadu_epi16(b)), epsilon_vec);
|
|
487
|
+
a += 32, b += 32, n -= 32;
|
|
472
488
|
}
|
|
489
|
+
__m512h ratio_vec = _mm512_div_ph(a_vec, b_vec);
|
|
490
|
+
__m512h log_ratio_vec = simsimd_avx512_f16_log2(ratio_vec);
|
|
491
|
+
__m512h prod_vec = _mm512_mul_ph(a_vec, log_ratio_vec);
|
|
492
|
+
sum_vec = _mm512_add_ph(sum_vec, prod_vec);
|
|
493
|
+
if (n)
|
|
494
|
+
goto simsimd_avx512_f16_kl_cycle;
|
|
495
|
+
|
|
473
496
|
simsimd_f32_t log2_normalizer = 0.693147181f;
|
|
474
497
|
return _mm512_reduce_add_ph(sum_vec) * log2_normalizer;
|
|
475
498
|
}
|
|
476
499
|
|
|
477
|
-
__attribute__((target("avx512f,avx512vl,avx512fp16"))) //
|
|
500
|
+
__attribute__((target("avx512f,avx512vl,avx512fp16,bmi2"))) //
|
|
478
501
|
inline static simsimd_f32_t
|
|
479
502
|
simsimd_avx512_f16_js(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
480
503
|
__m512h sum_a_vec = _mm512_set1_ph((_Float16)0);
|
|
481
504
|
__m512h sum_b_vec = _mm512_set1_ph((_Float16)0);
|
|
482
505
|
__m512h epsilon_vec = _mm512_set1_ph((_Float16)1e-6f);
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
// Division is an expensive operation. Instead of doing it twice,
|
|
496
|
-
// we can approximate the reciprocal of `m` and multiply instead.
|
|
497
|
-
__m512h m_recip_approx = _mm512_rcp_ph(m_vec);
|
|
498
|
-
__m512h ratio_a_vec = _mm512_mul_ph(a_vec, m_recip_approx);
|
|
499
|
-
__m512h ratio_b_vec = _mm512_mul_ph(b_vec, m_recip_approx);
|
|
500
|
-
|
|
501
|
-
// The natural logarithm is equivalent to `log2`, multiplied by the `loge(2)`
|
|
502
|
-
__m512h log_ratio_a_vec = simsimd_avx512_f16_log2(ratio_a_vec);
|
|
503
|
-
__m512h log_ratio_b_vec = simsimd_avx512_f16_log2(ratio_b_vec);
|
|
504
|
-
|
|
505
|
-
// Instead of separate multiplication and addition, invoke the FMA
|
|
506
|
-
sum_a_vec = _mm512_maskz_fmadd_ph(nonzero_mask, a_vec, log_ratio_a_vec, sum_a_vec);
|
|
507
|
-
sum_b_vec = _mm512_maskz_fmadd_ph(nonzero_mask, b_vec, log_ratio_b_vec, sum_b_vec);
|
|
506
|
+
__m512h a_vec, b_vec;
|
|
507
|
+
|
|
508
|
+
simsimd_avx512_f16_js_cycle:
|
|
509
|
+
if (n < 32) {
|
|
510
|
+
__mmask32 mask = _bzhi_u32(0xFFFFFFFF, n);
|
|
511
|
+
a_vec = _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, a));
|
|
512
|
+
b_vec = _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, b));
|
|
513
|
+
n = 0;
|
|
514
|
+
} else {
|
|
515
|
+
a_vec = _mm512_castsi512_ph(_mm512_loadu_epi16(a));
|
|
516
|
+
b_vec = _mm512_castsi512_ph(_mm512_loadu_epi16(b));
|
|
517
|
+
a += 32, b += 32, n -= 32;
|
|
508
518
|
}
|
|
519
|
+
__m512h m_vec = _mm512_mul_ph(_mm512_add_ph(a_vec, b_vec), _mm512_set1_ph((_Float16)0.5f));
|
|
520
|
+
__mmask32 nonzero_mask_a = _mm512_cmp_ph_mask(a_vec, epsilon_vec, _CMP_GE_OQ);
|
|
521
|
+
__mmask32 nonzero_mask_b = _mm512_cmp_ph_mask(b_vec, epsilon_vec, _CMP_GE_OQ);
|
|
522
|
+
__mmask32 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
|
|
523
|
+
__m512h m_recip_approx = _mm512_rcp_ph(m_vec);
|
|
524
|
+
__m512h ratio_a_vec = _mm512_mul_ph(a_vec, m_recip_approx);
|
|
525
|
+
__m512h ratio_b_vec = _mm512_mul_ph(b_vec, m_recip_approx);
|
|
526
|
+
__m512h log_ratio_a_vec = simsimd_avx512_f16_log2(ratio_a_vec);
|
|
527
|
+
__m512h log_ratio_b_vec = simsimd_avx512_f16_log2(ratio_b_vec);
|
|
528
|
+
sum_a_vec = _mm512_maskz_fmadd_ph(nonzero_mask, a_vec, log_ratio_a_vec, sum_a_vec);
|
|
529
|
+
sum_b_vec = _mm512_maskz_fmadd_ph(nonzero_mask, b_vec, log_ratio_b_vec, sum_b_vec);
|
|
530
|
+
if (n)
|
|
531
|
+
goto simsimd_avx512_f16_js_cycle;
|
|
532
|
+
|
|
509
533
|
simsimd_f32_t log2_normalizer = 0.693147181f;
|
|
510
534
|
return _mm512_reduce_add_ph(_mm512_add_ph(sum_a_vec, sum_b_vec)) * 0.5f * log2_normalizer;
|
|
511
535
|
}
|
|
@@ -74,6 +74,7 @@ typedef enum {
|
|
|
74
74
|
simsimd_cap_x86_avx2fp16_k = 1 << 22, ///< x86 AVX2 with FP16 capability
|
|
75
75
|
simsimd_cap_x86_avx512fp16_k = 1 << 23, ///< x86 AVX512 with FP16 capability
|
|
76
76
|
simsimd_cap_x86_avx512vpopcntdq_k = 1 << 24, ///< x86 AVX512 VPOPCNTDQ instruction capability
|
|
77
|
+
simsimd_cap_x86_avx512vnni_k = 1 << 25, ///< x86 AVX512 VNNI instruction capability
|
|
77
78
|
|
|
78
79
|
} simsimd_capability_t;
|
|
79
80
|
|
|
@@ -112,42 +113,50 @@ inline static simsimd_capability_t simsimd_capabilities() {
|
|
|
112
113
|
/// The states of 4 registers populated for a specific "cpuid" assmebly call
|
|
113
114
|
union four_registers_t {
|
|
114
115
|
int array[4];
|
|
115
|
-
struct {
|
|
116
|
+
struct separate_t {
|
|
116
117
|
unsigned eax, ebx, ecx, edx;
|
|
117
|
-
};
|
|
118
|
+
} named;
|
|
118
119
|
} info1, info7;
|
|
119
120
|
|
|
120
121
|
#ifdef _MSC_VER
|
|
121
122
|
__cpuidex(info1.array, 1, 0);
|
|
122
123
|
__cpuidex(info7.array, 7, 0);
|
|
123
124
|
#else
|
|
124
|
-
__asm__ __volatile__("cpuid"
|
|
125
|
-
|
|
125
|
+
__asm__ __volatile__("cpuid"
|
|
126
|
+
: "=a"(info1.named.eax), "=b"(info1.named.ebx), "=c"(info1.named.ecx), "=d"(info1.named.edx)
|
|
127
|
+
: "a"(1), "c"(0));
|
|
128
|
+
__asm__ __volatile__("cpuid"
|
|
129
|
+
: "=a"(info7.named.eax), "=b"(info7.named.ebx), "=c"(info7.named.ecx), "=d"(info7.named.edx)
|
|
130
|
+
: "a"(7), "c"(0));
|
|
126
131
|
#endif
|
|
127
132
|
|
|
128
133
|
// Check for AVX2 (Function ID 7, EBX register)
|
|
129
134
|
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L148
|
|
130
|
-
unsigned supports_avx2 = (info7.ebx & 0x00000020) != 0;
|
|
135
|
+
unsigned supports_avx2 = (info7.named.ebx & 0x00000020) != 0;
|
|
131
136
|
// Check for F16C (Function ID 1, ECX register)
|
|
132
137
|
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L107
|
|
133
|
-
unsigned supports_f16c = (info1.ecx & 0x20000000) != 0;
|
|
138
|
+
unsigned supports_f16c = (info1.named.ecx & 0x20000000) != 0;
|
|
134
139
|
// Check for AVX512F (Function ID 7, EBX register)
|
|
135
140
|
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L155
|
|
136
|
-
unsigned supports_avx512f = (info7.ebx & 0x00010000) != 0;
|
|
141
|
+
unsigned supports_avx512f = (info7.named.ebx & 0x00010000) != 0;
|
|
137
142
|
// Check for AVX512FP16 (Function ID 7, EDX register)
|
|
138
143
|
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L198C9-L198C23
|
|
139
|
-
unsigned supports_avx512fp16 = (info7.edx & 0x00800000) != 0;
|
|
144
|
+
unsigned supports_avx512fp16 = (info7.named.edx & 0x00800000) != 0;
|
|
140
145
|
// Check for VPOPCNTDQ (Function ID 1, ECX register)
|
|
141
146
|
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L182C30-L182C40
|
|
142
|
-
unsigned supports_avx512vpopcntdq = (info1.ecx & 0x00004000) != 0;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
(
|
|
149
|
-
(
|
|
150
|
-
|
|
147
|
+
unsigned supports_avx512vpopcntdq = (info1.named.ecx & 0x00004000) != 0;
|
|
148
|
+
// Check for VNNI (Function ID 1, ECX register)
|
|
149
|
+
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L180
|
|
150
|
+
unsigned supports_avx512vnni = (info1.named.ecx & 0x00000800) != 0;
|
|
151
|
+
|
|
152
|
+
return (simsimd_capability_t)( //
|
|
153
|
+
(simsimd_cap_x86_avx2_k * supports_avx2) | //
|
|
154
|
+
(simsimd_cap_x86_avx512_k * supports_avx512f) | //
|
|
155
|
+
(simsimd_cap_x86_avx2fp16_k * (supports_avx2 && supports_f16c)) | //
|
|
156
|
+
(simsimd_cap_x86_avx512fp16_k * (supports_avx512fp16 && supports_avx512f)) | //
|
|
157
|
+
(simsimd_cap_x86_avx512vpopcntdq_k * (supports_avx512vpopcntdq)) | //
|
|
158
|
+
(simsimd_cap_x86_avx512vnni_k * (supports_avx512vnni)) | //
|
|
159
|
+
(simsimd_cap_serial_k));
|
|
151
160
|
|
|
152
161
|
#endif // SIMSIMD_TARGET_X86
|
|
153
162
|
|
|
@@ -319,11 +328,11 @@ inline static void simsimd_find_metric_punned( //
|
|
|
319
328
|
}
|
|
320
329
|
#endif
|
|
321
330
|
#if SIMSIMD_TARGET_X86_AVX512
|
|
322
|
-
if (viable &
|
|
331
|
+
if (viable & simsimd_cap_x86_avx512vnni_k)
|
|
323
332
|
switch (kind) {
|
|
324
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_ip, *c =
|
|
325
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_cos, *c =
|
|
326
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_l2sq, *c =
|
|
333
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_ip, *c = simsimd_cap_x86_avx512vnni_k; return;
|
|
334
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_cos, *c = simsimd_cap_x86_avx512vnni_k; return;
|
|
335
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_l2sq, *c = simsimd_cap_x86_avx512vnni_k; return;
|
|
327
336
|
default: break;
|
|
328
337
|
}
|
|
329
338
|
#endif
|