usearch 2.7.6 → 2.8.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/.dockerignore +93 -0
- package/.github/workflows/Dockerfile.libs +6 -2
- package/.github/workflows/prerelease.yml +242 -245
- package/.github/workflows/release.yml +390 -356
- package/.gitignore +1 -0
- package/.vscode/settings.json +3 -1
- package/CITATION.cff +1 -1
- package/CMakeLists.txt +35 -5
- package/Cargo.toml +1 -1
- package/README.md +1 -1
- package/build.gradle +6 -0
- package/c/README.md +3 -3
- package/c/lib.cpp +75 -11
- package/c/usearch.h +22 -1
- package/conanfile.py +1 -1
- package/cpp/README.md +2 -1
- package/cpp/bench.cpp +4 -1
- package/cpp/test.cpp +12 -12
- package/csharp/nuget/nuget-package.props +1 -1
- package/docs/compilation.md +5 -13
- package/golang/lib.go +4 -1
- package/include/usearch/index.hpp +31 -30
- package/include/usearch/index_dense.hpp +49 -48
- package/include/usearch/index_plugins.hpp +91 -24
- package/java/cloud/unum/usearch/Index.java +118 -26
- package/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp +8 -8
- package/javascript/usearch.js +1 -0
- package/objc/USearchObjective.mm +4 -1
- package/objc/include/USearchObjective.h +1 -0
- package/package.json +1 -1
- package/python/lib.cpp +6 -6
- package/python/scripts/bench.ipynb +24 -2
- package/python/usearch/index.py +8 -3
- package/rust/lib.cpp +14 -12
- package/rust/lib.hpp +13 -13
- package/rust/lib.rs +46 -0
- package/setup.py +15 -3
- package/simsimd/.github/workflows/prerelease.yml +7 -8
- package/simsimd/.github/workflows/release.yml +18 -20
- package/simsimd/README.md +13 -8
- package/simsimd/binding.gyp +1 -1
- package/simsimd/cpp/bench.cxx +17 -3
- package/simsimd/include/simsimd/binary.h +1 -3
- package/simsimd/include/simsimd/probability.h +234 -361
- package/simsimd/include/simsimd/simsimd.h +95 -65
- package/simsimd/include/simsimd/spatial.h +0 -3
- package/simsimd/include/simsimd/types.h +12 -7
- package/simsimd/javascript/test.js +23 -5
- package/simsimd/package.json +2 -2
- package/wasmer.toml +1 -1
- package/wolfram/lib.cpp +1 -1
- package/csharp/eng/build_lib.sh +0 -65
- package/csharp/eng/clean.sh +0 -12
|
@@ -110,7 +110,7 @@ inline static simsimd_capability_t simsimd_capabilities() {
|
|
|
110
110
|
#if SIMSIMD_TARGET_X86
|
|
111
111
|
|
|
112
112
|
/// The states of 4 registers populated for a specific "cpuid" assmebly call
|
|
113
|
-
union {
|
|
113
|
+
union four_registers_t {
|
|
114
114
|
int array[4];
|
|
115
115
|
struct {
|
|
116
116
|
unsigned eax, ebx, ecx, edx;
|
|
@@ -176,6 +176,11 @@ inline static simsimd_capability_t simsimd_capabilities() {
|
|
|
176
176
|
return simsimd_cap_serial_k;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
#pragma GCC diagnostic push
|
|
180
|
+
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
|
181
|
+
#pragma clang diagnostic push
|
|
182
|
+
#pragma clang diagnostic ignored "-Wcast-function-type"
|
|
183
|
+
|
|
179
184
|
/**
|
|
180
185
|
* @brief Determines the best suited metric implementation based on the given datatype,
|
|
181
186
|
* supported and allowed by hardware capabilities.
|
|
@@ -213,28 +218,33 @@ inline static void simsimd_find_metric_punned( //
|
|
|
213
218
|
#if SIMSIMD_TARGET_ARM_NEON
|
|
214
219
|
if (viable & simsimd_cap_arm_neon_k)
|
|
215
220
|
switch (kind) {
|
|
216
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_ip, *c = simsimd_cap_arm_neon_k;
|
|
217
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_cos, *c = simsimd_cap_arm_neon_k;
|
|
218
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_l2sq, *c = simsimd_cap_arm_neon_k;
|
|
219
|
-
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_js, *c = simsimd_cap_arm_neon_k;
|
|
220
|
-
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_kl, *c = simsimd_cap_arm_neon_k;
|
|
221
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_ip, *c = simsimd_cap_arm_neon_k; return;
|
|
222
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_cos, *c = simsimd_cap_arm_neon_k; return;
|
|
223
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_l2sq, *c = simsimd_cap_arm_neon_k; return;
|
|
224
|
+
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_js, *c = simsimd_cap_arm_neon_k; return;
|
|
225
|
+
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_kl, *c = simsimd_cap_arm_neon_k; return;
|
|
226
|
+
default: break;
|
|
221
227
|
}
|
|
222
228
|
#endif
|
|
223
229
|
#if SIMSIMD_TARGET_X86_AVX512
|
|
224
230
|
if (viable & simsimd_cap_x86_avx512_k)
|
|
225
231
|
switch (kind) {
|
|
226
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_ip, *c = simsimd_cap_x86_avx512_k;
|
|
227
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_cos, *c = simsimd_cap_x86_avx512_k;
|
|
228
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_l2sq, *c = simsimd_cap_x86_avx512_k;
|
|
232
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_ip, *c = simsimd_cap_x86_avx512_k; return;
|
|
233
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_cos, *c = simsimd_cap_x86_avx512_k; return;
|
|
234
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_l2sq, *c = simsimd_cap_x86_avx512_k; return;
|
|
235
|
+
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_js, *c = simsimd_cap_x86_avx512_k; return;
|
|
236
|
+
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_kl, *c = simsimd_cap_x86_avx512_k; return;
|
|
237
|
+
default: break;
|
|
229
238
|
}
|
|
230
239
|
#endif
|
|
231
240
|
if (viable & simsimd_cap_serial_k)
|
|
232
241
|
switch (kind) {
|
|
233
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_ip, *c = simsimd_cap_serial_k;
|
|
234
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_cos, *c = simsimd_cap_serial_k;
|
|
235
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_l2sq, *c = simsimd_cap_serial_k;
|
|
236
|
-
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_js, *c = simsimd_cap_serial_k;
|
|
237
|
-
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_kl, *c = simsimd_cap_serial_k;
|
|
242
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_ip, *c = simsimd_cap_serial_k; return;
|
|
243
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_cos, *c = simsimd_cap_serial_k; return;
|
|
244
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_l2sq, *c = simsimd_cap_serial_k; return;
|
|
245
|
+
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_js, *c = simsimd_cap_serial_k; return;
|
|
246
|
+
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_kl, *c = simsimd_cap_serial_k; return;
|
|
247
|
+
default: break;
|
|
238
248
|
}
|
|
239
249
|
|
|
240
250
|
break;
|
|
@@ -242,48 +252,57 @@ inline static void simsimd_find_metric_punned( //
|
|
|
242
252
|
// Half-precision floating-point vectors
|
|
243
253
|
case simsimd_datatype_f16_k:
|
|
244
254
|
|
|
245
|
-
#if SIMSIMD_TARGET_ARM_NEON
|
|
246
|
-
if (viable & simsimd_cap_arm_neon_k)
|
|
247
|
-
switch (kind) {
|
|
248
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_ip, *c = simsimd_cap_arm_neon_k; break;
|
|
249
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_cos, *c = simsimd_cap_arm_neon_k; break;
|
|
250
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_l2sq, *c = simsimd_cap_arm_neon_k; break;
|
|
251
|
-
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_js, *c = simsimd_cap_arm_neon_k; break;
|
|
252
|
-
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_kl, *c = simsimd_cap_arm_neon_k; break;
|
|
253
|
-
}
|
|
254
|
-
#endif
|
|
255
255
|
#if SIMSIMD_TARGET_ARM_SVE
|
|
256
256
|
if (viable & simsimd_cap_arm_sve_k)
|
|
257
257
|
switch (kind) {
|
|
258
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_ip, *c = simsimd_cap_arm_sve_k;
|
|
259
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_cos, *c = simsimd_cap_arm_sve_k;
|
|
260
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_l2sq, *c = simsimd_cap_arm_sve_k;
|
|
258
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_ip, *c = simsimd_cap_arm_sve_k; return;
|
|
259
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_cos, *c = simsimd_cap_arm_sve_k; return;
|
|
260
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_l2sq, *c = simsimd_cap_arm_sve_k; return;
|
|
261
|
+
default: break;
|
|
261
262
|
}
|
|
262
263
|
#endif
|
|
263
|
-
#if
|
|
264
|
-
if (viable &
|
|
264
|
+
#if SIMSIMD_TARGET_ARM_NEON
|
|
265
|
+
if (viable & simsimd_cap_arm_neon_k)
|
|
265
266
|
switch (kind) {
|
|
266
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&
|
|
267
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&
|
|
268
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&
|
|
267
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_ip, *c = simsimd_cap_arm_neon_k; return;
|
|
268
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_cos, *c = simsimd_cap_arm_neon_k; return;
|
|
269
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_l2sq, *c = simsimd_cap_arm_neon_k; return;
|
|
270
|
+
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_js, *c = simsimd_cap_arm_neon_k; return;
|
|
271
|
+
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_kl, *c = simsimd_cap_arm_neon_k; return;
|
|
272
|
+
default: break;
|
|
269
273
|
}
|
|
270
274
|
#endif
|
|
271
275
|
#if SIMSIMD_TARGET_X86_AVX512
|
|
272
|
-
if (viable &
|
|
276
|
+
if (viable & simsimd_cap_x86_avx512fp16_k)
|
|
277
|
+
switch (kind) {
|
|
278
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_ip, *c = simsimd_cap_x86_avx512fp16_k; return;
|
|
279
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_cos, *c = simsimd_cap_x86_avx512fp16_k; return;
|
|
280
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_l2sq, *c = simsimd_cap_x86_avx512fp16_k; return;
|
|
281
|
+
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_js, *c = simsimd_cap_x86_avx512fp16_k; return;
|
|
282
|
+
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_kl, *c = simsimd_cap_x86_avx512fp16_k; return;
|
|
283
|
+
default: break;
|
|
284
|
+
}
|
|
285
|
+
#endif
|
|
286
|
+
#if SIMSIMD_TARGET_X86_AVX2
|
|
287
|
+
if (viable & simsimd_cap_x86_avx2fp16_k)
|
|
273
288
|
switch (kind) {
|
|
274
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&
|
|
275
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&
|
|
276
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&
|
|
289
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_ip, *c = simsimd_cap_x86_avx2fp16_k; return;
|
|
290
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_cos, *c = simsimd_cap_x86_avx2fp16_k; return;
|
|
291
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_l2sq, *c = simsimd_cap_x86_avx2fp16_k; return;
|
|
292
|
+
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_js, *c = simsimd_cap_x86_avx2fp16_k; return;
|
|
293
|
+
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_kl, *c = simsimd_cap_x86_avx2fp16_k; return;
|
|
294
|
+
default: break;
|
|
277
295
|
}
|
|
278
296
|
#endif
|
|
279
297
|
|
|
280
298
|
if (viable & simsimd_cap_serial_k)
|
|
281
299
|
switch (kind) {
|
|
282
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_ip, *c = simsimd_cap_serial_k;
|
|
283
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_cos, *c = simsimd_cap_serial_k;
|
|
284
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_l2sq, *c = simsimd_cap_serial_k;
|
|
285
|
-
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_js, *c = simsimd_cap_serial_k;
|
|
286
|
-
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_kl, *c = simsimd_cap_serial_k;
|
|
300
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_ip, *c = simsimd_cap_serial_k; return;
|
|
301
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_cos, *c = simsimd_cap_serial_k; return;
|
|
302
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_l2sq, *c = simsimd_cap_serial_k; return;
|
|
303
|
+
case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_js, *c = simsimd_cap_serial_k; return;
|
|
304
|
+
case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_kl, *c = simsimd_cap_serial_k; return;
|
|
305
|
+
default: break;
|
|
287
306
|
}
|
|
288
307
|
|
|
289
308
|
break;
|
|
@@ -293,33 +312,37 @@ inline static void simsimd_find_metric_punned( //
|
|
|
293
312
|
#if SIMSIMD_TARGET_ARM_NEON
|
|
294
313
|
if (viable & simsimd_cap_arm_neon_k)
|
|
295
314
|
switch (kind) {
|
|
296
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_ip, *c = simsimd_cap_arm_neon_k;
|
|
297
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_cos, *c = simsimd_cap_arm_neon_k;
|
|
298
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_l2sq, *c = simsimd_cap_arm_neon_k;
|
|
315
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_ip, *c = simsimd_cap_arm_neon_k; return;
|
|
316
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_cos, *c = simsimd_cap_arm_neon_k; return;
|
|
317
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_l2sq, *c = simsimd_cap_arm_neon_k; return;
|
|
318
|
+
default: break;
|
|
299
319
|
}
|
|
300
320
|
#endif
|
|
301
|
-
#if
|
|
302
|
-
if (viable &
|
|
321
|
+
#if SIMSIMD_TARGET_X86_AVX512
|
|
322
|
+
if (viable & simsimd_cap_x86_avx512_k)
|
|
303
323
|
switch (kind) {
|
|
304
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&
|
|
305
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&
|
|
306
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&
|
|
324
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_ip, *c = simsimd_cap_x86_avx512_k; return;
|
|
325
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_cos, *c = simsimd_cap_x86_avx512_k; return;
|
|
326
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_l2sq, *c = simsimd_cap_x86_avx512_k; return;
|
|
327
|
+
default: break;
|
|
307
328
|
}
|
|
308
329
|
#endif
|
|
309
|
-
#if
|
|
310
|
-
if (viable &
|
|
330
|
+
#if SIMSIMD_TARGET_X86_AVX2
|
|
331
|
+
if (viable & simsimd_cap_x86_avx2_k)
|
|
311
332
|
switch (kind) {
|
|
312
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&
|
|
313
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&
|
|
314
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&
|
|
333
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_i8_ip, *c = simsimd_cap_x86_avx2_k; return;
|
|
334
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_i8_cos, *c = simsimd_cap_x86_avx2_k; return;
|
|
335
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_i8_l2sq, *c = simsimd_cap_x86_avx2_k; return;
|
|
336
|
+
default: break;
|
|
315
337
|
}
|
|
316
338
|
#endif
|
|
317
339
|
|
|
318
340
|
if (viable & simsimd_cap_serial_k)
|
|
319
341
|
switch (kind) {
|
|
320
|
-
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_ip, *c = simsimd_cap_serial_k;
|
|
321
|
-
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_cos, *c = simsimd_cap_serial_k;
|
|
322
|
-
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_l2sq, *c = simsimd_cap_serial_k;
|
|
342
|
+
case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_ip, *c = simsimd_cap_serial_k; return;
|
|
343
|
+
case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_cos, *c = simsimd_cap_serial_k; return;
|
|
344
|
+
case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_l2sq, *c = simsimd_cap_serial_k; return;
|
|
345
|
+
default: break;
|
|
323
346
|
}
|
|
324
347
|
|
|
325
348
|
break;
|
|
@@ -330,29 +353,33 @@ inline static void simsimd_find_metric_punned( //
|
|
|
330
353
|
#if SIMSIMD_TARGET_ARM_NEON
|
|
331
354
|
if (viable & simsimd_cap_arm_neon_k)
|
|
332
355
|
switch (kind) {
|
|
333
|
-
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_neon_b8_hamming, *c = simsimd_cap_arm_neon_k;
|
|
334
|
-
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_neon_b8_jaccard, *c = simsimd_cap_arm_neon_k;
|
|
356
|
+
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_neon_b8_hamming, *c = simsimd_cap_arm_neon_k; return;
|
|
357
|
+
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_neon_b8_jaccard, *c = simsimd_cap_arm_neon_k; return;
|
|
358
|
+
default: break;
|
|
335
359
|
}
|
|
336
360
|
#endif
|
|
337
361
|
#if SIMSIMD_TARGET_ARM_SVE
|
|
338
362
|
if (viable & simsimd_cap_arm_sve_k)
|
|
339
363
|
switch (kind) {
|
|
340
|
-
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_sve_b8_hamming, *c = simsimd_cap_arm_sve_k;
|
|
341
|
-
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_sve_b8_jaccard, *c = simsimd_cap_arm_sve_k;
|
|
364
|
+
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_sve_b8_hamming, *c = simsimd_cap_arm_sve_k; return;
|
|
365
|
+
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_sve_b8_jaccard, *c = simsimd_cap_arm_sve_k; return;
|
|
366
|
+
default: break;
|
|
342
367
|
}
|
|
343
368
|
#endif
|
|
344
369
|
#if SIMSIMD_TARGET_X86_AVX512
|
|
345
370
|
if (viable & simsimd_cap_x86_avx512vpopcntdq_k)
|
|
346
371
|
switch (kind) {
|
|
347
|
-
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_b8_hamming, *c = simsimd_cap_x86_avx512vpopcntdq_k;
|
|
348
|
-
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_b8_jaccard, *c = simsimd_cap_x86_avx512vpopcntdq_k;
|
|
372
|
+
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_b8_hamming, *c = simsimd_cap_x86_avx512vpopcntdq_k; return;
|
|
373
|
+
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_b8_jaccard, *c = simsimd_cap_x86_avx512vpopcntdq_k; return;
|
|
374
|
+
default: break;
|
|
349
375
|
}
|
|
350
376
|
#endif
|
|
351
377
|
|
|
352
378
|
if (viable & simsimd_cap_serial_k)
|
|
353
379
|
switch (kind) {
|
|
354
|
-
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_serial_b8_hamming, *c = simsimd_cap_serial_k;
|
|
355
|
-
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_serial_b8_jaccard, *c = simsimd_cap_serial_k;
|
|
380
|
+
case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_serial_b8_hamming, *c = simsimd_cap_serial_k; return;
|
|
381
|
+
case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_serial_b8_jaccard, *c = simsimd_cap_serial_k; return;
|
|
382
|
+
default: break;
|
|
356
383
|
}
|
|
357
384
|
|
|
358
385
|
break;
|
|
@@ -360,6 +387,9 @@ inline static void simsimd_find_metric_punned( //
|
|
|
360
387
|
// clang-format on
|
|
361
388
|
}
|
|
362
389
|
|
|
390
|
+
#pragma clang diagnostic pop
|
|
391
|
+
#pragma GCC diagnostic pop
|
|
392
|
+
|
|
363
393
|
/**
|
|
364
394
|
* @brief Selects the most suitable metric implementation based on the given metric kind, datatype,
|
|
365
395
|
* and allowed capabilities. @b Don't call too often and prefer caching the `simsimd_capabilities()`.
|
|
@@ -816,8 +816,6 @@ __attribute__((target("avx512fp16,avx512vl,avx512f"))) //
|
|
|
816
816
|
inline static simsimd_f32_t
|
|
817
817
|
simsimd_avx512_f16_ip(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
818
818
|
__m512h ab_vec = _mm512_set1_ph(0);
|
|
819
|
-
simsimd_size_t i = 0;
|
|
820
|
-
|
|
821
819
|
for (simsimd_size_t i = 0; i < n; i += 32) {
|
|
822
820
|
__mmask32 mask = n - i >= 32 ? 0xFFFFFFFF : ((1u << (n - i)) - 1u);
|
|
823
821
|
__m512i a_vec = _mm512_maskz_loadu_epi16(mask, a + i);
|
|
@@ -887,7 +885,6 @@ simsimd_avx512_i8_cos(simsimd_i8_t const* a, simsimd_i8_t const* b, simsimd_size
|
|
|
887
885
|
__m512i ab_i32s_vec = _mm512_setzero_si512();
|
|
888
886
|
__m512i a2_i32s_vec = _mm512_setzero_si512();
|
|
889
887
|
__m512i b2_i32s_vec = _mm512_setzero_si512();
|
|
890
|
-
simsimd_size_t i = 0;
|
|
891
888
|
|
|
892
889
|
for (simsimd_size_t i = 0; i < n; i += 32) {
|
|
893
890
|
__mmask32 mask = n - i >= 32 ? 0xFFFFFFFF : ((1u << (n - i)) - 1u);
|
|
@@ -161,7 +161,7 @@ inline static simsimd_f32_t simsimd_approximate_inverse_square_root(simsimd_f32_
|
|
|
161
161
|
/**
|
|
162
162
|
* @brief Computes `log(x)` using the Mercator series.
|
|
163
163
|
* The series converges to the natural logarithm for args between -1 and 1.
|
|
164
|
-
* Published in 1668 in Logarithmotechnia.
|
|
164
|
+
* Published in 1668 in "Logarithmotechnia".
|
|
165
165
|
*/
|
|
166
166
|
inline static simsimd_f32_t simsimd_approximate_log(simsimd_f32_t number) {
|
|
167
167
|
simsimd_f32_t x = number - 1;
|
|
@@ -181,14 +181,19 @@ inline static simsimd_f32_t simsimd_approximate_log(simsimd_f32_t number) {
|
|
|
181
181
|
* https://github.com/OpenCyphal/libcanard/blob/636795f4bc395f56af8d2c61d3757b5e762bb9e5/canard.c#L811-L834
|
|
182
182
|
*/
|
|
183
183
|
inline static float simsimd_uncompress_f16(unsigned short x) {
|
|
184
|
+
union float_or_unsigned_int_t {
|
|
185
|
+
float f;
|
|
186
|
+
unsigned int i;
|
|
187
|
+
};
|
|
184
188
|
unsigned int exponent = (x & 0x7C00) >> 10;
|
|
185
189
|
unsigned int mantissa = (x & 0x03FF) << 13;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
unsigned int
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
union float_or_unsigned_int_t mantissa_union;
|
|
191
|
+
mantissa_union.f = (float)mantissa;
|
|
192
|
+
unsigned int v = (mantissa_union.i) >> 23;
|
|
193
|
+
union float_or_unsigned_int_t result_union;
|
|
194
|
+
result_union.i = (x & 0x8000) << 16 | (exponent != 0) * ((exponent + 112) << 23 | mantissa) |
|
|
195
|
+
((exponent == 0) & (mantissa != 0)) * ((v - 37) << 23 | ((mantissa << (150 - v)) & 0x007FE000));
|
|
196
|
+
return result_union.f;
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
#ifdef __cplusplus
|
|
@@ -4,8 +4,11 @@ import assert from 'node:assert';
|
|
|
4
4
|
|
|
5
5
|
const simsimd = bindings('simsimd');
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const f32Array1 = new Float32Array([1.0, 2.0, 3.0]);
|
|
8
|
+
const f32Array2 = new Float32Array([4.0, 5.0, 6.0]);
|
|
9
|
+
|
|
10
|
+
const u8Array1 = new Uint8Array([1, 2, 3]);
|
|
11
|
+
const u8Array2 = new Uint8Array([4, 5, 6]);
|
|
9
12
|
|
|
10
13
|
function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
11
14
|
const lowerBound = expected - tolerance;
|
|
@@ -13,17 +16,32 @@ function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
|
13
16
|
assert(actual >= lowerBound && actual <= upperBound, `Expected ${actual} to be almost equal to ${expected}`);
|
|
14
17
|
}
|
|
15
18
|
|
|
19
|
+
test('Distance from itself', () => {
|
|
20
|
+
assertAlmostEqual(simsimd.sqeuclidean(f32Array1, f32Array1), 0.0, 0.01);
|
|
21
|
+
assertAlmostEqual(simsimd.cosine(f32Array1, f32Array1), 0.0, 0.01);
|
|
22
|
+
|
|
23
|
+
// Inner-product distance on non-nroamalized vectors would yield:
|
|
24
|
+
// 1 - 1 - 4 - 9 = -13
|
|
25
|
+
assertAlmostEqual(simsimd.inner(f32Array1, f32Array1), -13.0, 0.01);
|
|
26
|
+
|
|
27
|
+
assertAlmostEqual(simsimd.kullbackleibler(f32Array1, f32Array1), 0.0, 0.01);
|
|
28
|
+
assertAlmostEqual(simsimd.jensenshannon(f32Array1, f32Array1), 0.0, 0.01);
|
|
29
|
+
|
|
30
|
+
assertAlmostEqual(simsimd.hamming(u8Array1, u8Array1), 0.0, 0.01);
|
|
31
|
+
assertAlmostEqual(simsimd.jaccard(u8Array1, u8Array1), 0.0, 0.01);
|
|
32
|
+
});
|
|
33
|
+
|
|
16
34
|
test('Squared Euclidean Distance', () => {
|
|
17
|
-
const result = simsimd.sqeuclidean(
|
|
35
|
+
const result = simsimd.sqeuclidean(f32Array1, f32Array2);
|
|
18
36
|
assertAlmostEqual(result, 27.0, 0.01);
|
|
19
37
|
});
|
|
20
38
|
|
|
21
39
|
test('Inner Product', () => {
|
|
22
|
-
const result = simsimd.inner(
|
|
40
|
+
const result = simsimd.inner(f32Array1, f32Array2);
|
|
23
41
|
assertAlmostEqual(result, -31.0, 0.01);
|
|
24
42
|
});
|
|
25
43
|
|
|
26
44
|
test('Cosine Similarity', () => {
|
|
27
|
-
const result = simsimd.cosine(
|
|
45
|
+
const result = simsimd.cosine(f32Array1, f32Array2);
|
|
28
46
|
assertAlmostEqual(result, 0.029, 0.01);
|
|
29
47
|
});
|
package/simsimd/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simsimd",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Vector Similarity Functions 3x-200x Faster than SciPy and NumPy",
|
|
5
5
|
"author": "Ash Vardanian",
|
|
6
6
|
"license": "Apache 2.0",
|
|
@@ -34,4 +34,4 @@
|
|
|
34
34
|
"typescript": "^5.1.6",
|
|
35
35
|
"usearch": "^2.7.2"
|
|
36
36
|
}
|
|
37
|
-
}
|
|
37
|
+
}
|
package/wasmer.toml
CHANGED
package/wolfram/lib.cpp
CHANGED
|
@@ -9,7 +9,7 @@ using vector_view_t = span_gt<float>;
|
|
|
9
9
|
|
|
10
10
|
using add_result_t = typename index_t::add_result_t;
|
|
11
11
|
using search_result_t = typename index_t::search_result_t;
|
|
12
|
-
using
|
|
12
|
+
using vector_key_t = typename index_t::vector_key_t;
|
|
13
13
|
|
|
14
14
|
EXTERN_C DLLEXPORT int WolframLibrary_initialize(WolframLibraryData libData) { return LIBRARY_NO_ERROR; }
|
|
15
15
|
EXTERN_C DLLEXPORT void WolframLibrary_uninitialize(WolframLibraryData libData) { return; }
|
package/csharp/eng/build_lib.sh
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Get absolute path to the usearch dir
|
|
4
|
-
# FIX: realpath is not available on OSX, so use pwd
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
-
SCRIPT_DIR="${SCRIPT_DIR}/"
|
|
7
|
-
|
|
8
|
-
# Define project paths
|
|
9
|
-
REPO_ROOT=`cd -P "${SCRIPT_DIR}../.." && pwd`
|
|
10
|
-
REPO_ROOT="${REPO_ROOT}/"
|
|
11
|
-
C_DIR="${REPO_ROOT}c/"
|
|
12
|
-
CSHARP_DIR="${REPO_ROOT}csharp/"
|
|
13
|
-
BUILD_ARTIFACTS_DIR="${CSHARP_DIR}lib/"
|
|
14
|
-
|
|
15
|
-
LIB_FILE="libusearch_c"
|
|
16
|
-
|
|
17
|
-
# Determine the architecture type (only x64 is supported)
|
|
18
|
-
ARCH_TYPE="$(uname -m)"
|
|
19
|
-
case "$ARCH_TYPE" in
|
|
20
|
-
x86_64)
|
|
21
|
-
ARCH="x64"
|
|
22
|
-
;;
|
|
23
|
-
# i386|i486|i586|i686)
|
|
24
|
-
# ARCH="x86"
|
|
25
|
-
# ;;
|
|
26
|
-
*)
|
|
27
|
-
echo "Unsupported architecture"
|
|
28
|
-
exit 1
|
|
29
|
-
;;
|
|
30
|
-
esac
|
|
31
|
-
echo "Detected architecture: $ARCH"
|
|
32
|
-
|
|
33
|
-
# Determine the OS type (linux or macos) and set the shared library extension accordingly
|
|
34
|
-
case "$(uname -s)" in
|
|
35
|
-
Darwin)
|
|
36
|
-
BUILD_ARTIFACTS_DIR+="runtimes/osx-${ARCH}/native/"
|
|
37
|
-
LIB_FILE+=".dylib"
|
|
38
|
-
;;
|
|
39
|
-
Linux)
|
|
40
|
-
BUILD_ARTIFACTS_DIR+="runtimes/linux-${ARCH}/native/"
|
|
41
|
-
LIB_FILE+=".so"
|
|
42
|
-
;;
|
|
43
|
-
*)
|
|
44
|
-
echo "Unsupported operating system"
|
|
45
|
-
exit 1
|
|
46
|
-
;;
|
|
47
|
-
esac
|
|
48
|
-
|
|
49
|
-
MAKE_TARGET="${LIB_FILE}"
|
|
50
|
-
|
|
51
|
-
# Build the native dynamic lib
|
|
52
|
-
cd "$C_DIR" || { echo "C directory not found in $C_DIR"; exit 1; }
|
|
53
|
-
if [ ! -f Makefile ]; then
|
|
54
|
-
echo "Makefile not found in $C_DIR"
|
|
55
|
-
exit 1
|
|
56
|
-
fi
|
|
57
|
-
make "${MAKE_TARGET}"
|
|
58
|
-
if [ $? -ne 0 ]; then
|
|
59
|
-
echo "Build failed!"
|
|
60
|
-
exit 1
|
|
61
|
-
fi
|
|
62
|
-
|
|
63
|
-
# Create output dir for shared lib and copy it there
|
|
64
|
-
mkdir -p "$BUILD_ARTIFACTS_DIR"
|
|
65
|
-
cp "${C_DIR}/${LIB_FILE}" "$BUILD_ARTIFACTS_DIR"
|
package/csharp/eng/clean.sh
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Get absolute path to the usearch csharp dir
|
|
4
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
-
SCRIPT_DIR="${SCRIPT_DIR}/"
|
|
6
|
-
CSHARP_DIR=`cd -P "${SCRIPT_DIR}.." && pwd`
|
|
7
|
-
CSHARP_DIR="${CSHARP_DIR}/"
|
|
8
|
-
|
|
9
|
-
rm -rf ${CSHARP_DIR}lib # Local temp path for native libs
|
|
10
|
-
rm -rf ${CSHARP_DIR}packages # Local temp path for nuget packages
|
|
11
|
-
find ${CSHARP_DIR} -type d -name 'bin' -exec rm -rf {} +
|
|
12
|
-
find ${CSHARP_DIR} -type d -name 'obj' -exec rm -rf {} +
|