usearch 2.13.3 → 2.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/include/usearch/index.hpp +1 -1
- 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/include/simsimd/binary.h +5 -5
- package/simsimd/include/simsimd/dot.h +16 -0
- package/simsimd/include/simsimd/simsimd.h +16 -0
- package/simsimd/include/simsimd/spatial.h +63 -8
package/README.md
CHANGED
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -73,7 +73,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_serial(simsimd_b8_t const* a, simsimd_b8_
|
|
|
73
73
|
simsimd_i32_t intersection = 0, union_ = 0;
|
|
74
74
|
for (simsimd_size_t i = 0; i != n_words; ++i)
|
|
75
75
|
intersection += simsimd_popcount_b8(a[i] & b[i]), union_ += simsimd_popcount_b8(a[i] | b[i]);
|
|
76
|
-
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ :
|
|
76
|
+
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
#if SIMSIMD_TARGET_ARM
|
|
@@ -110,7 +110,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_neon(simsimd_b8_t const* a, simsimd_b8_t
|
|
|
110
110
|
// Handle the tail
|
|
111
111
|
for (; i != n_words; ++i)
|
|
112
112
|
intersection += simsimd_popcount_b8(a[i] & b[i]), union_ += simsimd_popcount_b8(a[i] | b[i]);
|
|
113
|
-
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ :
|
|
113
|
+
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
#pragma clang attribute pop
|
|
@@ -148,7 +148,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_sve(simsimd_b8_t const* a, simsimd_b8_t c
|
|
|
148
148
|
union_ += svaddv_u8(svptrue_b8(), svcnt_u8_x(svptrue_b8(), svorr_u8_m(svptrue_b8(), a_vec, b_vec)));
|
|
149
149
|
i += svcntb();
|
|
150
150
|
} while (i < n_words);
|
|
151
|
-
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ :
|
|
151
|
+
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
#pragma clang attribute pop
|
|
@@ -213,7 +213,7 @@ simsimd_jaccard_b8_ice_cycle:
|
|
|
213
213
|
|
|
214
214
|
simsimd_size_t intersection = _mm512_reduce_add_epi64(intersection_vec),
|
|
215
215
|
union_ = _mm512_reduce_add_epi64(union_vec);
|
|
216
|
-
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ :
|
|
216
|
+
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
#pragma clang attribute pop
|
|
@@ -245,7 +245,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_haswell(simsimd_b8_t const* a, simsimd_b8
|
|
|
245
245
|
union_ += _mm_popcnt_u64(*(simsimd_u64_t const*)a | *(simsimd_u64_t const*)b);
|
|
246
246
|
for (; n_words; --n_words, ++a, ++b)
|
|
247
247
|
intersection += _mm_popcnt_u32(*a & *b), union_ += _mm_popcnt_u32(*a | *b);
|
|
248
|
-
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ :
|
|
248
|
+
*result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
#pragma clang attribute pop
|
|
@@ -858,6 +858,22 @@ inline simsimd_f64_t _mm256_reduce_add_ps_dbl(__m256 vec) {
|
|
|
858
858
|
return _mm_cvtsd_f64(sum128);
|
|
859
859
|
}
|
|
860
860
|
|
|
861
|
+
SIMSIMD_PUBLIC void simsimd_dot_f32_haswell(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n,
|
|
862
|
+
simsimd_distance_t* results) {
|
|
863
|
+
|
|
864
|
+
__m256 ab_vec = _mm256_setzero_ps();
|
|
865
|
+
simsimd_size_t i = 0;
|
|
866
|
+
for (; i + 8 <= n; i += 8) {
|
|
867
|
+
__m256 a_vec = _mm256_loadu_ps(a + i);
|
|
868
|
+
__m256 b_vec = _mm256_loadu_ps(b + i);
|
|
869
|
+
ab_vec = _mm256_fmadd_ps(a_vec, b_vec, ab_vec);
|
|
870
|
+
}
|
|
871
|
+
simsimd_f64_t ab = _mm256_reduce_add_ps_dbl(ab_vec);
|
|
872
|
+
for (; i < n; ++i)
|
|
873
|
+
ab += a[i] * b[i];
|
|
874
|
+
*results = ab;
|
|
875
|
+
}
|
|
876
|
+
|
|
861
877
|
SIMSIMD_PUBLIC void simsimd_dot_f32c_haswell(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n,
|
|
862
878
|
simsimd_distance_t* results) {
|
|
863
879
|
|
|
@@ -527,6 +527,16 @@ SIMSIMD_PUBLIC void simsimd_find_metric_punned( //
|
|
|
527
527
|
default: break;
|
|
528
528
|
}
|
|
529
529
|
#endif
|
|
530
|
+
#if SIMSIMD_TARGET_HASWELL
|
|
531
|
+
if (viable & simsimd_cap_haswell_k)
|
|
532
|
+
switch (kind) {
|
|
533
|
+
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
534
|
+
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
535
|
+
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
536
|
+
default: break;
|
|
537
|
+
}
|
|
538
|
+
#endif
|
|
539
|
+
|
|
530
540
|
if (viable & simsimd_cap_serial_k)
|
|
531
541
|
switch (kind) {
|
|
532
542
|
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
@@ -1120,6 +1130,8 @@ SIMSIMD_PUBLIC void simsimd_dot_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1120
1130
|
simsimd_dot_f32_neon(a, b, n, d);
|
|
1121
1131
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1122
1132
|
simsimd_dot_f32_skylake(a, b, n, d);
|
|
1133
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1134
|
+
simsimd_dot_f32_haswell(a, b, n, d);
|
|
1123
1135
|
#else
|
|
1124
1136
|
simsimd_dot_f32_serial(a, b, n, d);
|
|
1125
1137
|
#endif
|
|
@@ -1292,6 +1304,8 @@ SIMSIMD_PUBLIC void simsimd_cos_f32(simsimd_f32_t const* a, simsimd_f32_t const*
|
|
|
1292
1304
|
simsimd_cos_f32_neon(a, b, n, d);
|
|
1293
1305
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1294
1306
|
simsimd_cos_f32_skylake(a, b, n, d);
|
|
1307
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1308
|
+
simsimd_cos_f32_haswell(a, b, n, d);
|
|
1295
1309
|
#else
|
|
1296
1310
|
simsimd_cos_f32_serial(a, b, n, d);
|
|
1297
1311
|
#endif
|
|
@@ -1338,6 +1352,8 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f32(simsimd_f32_t const* a, simsimd_f32_t const
|
|
|
1338
1352
|
simsimd_l2sq_f32_neon(a, b, n, d);
|
|
1339
1353
|
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1340
1354
|
simsimd_l2sq_f32_skylake(a, b, n, d);
|
|
1355
|
+
#elif SIMSIMD_TARGET_HASWELL
|
|
1356
|
+
simsimd_l2sq_f32_haswell(a, b, n, d);
|
|
1341
1357
|
#else
|
|
1342
1358
|
simsimd_l2sq_f32_serial(a, b, n, d);
|
|
1343
1359
|
#endif
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
|
|
28
28
|
#include "types.h"
|
|
29
29
|
|
|
30
|
+
#include "dot.h" // `_mm256_reduce_add_ps_dbl`
|
|
31
|
+
|
|
30
32
|
#ifdef __cplusplus
|
|
31
33
|
extern "C" {
|
|
32
34
|
#endif
|
|
@@ -93,6 +95,8 @@ SIMSIMD_PUBLIC void simsimd_l2sq_f16_haswell(simsimd_f16_t const* a, simsimd_f16
|
|
|
93
95
|
SIMSIMD_PUBLIC void simsimd_cos_f16_haswell(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t*);
|
|
94
96
|
SIMSIMD_PUBLIC void simsimd_l2sq_bf16_haswell(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n, simsimd_distance_t*);
|
|
95
97
|
SIMSIMD_PUBLIC void simsimd_cos_bf16_haswell(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n, simsimd_distance_t*);
|
|
98
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_f32_haswell(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t*);
|
|
99
|
+
SIMSIMD_PUBLIC void simsimd_cos_f32_haswell(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t*);
|
|
96
100
|
|
|
97
101
|
/* SIMD-powered backends for AVX512 CPUs of Skylake generation and newer, using 32-bit arithmetic over 512-bit words.
|
|
98
102
|
* Skylake was launched in 2015, and discontinued in 2019. Skylake had support for F, CD, VL, DQ, and BW extensions,
|
|
@@ -839,8 +843,7 @@ SIMSIMD_PUBLIC void simsimd_cos_f16_haswell(simsimd_f16_t const* a, simsimd_f16_
|
|
|
839
843
|
__m128 b2_sqrt_recip = _mm_rsqrt_ss(_mm_set_ss((float)b2));
|
|
840
844
|
__m128 result_vec = _mm_mul_ss(a2_sqrt_recip, b2_sqrt_recip); // Multiply the reciprocal square roots
|
|
841
845
|
result_vec = _mm_mul_ss(result_vec, _mm_set_ss((float)ab)); // Multiply by ab
|
|
842
|
-
|
|
843
|
-
*result = ab != 0 ? _mm_cvtss_f32(result_vec) : 1; // Extract the final result
|
|
846
|
+
*result = ab != 0 ? 1 - _mm_cvtss_f32(result_vec) : 1; // Extract the final result
|
|
844
847
|
}
|
|
845
848
|
|
|
846
849
|
SIMSIMD_PUBLIC void simsimd_l2sq_bf16_haswell(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n,
|
|
@@ -946,8 +949,7 @@ SIMSIMD_PUBLIC void simsimd_cos_bf16_haswell(simsimd_bf16_t const* a, simsimd_bf
|
|
|
946
949
|
__m128 b2_sqrt_recip = _mm_rsqrt_ss(_mm_set_ss((float)b2));
|
|
947
950
|
__m128 result_vec = _mm_mul_ss(a2_sqrt_recip, b2_sqrt_recip); // Multiply the reciprocal square roots
|
|
948
951
|
result_vec = _mm_mul_ss(result_vec, _mm_set_ss((float)ab)); // Multiply by ab
|
|
949
|
-
|
|
950
|
-
*result = ab != 0 ? _mm_cvtss_f32(result_vec) : 1; // Extract the final result
|
|
952
|
+
*result = ab != 0 ? 1 - _mm_cvtss_f32(result_vec) : 1; // Extract the final result
|
|
951
953
|
}
|
|
952
954
|
|
|
953
955
|
SIMSIMD_PUBLIC void simsimd_l2sq_i8_haswell(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size_t n,
|
|
@@ -1058,7 +1060,60 @@ SIMSIMD_PUBLIC void simsimd_cos_i8_haswell(simsimd_i8_t const* a, simsimd_i8_t c
|
|
|
1058
1060
|
// Compute cosine similarity: ab / sqrt(a2 * b2)
|
|
1059
1061
|
__m128 denom = _mm_mul_ss(a2_sqrt_recip, b2_sqrt_recip); // Reciprocal of sqrt(a2 * b2)
|
|
1060
1062
|
__m128 result_vec = _mm_mul_ss(_mm_set_ss((float)ab), denom); // ab * reciprocal of sqrt(a2 * b2)
|
|
1061
|
-
*result = ab != 0 ? 1 - _mm_cvtss_f32(result_vec) :
|
|
1063
|
+
*result = ab != 0 ? 1 - _mm_cvtss_f32(result_vec) : 1; // Extract the final result
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
SIMSIMD_PUBLIC void simsimd_l2sq_f32_haswell(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n,
|
|
1067
|
+
simsimd_distance_t* result) {
|
|
1068
|
+
|
|
1069
|
+
__m256 d2_vec = _mm256_setzero_ps();
|
|
1070
|
+
simsimd_size_t i = 0;
|
|
1071
|
+
for (; i + 8 <= n; i += 8) {
|
|
1072
|
+
__m256 a_vec = _mm256_loadu_ps(a + i);
|
|
1073
|
+
__m256 b_vec = _mm256_loadu_ps(b + i);
|
|
1074
|
+
__m256 d_vec = _mm256_sub_ps(a_vec, b_vec);
|
|
1075
|
+
d2_vec = _mm256_fmadd_ps(d_vec, d_vec, d2_vec);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
simsimd_f64_t d2 = _mm256_reduce_add_ps_dbl(d2_vec);
|
|
1079
|
+
for (; i < n; ++i) {
|
|
1080
|
+
float d = a[i] - b[i];
|
|
1081
|
+
d2 += d * d;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
*result = d2;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
SIMSIMD_PUBLIC void simsimd_cos_f32_haswell(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n,
|
|
1088
|
+
simsimd_distance_t* result) {
|
|
1089
|
+
|
|
1090
|
+
__m256 ab_vec = _mm256_setzero_ps();
|
|
1091
|
+
__m256 a2_vec = _mm256_setzero_ps();
|
|
1092
|
+
__m256 b2_vec = _mm256_setzero_ps();
|
|
1093
|
+
simsimd_size_t i = 0;
|
|
1094
|
+
for (; i + 8 <= n; i += 8) {
|
|
1095
|
+
__m256 a_vec = _mm256_loadu_ps(a + i);
|
|
1096
|
+
__m256 b_vec = _mm256_loadu_ps(b + i);
|
|
1097
|
+
ab_vec = _mm256_fmadd_ps(a_vec, b_vec, ab_vec);
|
|
1098
|
+
a2_vec = _mm256_fmadd_ps(a_vec, a_vec, a2_vec);
|
|
1099
|
+
b2_vec = _mm256_fmadd_ps(b_vec, b_vec, b2_vec);
|
|
1100
|
+
}
|
|
1101
|
+
simsimd_f64_t ab = _mm256_reduce_add_ps_dbl(ab_vec);
|
|
1102
|
+
simsimd_f64_t a2 = _mm256_reduce_add_ps_dbl(a2_vec);
|
|
1103
|
+
simsimd_f64_t b2 = _mm256_reduce_add_ps_dbl(b2_vec);
|
|
1104
|
+
for (; i < n; ++i) {
|
|
1105
|
+
float ai = a[i], bi = b[i];
|
|
1106
|
+
ab += ai * bi, a2 += ai * ai, b2 += bi * bi;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
// Compute the reciprocal of the square roots
|
|
1110
|
+
__m128 a2_sqrt_recip = _mm_rsqrt_ss(_mm_set_ss((float)a2));
|
|
1111
|
+
__m128 b2_sqrt_recip = _mm_rsqrt_ss(_mm_set_ss((float)b2));
|
|
1112
|
+
|
|
1113
|
+
// Compute cosine similarity: ab / sqrt(a2 * b2)
|
|
1114
|
+
__m128 denom = _mm_mul_ss(a2_sqrt_recip, b2_sqrt_recip); // Reciprocal of sqrt(a2 * b2)
|
|
1115
|
+
__m128 result_vec = _mm_mul_ss(_mm_set_ss((float)ab), denom); // ab * reciprocal of sqrt(a2 * b2)
|
|
1116
|
+
*result = ab != 0 ? 1 - _mm_cvtss_f32(result_vec) : 1; // Extract the final result
|
|
1062
1117
|
}
|
|
1063
1118
|
|
|
1064
1119
|
#pragma clang attribute pop
|
|
@@ -1282,7 +1337,7 @@ simsimd_cos_bf16_genoa_cycle:
|
|
|
1282
1337
|
__m128 rsqrts = _mm_rsqrt14_ps(_mm_set_ps(0.f, 0.f, a2 + 1.e-9f, b2 + 1.e-9f));
|
|
1283
1338
|
simsimd_f32_t rsqrt_a2 = _mm_cvtss_f32(rsqrts);
|
|
1284
1339
|
simsimd_f32_t rsqrt_b2 = _mm_cvtss_f32(_mm_shuffle_ps(rsqrts, rsqrts, _MM_SHUFFLE(0, 0, 0, 1)));
|
|
1285
|
-
*result = ab != 0 ? 1 - ab * rsqrt_a2 * rsqrt_b2 :
|
|
1340
|
+
*result = ab != 0 ? 1 - ab * rsqrt_a2 * rsqrt_b2 : 1;
|
|
1286
1341
|
}
|
|
1287
1342
|
|
|
1288
1343
|
#pragma clang attribute pop
|
|
@@ -1350,7 +1405,7 @@ simsimd_cos_f16_sapphire_cycle:
|
|
|
1350
1405
|
__m128 rsqrts = _mm_rsqrt14_ps(_mm_set_ps(0.f, 0.f, a2 + 1.e-9f, b2 + 1.e-9f));
|
|
1351
1406
|
simsimd_f32_t rsqrt_a2 = _mm_cvtss_f32(rsqrts);
|
|
1352
1407
|
simsimd_f32_t rsqrt_b2 = _mm_cvtss_f32(_mm_shuffle_ps(rsqrts, rsqrts, _MM_SHUFFLE(0, 0, 0, 1)));
|
|
1353
|
-
*result = ab != 0 ? 1 - ab * rsqrt_a2 * rsqrt_b2 :
|
|
1408
|
+
*result = ab != 0 ? 1 - ab * rsqrt_a2 * rsqrt_b2 : 1;
|
|
1354
1409
|
}
|
|
1355
1410
|
|
|
1356
1411
|
#pragma clang attribute pop
|
|
@@ -1440,7 +1495,7 @@ simsimd_cos_i8_ice_cycle:
|
|
|
1440
1495
|
__m128 rsqrts = _mm_maskz_rsqrt14_ps(0xFF, _mm_set_ps(0.f, 0.f, a2 + 1.e-9f, b2 + 1.e-9f));
|
|
1441
1496
|
simsimd_f32_t rsqrt_a2 = _mm_cvtss_f32(rsqrts);
|
|
1442
1497
|
simsimd_f32_t rsqrt_b2 = _mm_cvtss_f32(_mm_shuffle_ps(rsqrts, rsqrts, _MM_SHUFFLE(0, 0, 0, 1)));
|
|
1443
|
-
*result = ab != 0 ? 1 - ab * rsqrt_a2 * rsqrt_b2 :
|
|
1498
|
+
*result = ab != 0 ? 1 - ab * rsqrt_a2 * rsqrt_b2 : 1;
|
|
1444
1499
|
}
|
|
1445
1500
|
|
|
1446
1501
|
#pragma clang attribute pop
|