usearch 2.15.3 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/cpp/test.cpp +16 -0
- package/include/usearch/index.hpp +21 -5
- package/include/usearch/index_dense.hpp +6 -1
- package/include/usearch/index_plugins.hpp +345 -8
- package/javascript/lib.cpp +17 -5
- package/javascript/usearch.test.js +190 -21
- package/package.json +1 -1
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/simsimd/.git-blame-ignore-revs +2 -0
- package/simsimd/CONTRIBUTING.md +71 -23
- package/simsimd/Cargo.lock +1 -1
- package/simsimd/Cargo.toml +4 -4
- package/simsimd/MANIFEST.in +2 -1
- package/simsimd/Package.swift +15 -3
- package/simsimd/README.md +104 -35
- package/simsimd/binding.gyp +6 -2
- package/simsimd/build.rs +2 -0
- package/simsimd/c/lib.c +180 -99
- package/simsimd/include/simsimd/binary.h +311 -102
- package/simsimd/include/simsimd/curved.h +134 -135
- package/simsimd/include/simsimd/dot.h +448 -274
- package/simsimd/include/simsimd/elementwise.h +1437 -0
- package/simsimd/include/simsimd/geospatial.h +2 -2
- package/simsimd/include/simsimd/mesh.h +2 -2
- package/simsimd/include/simsimd/probability.h +88 -88
- package/simsimd/include/simsimd/simsimd.h +1157 -772
- package/simsimd/include/simsimd/sparse.h +768 -147
- package/simsimd/include/simsimd/spatial.h +955 -376
- package/simsimd/include/simsimd/types.h +145 -71
- package/simsimd/javascript/lib.c +1 -2
- package/simsimd/package.json +4 -4
- package/simsimd/rust/lib.rs +14 -1
- package/simsimd/scripts/bench.cxx +1070 -0
- package/simsimd/scripts/bench.ipynb +187 -0
- package/simsimd/{javascript → scripts}/bench.js +1 -1
- package/simsimd/{rust/benches/sqeuclidean.rs → scripts/bench_sqeuclidean.rs} +6 -6
- package/simsimd/scripts/bench_vectors.py +700 -0
- package/simsimd/scripts/bench_vectors_live.py +213 -0
- package/simsimd/scripts/test.c +155 -0
- package/simsimd/{javascript → scripts}/test.mjs +2 -2
- package/simsimd/scripts/test.py +1410 -0
- package/simsimd/swift/{source/SimSIMD.swift → SimSIMD.swift} +6 -2
- package/simsimd/swift/{tests/SimSIMDTests.swift → Test.swift} +1 -1
- /package/simsimd/{rust/benches/cosine.rs → scripts/bench_cosine.rs} +0 -0
- /package/simsimd/{rust/benches/native.rs → scripts/bench_native.rs} +0 -0
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* - 16-bit brain-floating point numbers
|
|
15
15
|
*
|
|
16
16
|
* For hardware architectures:
|
|
17
|
-
* - Arm
|
|
18
|
-
* - x86
|
|
17
|
+
* - Arm: NEON
|
|
18
|
+
* - x86: Haswell, Ice Lake, Skylake, Genoa, Sapphire
|
|
19
19
|
*
|
|
20
20
|
* x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/
|
|
21
21
|
* Arm intrinsics: https://developer.arm.com/architectures/instruction-sets/intrinsics/
|
|
@@ -92,40 +92,40 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16_sapphire(simsimd_f16_t const* a, simsim
|
|
|
92
92
|
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_sapphire(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_f16_t const* c, simsimd_size_t n, simsimd_distance_t* result);
|
|
93
93
|
// clang-format on
|
|
94
94
|
|
|
95
|
-
#define SIMSIMD_MAKE_BILINEAR(name, input_type, accumulator_type, load_and_convert)
|
|
96
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_##input_type##_##name(
|
|
97
|
-
simsimd_##input_type##_t const*
|
|
98
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
99
|
-
simsimd_##accumulator_type##_t sum = 0;
|
|
100
|
-
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
101
|
-
simsimd_##accumulator_type##_t partial = 0;
|
|
102
|
-
simsimd_##accumulator_type##_t a_i = load_and_convert(a + i);
|
|
103
|
-
for (simsimd_size_t j = 0; j != n; ++j) {
|
|
104
|
-
simsimd_##accumulator_type##_t b_j = load_and_convert(b + j);
|
|
105
|
-
simsimd_##accumulator_type##_t c_ij = load_and_convert(c + i * n + j);
|
|
106
|
-
partial += c_ij * b_j;
|
|
107
|
-
}
|
|
108
|
-
sum += a_i * partial;
|
|
109
|
-
}
|
|
110
|
-
*result = (simsimd_distance_t)sum;
|
|
95
|
+
#define SIMSIMD_MAKE_BILINEAR(name, input_type, accumulator_type, load_and_convert) \
|
|
96
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_##input_type##_##name( \
|
|
97
|
+
simsimd_##input_type##_t const *a, simsimd_##input_type##_t const *b, simsimd_##input_type##_t const *c, \
|
|
98
|
+
simsimd_size_t n, simsimd_distance_t *result) { \
|
|
99
|
+
simsimd_##accumulator_type##_t sum = 0; \
|
|
100
|
+
for (simsimd_size_t i = 0; i != n; ++i) { \
|
|
101
|
+
simsimd_##accumulator_type##_t partial = 0; \
|
|
102
|
+
simsimd_##accumulator_type##_t a_i = load_and_convert(a + i); \
|
|
103
|
+
for (simsimd_size_t j = 0; j != n; ++j) { \
|
|
104
|
+
simsimd_##accumulator_type##_t b_j = load_and_convert(b + j); \
|
|
105
|
+
simsimd_##accumulator_type##_t c_ij = load_and_convert(c + i * n + j); \
|
|
106
|
+
partial += c_ij * b_j; \
|
|
107
|
+
} \
|
|
108
|
+
sum += a_i * partial; \
|
|
109
|
+
} \
|
|
110
|
+
*result = (simsimd_distance_t)sum; \
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
#define SIMSIMD_MAKE_MAHALANOBIS(name, input_type, accumulator_type, load_and_convert)
|
|
114
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_##input_type##_##name(
|
|
115
|
-
simsimd_##input_type##_t const*
|
|
116
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
117
|
-
simsimd_##accumulator_type##_t sum = 0;
|
|
118
|
-
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
119
|
-
simsimd_##accumulator_type##_t partial = 0;
|
|
120
|
-
simsimd_##accumulator_type##_t diff_i = load_and_convert(a + i) - load_and_convert(b + i);
|
|
121
|
-
for (simsimd_size_t j = 0; j != n; ++j) {
|
|
122
|
-
simsimd_##accumulator_type##_t diff_j = load_and_convert(a + j) - load_and_convert(b + j);
|
|
123
|
-
simsimd_##accumulator_type##_t c_ij = load_and_convert(c + i * n + j);
|
|
124
|
-
partial += c_ij * diff_j;
|
|
125
|
-
}
|
|
126
|
-
sum += diff_i * partial;
|
|
127
|
-
}
|
|
128
|
-
*result = (simsimd_distance_t)SIMSIMD_SQRT(sum);
|
|
113
|
+
#define SIMSIMD_MAKE_MAHALANOBIS(name, input_type, accumulator_type, load_and_convert) \
|
|
114
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_##input_type##_##name( \
|
|
115
|
+
simsimd_##input_type##_t const *a, simsimd_##input_type##_t const *b, simsimd_##input_type##_t const *c, \
|
|
116
|
+
simsimd_size_t n, simsimd_distance_t *result) { \
|
|
117
|
+
simsimd_##accumulator_type##_t sum = 0; \
|
|
118
|
+
for (simsimd_size_t i = 0; i != n; ++i) { \
|
|
119
|
+
simsimd_##accumulator_type##_t partial = 0; \
|
|
120
|
+
simsimd_##accumulator_type##_t diff_i = load_and_convert(a + i) - load_and_convert(b + i); \
|
|
121
|
+
for (simsimd_size_t j = 0; j != n; ++j) { \
|
|
122
|
+
simsimd_##accumulator_type##_t diff_j = load_and_convert(a + j) - load_and_convert(b + j); \
|
|
123
|
+
simsimd_##accumulator_type##_t c_ij = load_and_convert(c + i * n + j); \
|
|
124
|
+
partial += c_ij * diff_j; \
|
|
125
|
+
} \
|
|
126
|
+
sum += diff_i * partial; \
|
|
127
|
+
} \
|
|
128
|
+
*result = (simsimd_distance_t)SIMSIMD_SQRT(sum); \
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
SIMSIMD_MAKE_BILINEAR(serial, f64, f64, SIMSIMD_DEREFERENCE) // simsimd_bilinear_f64_serial
|
|
@@ -149,14 +149,14 @@ SIMSIMD_MAKE_MAHALANOBIS(accurate, f16, f64, SIMSIMD_F16_TO_F32) // simsimd_maha
|
|
|
149
149
|
SIMSIMD_MAKE_BILINEAR(accurate, bf16, f64, SIMSIMD_BF16_TO_F32) // simsimd_bilinear_bf16_accurate
|
|
150
150
|
SIMSIMD_MAKE_MAHALANOBIS(accurate, bf16, f64, SIMSIMD_BF16_TO_F32) // simsimd_mahalanobis_bf16_accurate
|
|
151
151
|
|
|
152
|
-
#if
|
|
152
|
+
#if _SIMSIMD_TARGET_ARM
|
|
153
153
|
#if SIMSIMD_TARGET_NEON
|
|
154
154
|
#pragma GCC push_options
|
|
155
155
|
#pragma GCC target("arch=armv8.2-a+simd")
|
|
156
156
|
#pragma clang attribute push(__attribute__((target("arch=armv8.2-a+simd"))), apply_to = function)
|
|
157
157
|
|
|
158
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f32_neon(simsimd_f32_t const*
|
|
159
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
158
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f32_neon(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
159
|
+
simsimd_size_t n, simsimd_distance_t *result) {
|
|
160
160
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
161
161
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
162
162
|
float32x4_t a_vec = vdupq_n_f32(a[i]);
|
|
@@ -177,8 +177,7 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f32_neon(simsimd_f32_t const* a, simsimd_f3
|
|
|
177
177
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
178
178
|
simsimd_f32_t a_i = a[i];
|
|
179
179
|
simsimd_f32_t partial_sum = 0;
|
|
180
|
-
for (simsimd_size_t j = tail_start; j != n; ++j)
|
|
181
|
-
partial_sum += b[j] * c[i * n + j];
|
|
180
|
+
for (simsimd_size_t j = tail_start; j != n; ++j) partial_sum += b[j] * c[i * n + j];
|
|
182
181
|
sum += a[i] * partial_sum;
|
|
183
182
|
}
|
|
184
183
|
}
|
|
@@ -186,8 +185,8 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f32_neon(simsimd_f32_t const* a, simsimd_f3
|
|
|
186
185
|
*result = sum;
|
|
187
186
|
}
|
|
188
187
|
|
|
189
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_neon(simsimd_f32_t const*
|
|
190
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
188
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_neon(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
189
|
+
simsimd_size_t n, simsimd_distance_t *result) {
|
|
191
190
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
192
191
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
193
192
|
float32x4_t diff_i_vec = vdupq_n_f32(a[i] - b[i]);
|
|
@@ -229,16 +228,16 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_neon(simsimd_f32_t const* a, simsimd
|
|
|
229
228
|
#pragma GCC target("arch=armv8.2-a+simd+fp16")
|
|
230
229
|
#pragma clang attribute push(__attribute__((target("arch=armv8.2-a+simd+fp16"))), apply_to = function)
|
|
231
230
|
|
|
232
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f16_neon(simsimd_f16_t const*
|
|
233
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
231
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f16_neon(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
232
|
+
simsimd_size_t n, simsimd_distance_t *result) {
|
|
234
233
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
235
234
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
236
235
|
// MSVC doesn't recognize `vdup_n_f16` as a valid intrinsic
|
|
237
|
-
float32x4_t a_vec = vcvt_f32_f16(vreinterpret_f16_s16(vdup_n_s16(*(short const*)(a + i))));
|
|
236
|
+
float32x4_t a_vec = vcvt_f32_f16(vreinterpret_f16_s16(vdup_n_s16(*(short const *)(a + i))));
|
|
238
237
|
float32x4_t partial_sum_vec = vdupq_n_f32(0);
|
|
239
238
|
for (simsimd_size_t j = 0; j + 4 <= n; j += 4) {
|
|
240
|
-
float32x4_t b_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const*)(b + j)));
|
|
241
|
-
float32x4_t c_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const*)(c + i * n + j)));
|
|
239
|
+
float32x4_t b_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)(b + j)));
|
|
240
|
+
float32x4_t c_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)(c + i * n + j)));
|
|
242
241
|
partial_sum_vec = vmlaq_f32(partial_sum_vec, b_vec, c_vec);
|
|
243
242
|
}
|
|
244
243
|
sum_vec = vmlaq_f32(sum_vec, a_vec, partial_sum_vec);
|
|
@@ -261,20 +260,20 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16_neon(simsimd_f16_t const* a, simsimd_f1
|
|
|
261
260
|
*result = sum;
|
|
262
261
|
}
|
|
263
262
|
|
|
264
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_neon(simsimd_f16_t const*
|
|
265
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
263
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_neon(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
264
|
+
simsimd_size_t n, simsimd_distance_t *result) {
|
|
266
265
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
267
266
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
268
267
|
// MSVC doesn't recognize `vdup_n_f16` as a valid intrinsic
|
|
269
|
-
float32x4_t a_i_vec = vcvt_f32_f16(vreinterpret_f16_s16(vdup_n_s16(*(short const*)(a + i))));
|
|
270
|
-
float32x4_t b_i_vec = vcvt_f32_f16(vreinterpret_f16_s16(vdup_n_s16(*(short const*)(b + i))));
|
|
268
|
+
float32x4_t a_i_vec = vcvt_f32_f16(vreinterpret_f16_s16(vdup_n_s16(*(short const *)(a + i))));
|
|
269
|
+
float32x4_t b_i_vec = vcvt_f32_f16(vreinterpret_f16_s16(vdup_n_s16(*(short const *)(b + i))));
|
|
271
270
|
float32x4_t diff_i_vec = vsubq_f32(a_i_vec, b_i_vec);
|
|
272
271
|
float32x4_t partial_sum_vec = vdupq_n_f32(0);
|
|
273
272
|
for (simsimd_size_t j = 0; j + 4 <= n; j += 4) {
|
|
274
|
-
float32x4_t a_j_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const*)(a + j)));
|
|
275
|
-
float32x4_t b_j_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const*)(b + j)));
|
|
273
|
+
float32x4_t a_j_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)(a + j)));
|
|
274
|
+
float32x4_t b_j_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)(b + j)));
|
|
276
275
|
float32x4_t diff_j_vec = vsubq_f32(a_j_vec, b_j_vec);
|
|
277
|
-
float32x4_t c_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const*)(c + i * n + j)));
|
|
276
|
+
float32x4_t c_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)(c + i * n + j)));
|
|
278
277
|
partial_sum_vec = vmlaq_f32(partial_sum_vec, diff_j_vec, c_vec);
|
|
279
278
|
}
|
|
280
279
|
sum_vec = vmlaq_f32(sum_vec, diff_i_vec, partial_sum_vec);
|
|
@@ -310,15 +309,15 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_neon(simsimd_f16_t const* a, simsimd
|
|
|
310
309
|
#pragma GCC target("arch=armv8.6-a+simd+bf16")
|
|
311
310
|
#pragma clang attribute push(__attribute__((target("arch=armv8.6-a+simd+bf16"))), apply_to = function)
|
|
312
311
|
|
|
313
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_bf16_neon(simsimd_bf16_t const*
|
|
314
|
-
simsimd_bf16_t const*
|
|
312
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_bf16_neon(simsimd_bf16_t const *a, simsimd_bf16_t const *b,
|
|
313
|
+
simsimd_bf16_t const *c, simsimd_size_t n, simsimd_distance_t *result) {
|
|
315
314
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
316
315
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
317
316
|
float32x4_t a_vec = vdupq_n_f32(simsimd_bf16_to_f32(a + i));
|
|
318
317
|
float32x4_t partial_sum_vec = vdupq_n_f32(0);
|
|
319
318
|
for (simsimd_size_t j = 0; j + 8 <= n; j += 8) {
|
|
320
|
-
bfloat16x8_t b_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const*)(b + j));
|
|
321
|
-
bfloat16x8_t c_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const*)(c + i * n + j));
|
|
319
|
+
bfloat16x8_t b_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const *)(b + j));
|
|
320
|
+
bfloat16x8_t c_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const *)(c + i * n + j));
|
|
322
321
|
partial_sum_vec = vbfdotq_f32(partial_sum_vec, b_vec, c_vec);
|
|
323
322
|
}
|
|
324
323
|
sum_vec = vmlaq_f32(sum_vec, a_vec, partial_sum_vec);
|
|
@@ -341,9 +340,9 @@ SIMSIMD_PUBLIC void simsimd_bilinear_bf16_neon(simsimd_bf16_t const* a, simsimd_
|
|
|
341
340
|
*result = sum;
|
|
342
341
|
}
|
|
343
342
|
|
|
344
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_neon(simsimd_bf16_t const*
|
|
345
|
-
simsimd_bf16_t const*
|
|
346
|
-
simsimd_distance_t*
|
|
343
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_neon(simsimd_bf16_t const *a, simsimd_bf16_t const *b,
|
|
344
|
+
simsimd_bf16_t const *c, simsimd_size_t n,
|
|
345
|
+
simsimd_distance_t *result) {
|
|
347
346
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
348
347
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
349
348
|
simsimd_f32_t a_i = simsimd_bf16_to_f32(a + i);
|
|
@@ -351,8 +350,8 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_neon(simsimd_bf16_t const* a, simsi
|
|
|
351
350
|
float32x4_t diff_i_vec = vdupq_n_f32(a_i - b_i);
|
|
352
351
|
float32x4_t partial_sum_vec = vdupq_n_f32(0);
|
|
353
352
|
for (simsimd_size_t j = 0; j + 8 <= n; j += 8) {
|
|
354
|
-
bfloat16x8_t a_j_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const*)(a + j));
|
|
355
|
-
bfloat16x8_t b_j_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const*)(b + j));
|
|
353
|
+
bfloat16x8_t a_j_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const *)(a + j));
|
|
354
|
+
bfloat16x8_t b_j_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const *)(b + j));
|
|
356
355
|
|
|
357
356
|
// Arm NEON does not have a native subtraction instruction for `bf16`,
|
|
358
357
|
// so we need to convert to `f32` first, subtract, and only then get back to `bf16`
|
|
@@ -365,7 +364,7 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_neon(simsimd_bf16_t const* a, simsi
|
|
|
365
364
|
float32x4_t diff_j_vec_low = vsubq_f32(a_j_vec_low, b_j_vec_low);
|
|
366
365
|
bfloat16x8_t diff_j_vec = vcombine_bf16(vcvt_bf16_f32(diff_j_vec_low), vcvt_bf16_f32(diff_j_vec_high));
|
|
367
366
|
|
|
368
|
-
bfloat16x8_t c_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const*)(c + i * n + j));
|
|
367
|
+
bfloat16x8_t c_vec = vld1q_bf16((simsimd_bf16_for_arm_simd_t const *)(c + i * n + j));
|
|
369
368
|
partial_sum_vec = vbfdotq_f32(partial_sum_vec, diff_j_vec, c_vec);
|
|
370
369
|
}
|
|
371
370
|
sum_vec = vmlaq_f32(sum_vec, diff_i_vec, partial_sum_vec);
|
|
@@ -405,23 +404,23 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_neon(simsimd_bf16_t const* a, simsi
|
|
|
405
404
|
#pragma GCC pop_options
|
|
406
405
|
#endif // SIMSIMD_TARGET_NEON_BF16
|
|
407
406
|
|
|
408
|
-
#endif //
|
|
407
|
+
#endif // _SIMSIMD_TARGET_ARM
|
|
409
408
|
|
|
410
|
-
#if
|
|
409
|
+
#if _SIMSIMD_TARGET_X86
|
|
411
410
|
#if SIMSIMD_TARGET_HASWELL
|
|
412
411
|
#pragma GCC push_options
|
|
413
412
|
#pragma GCC target("avx2", "f16c", "fma")
|
|
414
413
|
#pragma clang attribute push(__attribute__((target("avx2,f16c,fma"))), apply_to = function)
|
|
415
414
|
|
|
416
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f16_haswell(simsimd_f16_t const*
|
|
417
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
415
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f16_haswell(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
416
|
+
simsimd_size_t n, simsimd_distance_t *result) {
|
|
418
417
|
__m256 sum_vec = _mm256_setzero_ps();
|
|
419
418
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
420
|
-
__m256 a_vec = _mm256_cvtph_ps(_mm_set1_epi16(*(short const*)(a + i)));
|
|
419
|
+
__m256 a_vec = _mm256_cvtph_ps(_mm_set1_epi16(*(short const *)(a + i)));
|
|
421
420
|
__m256 partial_sum_vec = _mm256_setzero_ps();
|
|
422
421
|
for (simsimd_size_t j = 0; j + 8 <= n; j += 8) {
|
|
423
|
-
__m256 b_vec = _mm256_cvtph_ps(
|
|
424
|
-
__m256 c_vec = _mm256_cvtph_ps(
|
|
422
|
+
__m256 b_vec = _mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)(b + j)));
|
|
423
|
+
__m256 c_vec = _mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)(c + i * n + j)));
|
|
425
424
|
partial_sum_vec = _mm256_fmadd_ps(b_vec, c_vec, partial_sum_vec);
|
|
426
425
|
}
|
|
427
426
|
sum_vec = _mm256_fmadd_ps(a_vec, partial_sum_vec, sum_vec);
|
|
@@ -433,7 +432,7 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16_haswell(simsimd_f16_t const* a, simsimd
|
|
|
433
432
|
simsimd_size_t tail_start = n - tail_length;
|
|
434
433
|
if (tail_length) {
|
|
435
434
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
436
|
-
simsimd_f32_t a_i = _mm256_cvtss_f32(_mm256_cvtph_ps(_mm_set1_epi16(*(short const*)(a + i))));
|
|
435
|
+
simsimd_f32_t a_i = _mm256_cvtss_f32(_mm256_cvtph_ps(_mm_set1_epi16(*(short const *)(a + i))));
|
|
437
436
|
__m256 b_vec = _simsimd_partial_load_f16x8_haswell(b + tail_start, tail_length);
|
|
438
437
|
__m256 c_vec = _simsimd_partial_load_f16x8_haswell(c + i * n + tail_start, tail_length);
|
|
439
438
|
simsimd_f32_t partial_sum = _simsimd_reduce_f32x8_haswell(_mm256_mul_ps(b_vec, c_vec));
|
|
@@ -444,20 +443,20 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16_haswell(simsimd_f16_t const* a, simsimd
|
|
|
444
443
|
*result = sum;
|
|
445
444
|
}
|
|
446
445
|
|
|
447
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_haswell(simsimd_f16_t const*
|
|
448
|
-
simsimd_f16_t const*
|
|
449
|
-
simsimd_distance_t*
|
|
446
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_haswell(simsimd_f16_t const *a, simsimd_f16_t const *b,
|
|
447
|
+
simsimd_f16_t const *c, simsimd_size_t n,
|
|
448
|
+
simsimd_distance_t *result) {
|
|
450
449
|
__m256 sum_vec = _mm256_setzero_ps();
|
|
451
450
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
452
|
-
__m256 diff_i_vec = _mm256_sub_ps(
|
|
453
|
-
_mm256_cvtph_ps(_mm_set1_epi16(*(short const*)(a + i))), //
|
|
454
|
-
_mm256_cvtph_ps(_mm_set1_epi16(*(short const*)(b + i))));
|
|
451
|
+
__m256 diff_i_vec = _mm256_sub_ps( //
|
|
452
|
+
_mm256_cvtph_ps(_mm_set1_epi16(*(short const *)(a + i))), //
|
|
453
|
+
_mm256_cvtph_ps(_mm_set1_epi16(*(short const *)(b + i))));
|
|
455
454
|
__m256 partial_sum_vec = _mm256_setzero_ps();
|
|
456
455
|
for (simsimd_size_t j = 0; j + 8 <= n; j += 8) {
|
|
457
456
|
__m256 diff_j_vec = _mm256_sub_ps( //
|
|
458
|
-
_mm256_cvtph_ps(
|
|
459
|
-
_mm256_cvtph_ps(
|
|
460
|
-
__m256 c_vec = _mm256_cvtph_ps(
|
|
457
|
+
_mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)(a + j))),
|
|
458
|
+
_mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)(b + j))));
|
|
459
|
+
__m256 c_vec = _mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)(c + i * n + j)));
|
|
461
460
|
partial_sum_vec = _mm256_fmadd_ps(diff_j_vec, c_vec, partial_sum_vec);
|
|
462
461
|
}
|
|
463
462
|
sum_vec = _mm256_fmadd_ps(diff_i_vec, partial_sum_vec, sum_vec);
|
|
@@ -469,9 +468,9 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_haswell(simsimd_f16_t const* a, sims
|
|
|
469
468
|
simsimd_size_t tail_start = n - tail_length;
|
|
470
469
|
if (tail_length) {
|
|
471
470
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
472
|
-
simsimd_f32_t diff_i = _mm256_cvtss_f32(_mm256_sub_ps(
|
|
473
|
-
_mm256_cvtph_ps(_mm_set1_epi16(*(short const*)(a + i))), //
|
|
474
|
-
_mm256_cvtph_ps(_mm_set1_epi16(*(short const*)(b + i)))));
|
|
471
|
+
simsimd_f32_t diff_i = _mm256_cvtss_f32(_mm256_sub_ps( //
|
|
472
|
+
_mm256_cvtph_ps(_mm_set1_epi16(*(short const *)(a + i))), //
|
|
473
|
+
_mm256_cvtph_ps(_mm_set1_epi16(*(short const *)(b + i)))));
|
|
475
474
|
__m256 diff_j_vec = _mm256_sub_ps( //
|
|
476
475
|
_simsimd_partial_load_f16x8_haswell(a + tail_start, tail_length),
|
|
477
476
|
_simsimd_partial_load_f16x8_haswell(b + tail_start, tail_length));
|
|
@@ -484,17 +483,17 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_haswell(simsimd_f16_t const* a, sims
|
|
|
484
483
|
*result = _simsimd_sqrt_f32_haswell(sum);
|
|
485
484
|
}
|
|
486
485
|
|
|
487
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_bf16_haswell(simsimd_bf16_t const*
|
|
488
|
-
simsimd_bf16_t const*
|
|
489
|
-
simsimd_distance_t*
|
|
486
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_bf16_haswell(simsimd_bf16_t const *a, simsimd_bf16_t const *b,
|
|
487
|
+
simsimd_bf16_t const *c, simsimd_size_t n,
|
|
488
|
+
simsimd_distance_t *result) {
|
|
490
489
|
__m256 sum_vec = _mm256_setzero_ps();
|
|
491
490
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
492
491
|
// The `simsimd_bf16_to_f32` is cheaper than `_simsimd_bf16x8_to_f32x8_haswell`
|
|
493
492
|
__m256 a_vec = _mm256_set1_ps(simsimd_bf16_to_f32(a + i));
|
|
494
493
|
__m256 partial_sum_vec = _mm256_setzero_ps();
|
|
495
494
|
for (simsimd_size_t j = 0; j + 8 <= n; j += 8) {
|
|
496
|
-
__m256 b_vec = _simsimd_bf16x8_to_f32x8_haswell(
|
|
497
|
-
__m256 c_vec = _simsimd_bf16x8_to_f32x8_haswell(
|
|
495
|
+
__m256 b_vec = _simsimd_bf16x8_to_f32x8_haswell(_mm_lddqu_si128((__m128i const *)(b + j)));
|
|
496
|
+
__m256 c_vec = _simsimd_bf16x8_to_f32x8_haswell(_mm_lddqu_si128((__m128i const *)(c + i * n + j)));
|
|
498
497
|
partial_sum_vec = _mm256_fmadd_ps(b_vec, c_vec, partial_sum_vec);
|
|
499
498
|
}
|
|
500
499
|
sum_vec = _mm256_fmadd_ps(a_vec, partial_sum_vec, sum_vec);
|
|
@@ -519,9 +518,9 @@ SIMSIMD_PUBLIC void simsimd_bilinear_bf16_haswell(simsimd_bf16_t const* a, simsi
|
|
|
519
518
|
*result = sum;
|
|
520
519
|
}
|
|
521
520
|
|
|
522
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_haswell(simsimd_bf16_t const*
|
|
523
|
-
simsimd_bf16_t const*
|
|
524
|
-
simsimd_distance_t*
|
|
521
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_haswell(simsimd_bf16_t const *a, simsimd_bf16_t const *b,
|
|
522
|
+
simsimd_bf16_t const *c, simsimd_size_t n,
|
|
523
|
+
simsimd_distance_t *result) {
|
|
525
524
|
__m256 sum_vec = _mm256_setzero_ps();
|
|
526
525
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
527
526
|
__m256 diff_i_vec = _mm256_sub_ps( //
|
|
@@ -529,10 +528,10 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_haswell(simsimd_bf16_t const* a, si
|
|
|
529
528
|
_mm256_set1_ps(simsimd_bf16_to_f32(b + i)));
|
|
530
529
|
__m256 partial_sum_vec = _mm256_setzero_ps();
|
|
531
530
|
for (simsimd_size_t j = 0; j + 8 <= n; j += 8) {
|
|
532
|
-
__m256 diff_j_vec = _mm256_sub_ps(
|
|
533
|
-
_simsimd_bf16x8_to_f32x8_haswell(
|
|
534
|
-
_simsimd_bf16x8_to_f32x8_haswell(
|
|
535
|
-
__m256 c_vec = _simsimd_bf16x8_to_f32x8_haswell(
|
|
531
|
+
__m256 diff_j_vec = _mm256_sub_ps( //
|
|
532
|
+
_simsimd_bf16x8_to_f32x8_haswell(_mm_lddqu_si128((__m128i const *)(a + j))), //
|
|
533
|
+
_simsimd_bf16x8_to_f32x8_haswell(_mm_lddqu_si128((__m128i const *)(b + j))));
|
|
534
|
+
__m256 c_vec = _simsimd_bf16x8_to_f32x8_haswell(_mm_lddqu_si128((__m128i const *)(c + i * n + j)));
|
|
536
535
|
partial_sum_vec = _mm256_fmadd_ps(diff_j_vec, c_vec, partial_sum_vec);
|
|
537
536
|
}
|
|
538
537
|
sum_vec = _mm256_fmadd_ps(diff_i_vec, partial_sum_vec, sum_vec);
|
|
@@ -567,8 +566,8 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_haswell(simsimd_bf16_t const* a, si
|
|
|
567
566
|
#pragma GCC target("avx2", "avx512f", "avx512vl", "bmi2")
|
|
568
567
|
#pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2"))), apply_to = function)
|
|
569
568
|
|
|
570
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f32_skylake(simsimd_f32_t const*
|
|
571
|
-
simsimd_size_t n, simsimd_distance_t*
|
|
569
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f32_skylake(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
570
|
+
simsimd_size_t n, simsimd_distance_t *result) {
|
|
572
571
|
simsimd_size_t tail_length = n % 16;
|
|
573
572
|
simsimd_size_t tail_start = n - tail_length;
|
|
574
573
|
__m512 sum_vec = _mm512_setzero_ps();
|
|
@@ -584,23 +583,23 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f32_skylake(simsimd_f32_t const* a, simsimd
|
|
|
584
583
|
if (j + 16 <= n) {
|
|
585
584
|
b_vec = _mm512_loadu_ps(b + j);
|
|
586
585
|
c_vec = _mm512_loadu_ps(c + i * n + j);
|
|
587
|
-
}
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
588
|
b_vec = _mm512_maskz_loadu_ps(tail_mask, b + tail_start);
|
|
589
589
|
c_vec = _mm512_maskz_loadu_ps(tail_mask, c + i * n + tail_start);
|
|
590
590
|
}
|
|
591
591
|
partial_sum_vec = _mm512_fmadd_ps(b_vec, c_vec, partial_sum_vec);
|
|
592
592
|
j += 16;
|
|
593
|
-
if (j < n)
|
|
594
|
-
goto simsimd_bilinear_f32_skylake_cycle;
|
|
593
|
+
if (j < n) goto simsimd_bilinear_f32_skylake_cycle;
|
|
595
594
|
sum_vec = _mm512_fmadd_ps(a_vec, partial_sum_vec, sum_vec);
|
|
596
595
|
}
|
|
597
596
|
|
|
598
597
|
*result = _mm512_reduce_add_ps(sum_vec);
|
|
599
598
|
}
|
|
600
599
|
|
|
601
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_skylake(simsimd_f32_t const*
|
|
602
|
-
simsimd_f32_t const*
|
|
603
|
-
simsimd_distance_t*
|
|
600
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_skylake(simsimd_f32_t const *a, simsimd_f32_t const *b,
|
|
601
|
+
simsimd_f32_t const *c, simsimd_size_t n,
|
|
602
|
+
simsimd_distance_t *result) {
|
|
604
603
|
simsimd_size_t tail_length = n % 16;
|
|
605
604
|
simsimd_size_t tail_start = n - tail_length;
|
|
606
605
|
__m512 sum_vec = _mm512_setzero_ps();
|
|
@@ -618,7 +617,8 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_skylake(simsimd_f32_t const* a, sims
|
|
|
618
617
|
a_j_vec = _mm512_loadu_ps(a + j);
|
|
619
618
|
b_j_vec = _mm512_loadu_ps(b + j);
|
|
620
619
|
c_vec = _mm512_loadu_ps(c + i * n + j);
|
|
621
|
-
}
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
622
|
a_j_vec = _mm512_maskz_loadu_ps(tail_mask, a + tail_start);
|
|
623
623
|
b_j_vec = _mm512_maskz_loadu_ps(tail_mask, b + tail_start);
|
|
624
624
|
c_vec = _mm512_maskz_loadu_ps(tail_mask, c + i * n + tail_start);
|
|
@@ -626,8 +626,7 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_skylake(simsimd_f32_t const* a, sims
|
|
|
626
626
|
diff_j_vec = _mm512_sub_ps(a_j_vec, b_j_vec);
|
|
627
627
|
partial_sum_vec = _mm512_fmadd_ps(diff_j_vec, c_vec, partial_sum_vec);
|
|
628
628
|
j += 16;
|
|
629
|
-
if (j < n)
|
|
630
|
-
goto simsimd_bilinear_f32_skylake_cycle;
|
|
629
|
+
if (j < n) goto simsimd_bilinear_f32_skylake_cycle;
|
|
631
630
|
sum_vec = _mm512_fmadd_ps(diff_i_vec, partial_sum_vec, sum_vec);
|
|
632
631
|
}
|
|
633
632
|
|
|
@@ -641,11 +640,11 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f32_skylake(simsimd_f32_t const* a, sims
|
|
|
641
640
|
#if SIMSIMD_TARGET_GENOA
|
|
642
641
|
#pragma GCC push_options
|
|
643
642
|
#pragma GCC target("avx2", "avx512f", "avx512vl", "bmi2", "avx512bw", "avx512bf16")
|
|
644
|
-
#pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2,avx512bw,avx512bf16"))),
|
|
643
|
+
#pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2,avx512bw,avx512bf16"))), \
|
|
645
644
|
apply_to = function)
|
|
646
645
|
|
|
647
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_bf16_genoa(simsimd_bf16_t const*
|
|
648
|
-
simsimd_bf16_t const*
|
|
646
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_bf16_genoa(simsimd_bf16_t const *a, simsimd_bf16_t const *b,
|
|
647
|
+
simsimd_bf16_t const *c, simsimd_size_t n, simsimd_distance_t *result) {
|
|
649
648
|
simsimd_size_t tail_length = n % 32;
|
|
650
649
|
simsimd_size_t tail_start = n - tail_length;
|
|
651
650
|
__m512 sum_vec = _mm512_setzero_ps();
|
|
@@ -661,23 +660,23 @@ SIMSIMD_PUBLIC void simsimd_bilinear_bf16_genoa(simsimd_bf16_t const* a, simsimd
|
|
|
661
660
|
if (j + 32 <= n) {
|
|
662
661
|
b_vec = _mm512_loadu_epi16(b + j);
|
|
663
662
|
c_vec = _mm512_loadu_epi16(c + i * n + j);
|
|
664
|
-
}
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
665
|
b_vec = _mm512_maskz_loadu_epi16(tail_mask, b + tail_start);
|
|
666
666
|
c_vec = _mm512_maskz_loadu_epi16(tail_mask, c + i * n + tail_start);
|
|
667
667
|
}
|
|
668
668
|
partial_sum_vec = _mm512_dpbf16_ps(partial_sum_vec, (__m512bh)(b_vec), (__m512bh)(c_vec));
|
|
669
669
|
j += 32;
|
|
670
|
-
if (j < n)
|
|
671
|
-
goto simsimd_bilinear_bf16_genoa_cycle;
|
|
670
|
+
if (j < n) goto simsimd_bilinear_bf16_genoa_cycle;
|
|
672
671
|
sum_vec = _mm512_fmadd_ps(a_vec, partial_sum_vec, sum_vec);
|
|
673
672
|
}
|
|
674
673
|
|
|
675
674
|
*result = _mm512_reduce_add_ps(sum_vec);
|
|
676
675
|
}
|
|
677
676
|
|
|
678
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_genoa(simsimd_bf16_t const*
|
|
679
|
-
simsimd_bf16_t const*
|
|
680
|
-
simsimd_distance_t*
|
|
677
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_genoa(simsimd_bf16_t const *a, simsimd_bf16_t const *b,
|
|
678
|
+
simsimd_bf16_t const *c, simsimd_size_t n,
|
|
679
|
+
simsimd_distance_t *result) {
|
|
681
680
|
simsimd_size_t tail_length = n % 32;
|
|
682
681
|
simsimd_size_t tail_start = n - tail_length;
|
|
683
682
|
__m512 sum_vec = _mm512_setzero_ps();
|
|
@@ -695,7 +694,8 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_genoa(simsimd_bf16_t const* a, sims
|
|
|
695
694
|
a_j_vec = _mm512_loadu_epi16(a + j);
|
|
696
695
|
b_j_vec = _mm512_loadu_epi16(b + j);
|
|
697
696
|
c_vec = _mm512_loadu_epi16(c + i * n + j);
|
|
698
|
-
}
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
699
|
a_j_vec = _mm512_maskz_loadu_epi16(tail_mask, a + tail_start);
|
|
700
700
|
b_j_vec = _mm512_maskz_loadu_epi16(tail_mask, b + tail_start);
|
|
701
701
|
c_vec = _mm512_maskz_loadu_epi16(tail_mask, c + i * n + tail_start);
|
|
@@ -703,8 +703,7 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_genoa(simsimd_bf16_t const* a, sims
|
|
|
703
703
|
diff_j_vec = _simsimd_substract_bf16x32_genoa(a_j_vec, b_j_vec);
|
|
704
704
|
partial_sum_vec = _mm512_dpbf16_ps(partial_sum_vec, (__m512bh)(diff_j_vec), (__m512bh)(c_vec));
|
|
705
705
|
j += 32;
|
|
706
|
-
if (j < n)
|
|
707
|
-
goto simsimd_mahalanobis_bf16_genoa_cycle;
|
|
706
|
+
if (j < n) goto simsimd_mahalanobis_bf16_genoa_cycle;
|
|
708
707
|
sum_vec = _mm512_fmadd_ps(diff_i_vec, partial_sum_vec, sum_vec);
|
|
709
708
|
}
|
|
710
709
|
|
|
@@ -718,19 +717,19 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16_genoa(simsimd_bf16_t const* a, sims
|
|
|
718
717
|
#if SIMSIMD_TARGET_SAPPHIRE
|
|
719
718
|
#pragma GCC push_options
|
|
720
719
|
#pragma GCC target("avx2", "avx512f", "avx512vl", "bmi2", "avx512bw", "avx512fp16")
|
|
721
|
-
#pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2,avx512bw,avx512fp16"))),
|
|
720
|
+
#pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2,avx512bw,avx512fp16"))), \
|
|
722
721
|
apply_to = function)
|
|
723
722
|
|
|
724
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f16_sapphire(simsimd_f16_t const*
|
|
725
|
-
simsimd_f16_t const*
|
|
726
|
-
simsimd_distance_t*
|
|
723
|
+
SIMSIMD_PUBLIC void simsimd_bilinear_f16_sapphire(simsimd_f16_t const *a, simsimd_f16_t const *b,
|
|
724
|
+
simsimd_f16_t const *c, simsimd_size_t n,
|
|
725
|
+
simsimd_distance_t *result) {
|
|
727
726
|
simsimd_size_t tail_length = n % 32;
|
|
728
727
|
simsimd_size_t tail_start = n - tail_length;
|
|
729
728
|
__m512h sum_vec = _mm512_setzero_ph();
|
|
730
729
|
__mmask32 tail_mask = (__mmask32)_bzhi_u32(0xFFFFFFFF, tail_length);
|
|
731
730
|
|
|
732
731
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
733
|
-
__m512h a_vec = _mm512_castsi512_ph(_mm512_set1_epi16(*(short const*)(a + i)));
|
|
732
|
+
__m512h a_vec = _mm512_castsi512_ph(_mm512_set1_epi16(*(short const *)(a + i)));
|
|
734
733
|
__m512h partial_sum_vec = _mm512_setzero_ph();
|
|
735
734
|
__m512i b_vec, c_vec;
|
|
736
735
|
simsimd_size_t j = 0;
|
|
@@ -739,31 +738,31 @@ SIMSIMD_PUBLIC void simsimd_bilinear_f16_sapphire(simsimd_f16_t const* a, simsim
|
|
|
739
738
|
if (j + 32 <= n) {
|
|
740
739
|
b_vec = _mm512_loadu_epi16(b + j);
|
|
741
740
|
c_vec = _mm512_loadu_epi16(c + i * n + j);
|
|
742
|
-
}
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
743
|
b_vec = _mm512_maskz_loadu_epi16(tail_mask, b + tail_start);
|
|
744
744
|
c_vec = _mm512_maskz_loadu_epi16(tail_mask, c + i * n + tail_start);
|
|
745
745
|
}
|
|
746
746
|
partial_sum_vec = _mm512_fmadd_ph(_mm512_castsi512_ph(b_vec), _mm512_castsi512_ph(c_vec), partial_sum_vec);
|
|
747
747
|
j += 32;
|
|
748
|
-
if (j < n)
|
|
749
|
-
goto simsimd_bilinear_f16_sapphire_cycle;
|
|
748
|
+
if (j < n) goto simsimd_bilinear_f16_sapphire_cycle;
|
|
750
749
|
sum_vec = _mm512_fmadd_ph(a_vec, partial_sum_vec, sum_vec);
|
|
751
750
|
}
|
|
752
751
|
|
|
753
752
|
*result = _mm512_reduce_add_ph(sum_vec);
|
|
754
753
|
}
|
|
755
754
|
|
|
756
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_sapphire(simsimd_f16_t const*
|
|
757
|
-
simsimd_f16_t const*
|
|
758
|
-
simsimd_distance_t*
|
|
755
|
+
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_sapphire(simsimd_f16_t const *a, simsimd_f16_t const *b,
|
|
756
|
+
simsimd_f16_t const *c, simsimd_size_t n,
|
|
757
|
+
simsimd_distance_t *result) {
|
|
759
758
|
simsimd_size_t tail_length = n % 32;
|
|
760
759
|
simsimd_size_t tail_start = n - tail_length;
|
|
761
760
|
__m512h sum_vec = _mm512_setzero_ph();
|
|
762
761
|
__mmask32 tail_mask = (__mmask32)_bzhi_u32(0xFFFFFFFF, tail_length);
|
|
763
762
|
|
|
764
763
|
for (simsimd_size_t i = 0; i != n; ++i) {
|
|
765
|
-
__m512h a_i_vec = _mm512_castsi512_ph(_mm512_set1_epi16(*(short const*)(a + i)));
|
|
766
|
-
__m512h b_i_vec = _mm512_castsi512_ph(_mm512_set1_epi16(*(short const*)(b + i)));
|
|
764
|
+
__m512h a_i_vec = _mm512_castsi512_ph(_mm512_set1_epi16(*(short const *)(a + i)));
|
|
765
|
+
__m512h b_i_vec = _mm512_castsi512_ph(_mm512_set1_epi16(*(short const *)(b + i)));
|
|
767
766
|
__m512h diff_i_vec = _mm512_sub_ph(a_i_vec, b_i_vec);
|
|
768
767
|
__m512h partial_sum_vec = _mm512_setzero_ph();
|
|
769
768
|
__m512h diff_j_vec;
|
|
@@ -776,7 +775,8 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_sapphire(simsimd_f16_t const* a, sim
|
|
|
776
775
|
a_j_vec = _mm512_loadu_epi16(a + j);
|
|
777
776
|
b_j_vec = _mm512_loadu_epi16(b + j);
|
|
778
777
|
c_vec = _mm512_loadu_epi16(c + i * n + j);
|
|
779
|
-
}
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
780
|
a_j_vec = _mm512_maskz_loadu_epi16(tail_mask, a + tail_start);
|
|
781
781
|
b_j_vec = _mm512_maskz_loadu_epi16(tail_mask, b + tail_start);
|
|
782
782
|
c_vec = _mm512_maskz_loadu_epi16(tail_mask, c + i * n + tail_start);
|
|
@@ -784,8 +784,7 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_sapphire(simsimd_f16_t const* a, sim
|
|
|
784
784
|
diff_j_vec = _mm512_sub_ph(_mm512_castsi512_ph(a_j_vec), _mm512_castsi512_ph(b_j_vec));
|
|
785
785
|
partial_sum_vec = _mm512_fmadd_ph(diff_j_vec, _mm512_castsi512_ph(c_vec), partial_sum_vec);
|
|
786
786
|
j += 32;
|
|
787
|
-
if (j < n)
|
|
788
|
-
goto simsimd_mahalanobis_f16_sapphire_cycle;
|
|
787
|
+
if (j < n) goto simsimd_mahalanobis_f16_sapphire_cycle;
|
|
789
788
|
sum_vec = _mm512_fmadd_ph(diff_i_vec, partial_sum_vec, sum_vec);
|
|
790
789
|
}
|
|
791
790
|
|
|
@@ -795,7 +794,7 @@ SIMSIMD_PUBLIC void simsimd_mahalanobis_f16_sapphire(simsimd_f16_t const* a, sim
|
|
|
795
794
|
#pragma clang attribute pop
|
|
796
795
|
#pragma GCC pop_options
|
|
797
796
|
#endif // SIMSIMD_TARGET_SAPPHIRE
|
|
798
|
-
#endif //
|
|
797
|
+
#endif // _SIMSIMD_TARGET_X86
|
|
799
798
|
|
|
800
799
|
#ifdef __cplusplus
|
|
801
800
|
}
|