usearch 2.9.1 → 2.10.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.
Files changed (169) hide show
  1. package/README.md +50 -52
  2. package/javascript/{types → dist/cjs}/usearch.d.ts +90 -115
  3. package/javascript/dist/cjs/usearch.js +531 -0
  4. package/javascript/dist/esm/usearch.d.ts +212 -0
  5. package/javascript/{usearch.js → dist/esm/usearch.js} +202 -153
  6. package/package.json +25 -23
  7. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  8. package/prebuilds/linux-arm64/usearch.node +0 -0
  9. package/prebuilds/linux-x64/usearch.node +0 -0
  10. package/prebuilds/win32-ia32/usearch.node +0 -0
  11. package/prebuilds/win32-x64/usearch.node +0 -0
  12. package/.clang-format +0 -10
  13. package/.clang-tidy +0 -60
  14. package/.cmake-format.py +0 -19
  15. package/.dockerignore +0 -93
  16. package/.gitattributes +0 -9
  17. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
  18. package/.github/ISSUE_TEMPLATE/config.yml +0 -5
  19. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -64
  20. package/.github/workflows/Dockerfile.libs +0 -36
  21. package/.github/workflows/prerelease.yml +0 -331
  22. package/.github/workflows/release.yml +0 -722
  23. package/.github/workflows/update_version.sh +0 -15
  24. package/.gitmodules +0 -9
  25. package/.releaserc +0 -90
  26. package/CITATION.cff +0 -11
  27. package/CMakeLists.txt +0 -324
  28. package/CODE_OF_CONDUCT.md +0 -128
  29. package/CONTRIBUTING.md +0 -353
  30. package/Cargo.toml +0 -19
  31. package/Dockerfile +0 -16
  32. package/VERSION +0 -1
  33. package/assets/unum.png +0 -0
  34. package/assets/usearch-approaches-transparent.png +0 -0
  35. package/assets/usearch-approaches-white.png +0 -0
  36. package/assets/usearch-neighbor-types.png +0 -0
  37. package/binding.gyp +0 -87
  38. package/build.gradle +0 -204
  39. package/build.rs +0 -18
  40. package/c/CMakeLists.txt +0 -25
  41. package/c/README.md +0 -34
  42. package/c/lib.cpp +0 -358
  43. package/c/test.c +0 -374
  44. package/c/usearch.h +0 -311
  45. package/cmake/clipp.cmake +0 -7
  46. package/cmake/config.cmake.in +0 -15
  47. package/cmake/emscripten.cmake +0 -8
  48. package/cmake/jemalloc.cmake +0 -62
  49. package/cmake/pkg-config.pc.in +0 -4
  50. package/cmake/usearchConfigVersion.cmake.in +0 -20
  51. package/conanfile.py +0 -26
  52. package/cpp/CMakeLists.txt +0 -14
  53. package/cpp/README.md +0 -161
  54. package/cpp/bench.cpp +0 -618
  55. package/cpp/test.cpp +0 -323
  56. package/fp16/CMakeLists.txt +0 -176
  57. package/fp16/LICENSE +0 -11
  58. package/fp16/README.md +0 -20
  59. package/fp16/bench/alt-element.cc +0 -89
  60. package/fp16/bench/from-alt-array.cc +0 -175
  61. package/fp16/bench/from-ieee-array.cc +0 -399
  62. package/fp16/bench/ieee-element.cc +0 -272
  63. package/fp16/bench/to-alt-array.cc +0 -91
  64. package/fp16/bench/to-ieee-array.cc +0 -303
  65. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  66. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  67. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  68. package/fp16/configure.py +0 -65
  69. package/fp16/confu.yaml +0 -8
  70. package/fp16/include/fp16/__init__.py +0 -0
  71. package/fp16/include/fp16/avx.py +0 -50
  72. package/fp16/include/fp16/avx2.py +0 -53
  73. package/fp16/include/fp16/bitcasts.h +0 -92
  74. package/fp16/include/fp16/fp16.h +0 -451
  75. package/fp16/include/fp16/psimd.h +0 -131
  76. package/fp16/include/fp16.h +0 -11
  77. package/fp16/jni/Android.mk +0 -6
  78. package/fp16/jni/Application.mk +0 -4
  79. package/fp16/test/alt-from-fp32-value.cc +0 -498
  80. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  81. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  82. package/fp16/test/alt-to-fp32-value.cc +0 -348
  83. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  84. package/fp16/test/bitcasts.cc +0 -56
  85. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  86. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  87. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  88. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  89. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  90. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  91. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  92. package/fp16/test/peachpy/stubs.py +0 -38
  93. package/fp16/test/tables.cc +0 -530
  94. package/fp16/test/tables.h +0 -13
  95. package/fp16/third-party/THHalf.h +0 -92
  96. package/fp16/third-party/eigen-half.h +0 -170
  97. package/fp16/third-party/float16-compressor.h +0 -80
  98. package/fp16/third-party/half.hpp +0 -2916
  99. package/fp16/third-party/npy-halffloat.h +0 -328
  100. package/include/usearch/index.hpp +0 -3836
  101. package/include/usearch/index_dense.hpp +0 -2004
  102. package/include/usearch/index_plugins.hpp +0 -2203
  103. package/javascript/lib.cpp +0 -341
  104. package/javascript/types/usearch.d.ts.map +0 -1
  105. package/javascript/usearch.test.js +0 -74
  106. package/package-ci.json +0 -10
  107. package/pyproject.toml +0 -51
  108. package/setup.py +0 -201
  109. package/simsimd/.releaserc +0 -86
  110. package/simsimd/Cargo.lock +0 -708
  111. package/simsimd/Cargo.toml +0 -36
  112. package/simsimd/LICENSE +0 -201
  113. package/simsimd/README.md +0 -275
  114. package/simsimd/binding.gyp +0 -36
  115. package/simsimd/build.rs +0 -20
  116. package/simsimd/include/simsimd/binary.h +0 -201
  117. package/simsimd/include/simsimd/probability.h +0 -548
  118. package/simsimd/include/simsimd/simsimd.h +0 -456
  119. package/simsimd/include/simsimd/spatial.h +0 -1175
  120. package/simsimd/include/simsimd/types.h +0 -207
  121. package/simsimd/javascript/bench.js +0 -127
  122. package/simsimd/javascript/fallback.ts +0 -193
  123. package/simsimd/javascript/lib.c +0 -102
  124. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  125. package/simsimd/javascript/simsimd.ts +0 -124
  126. package/simsimd/javascript/test.mjs +0 -153
  127. package/simsimd/javascript/tsconfig-base.json +0 -25
  128. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  129. package/simsimd/javascript/tsconfig-esm.json +0 -8
  130. package/simsimd/package-lock.json +0 -1688
  131. package/simsimd/package.json +0 -61
  132. package/simsimd/rust/benches/cosine.rs +0 -27
  133. package/simsimd/rust/benches/native.rs +0 -27
  134. package/simsimd/rust/benches/sqeuclidean.rs +0 -27
  135. package/simsimd/rust/lib.c +0 -68
  136. package/simsimd/rust/lib.rs +0 -232
  137. package/sqlite/README.md +0 -178
  138. package/sqlite/lib.cpp +0 -325
  139. package/stringzilla/CONTRIBUTING.md +0 -429
  140. package/stringzilla/Cargo.lock +0 -25
  141. package/stringzilla/Cargo.toml +0 -26
  142. package/stringzilla/LICENSE +0 -201
  143. package/stringzilla/README.md +0 -1281
  144. package/stringzilla/VERSION +0 -1
  145. package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
  146. package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
  147. package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
  148. package/stringzilla/binding.gyp +0 -16
  149. package/stringzilla/build.rs +0 -14
  150. package/stringzilla/c/lib.c +0 -304
  151. package/stringzilla/cli/README.md +0 -48
  152. package/stringzilla/cli/split.py +0 -72
  153. package/stringzilla/cli/wc.py +0 -37
  154. package/stringzilla/include/stringzilla/experimental.h +0 -724
  155. package/stringzilla/include/stringzilla/module.modulemap +0 -9
  156. package/stringzilla/include/stringzilla/stringzilla.h +0 -5240
  157. package/stringzilla/include/stringzilla/stringzilla.hpp +0 -3830
  158. package/stringzilla/javascript/lib.c +0 -125
  159. package/stringzilla/javascript/stringzilla.js +0 -22
  160. package/stringzilla/package-ci.json +0 -10
  161. package/stringzilla/package.json +0 -32
  162. package/stringzilla/rust/lib.rs +0 -362
  163. package/stringzilla/swift/StringProtocol+StringZilla.swift +0 -280
  164. package/stringzilla/swift/Test.swift +0 -60
  165. package/tsconfig.json +0 -21
  166. package/wasmer.toml +0 -12
  167. package/winlibinstaller.bat +0 -42
  168. /package/{simsimd/javascript/dist-package-cjs.json → javascript/dist/cjs/package.json} +0 -0
  169. /package/{simsimd/javascript/dist-package-esm.json → javascript/dist/esm/package.json} +0 -0
@@ -1,456 +0,0 @@
1
- /**
2
- * @brief SIMD-accelerated Similarity Measures and Distance Functions.
3
- * @file simsimd.h
4
- * @author Ash Vardanian
5
- * @date March 14, 2023
6
- * @copyright Copyright (c) 2023
7
- *
8
- * References:
9
- * x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/
10
- * Arm intrinsics: https://developer.arm.com/architectures/instruction-sets/intrinsics/
11
- * Detecting target CPU features at compile time: https://stackoverflow.com/a/28939692/2766161
12
- */
13
-
14
- #ifndef SIMSIMD_H
15
- #define SIMSIMD_H
16
-
17
- #define SIMSIMD_VERSION_MAJOR 3
18
- #define SIMSIMD_VERSION_MINOR 8
19
- #define SIMSIMD_VERSION_PATCH 0
20
-
21
- #include "binary.h" // Hamming, Jaccard
22
- #include "probability.h" // Kullback-Leibler, Jensen–Shannon
23
- #include "spatial.h" // L2, Inner Product, Cosine
24
-
25
- #if SIMSIMD_TARGET_ARM
26
- #ifdef __linux__
27
- #include <asm/hwcap.h>
28
- #include <sys/auxv.h>
29
- #endif
30
- #endif
31
-
32
- #ifdef __cplusplus
33
- extern "C" {
34
- #endif
35
-
36
- /**
37
- * @brief Enumeration of supported metric kinds.
38
- */
39
- typedef enum {
40
- simsimd_metric_unknown_k = 0, ///< Unknown metric kind
41
-
42
- // Classics:
43
- simsimd_metric_ip_k = 'i', ///< Inner product
44
- simsimd_metric_dot_k = 'i', ///< Inner product alias
45
- simsimd_metric_inner_k = 'i', ///< Inner product alias
46
-
47
- simsimd_metric_cos_k = 'c', ///< Cosine similarity
48
- simsimd_metric_cosine_k = 'c', ///< Cosine similarity alias
49
- simsimd_metric_angular_k = 'c', ///< Cosine similarity alias
50
-
51
- simsimd_metric_l2sq_k = 'e', ///< Squared Euclidean distance
52
- simsimd_metric_sqeuclidean_k = 'e', ///< Squared Euclidean distance alias
53
-
54
- // Binary:
55
- simsimd_metric_hamming_k = 'b', ///< Hamming distance
56
- simsimd_metric_jaccard_k = 'j', ///< Jaccard coefficient
57
-
58
- // Probability:
59
- simsimd_metric_kl_k = 'k', ///< Kullback-Leibler divergence
60
- simsimd_metric_kullback_leibler_k = 'k', ///< Kullback-Leibler divergence alias
61
-
62
- simsimd_metric_js_k = 's', ///< Jensen-Shannon divergence
63
- simsimd_metric_jensen_shannon_k = 's', ///< Jensen-Shannon divergence alias
64
-
65
- } simsimd_metric_kind_t;
66
-
67
- /**
68
- * @brief Enumeration of SIMD capabilities of the target architecture.
69
- */
70
- typedef enum {
71
- simsimd_cap_serial_k = 1, ///< Serial (non-SIMD) capability
72
- simsimd_cap_any_k = 0x7FFFFFFF, ///< Mask representing any capability with `INT_MAX`
73
-
74
- simsimd_cap_arm_neon_k = 1 << 10, ///< ARM NEON capability
75
- simsimd_cap_arm_sve_k = 1 << 11, ///< ARM SVE capability
76
- simsimd_cap_arm_sve2_k = 1 << 12, ///< ARM SVE2 capability
77
-
78
- simsimd_cap_x86_avx2_k = 1 << 20, ///< x86 AVX2 capability
79
- simsimd_cap_x86_avx512_k = 1 << 21, ///< x86 AVX512 capability
80
- simsimd_cap_x86_avx2fp16_k = 1 << 22, ///< x86 AVX2 with FP16 capability
81
- simsimd_cap_x86_avx512fp16_k = 1 << 23, ///< x86 AVX512 with FP16 capability
82
- simsimd_cap_x86_avx512vpopcntdq_k = 1 << 24, ///< x86 AVX512 VPOPCNTDQ instruction capability
83
- simsimd_cap_x86_avx512vnni_k = 1 << 25, ///< x86 AVX512 VNNI instruction capability
84
-
85
- } simsimd_capability_t;
86
-
87
- /**
88
- * @brief Enumeration of supported data types.
89
- */
90
- typedef enum {
91
- simsimd_datatype_unknown_k, ///< Unknown data type
92
- simsimd_datatype_f64_k, ///< Double precision floating point
93
- simsimd_datatype_f32_k, ///< Single precision floating point
94
- simsimd_datatype_f16_k, ///< Half precision floating point
95
- simsimd_datatype_i8_k, ///< 8-bit integer
96
- simsimd_datatype_b8_k, ///< Single-bit values packed into 8-bit words
97
- } simsimd_datatype_t;
98
-
99
- /**
100
- * @brief Type-punned function pointer accepting two vectors and outputting their similarity/distance.
101
- *
102
- * @param[in] a Pointer to the first data array.
103
- * @param[in] b Pointer to the second data array.
104
- * @param[in] size_a Size of the first data array.
105
- * @param[in] size_b Size of the second data array.
106
- * @return Computed metric as a single-precision floating-point value.
107
- */
108
- typedef simsimd_f32_t (*simsimd_metric_punned_t)(void const* a, void const* b, simsimd_size_t size_a,
109
- simsimd_size_t size_b);
110
-
111
- /**
112
- * @brief Function to determine the SIMD capabilities of the current machine at @b runtime.
113
- * @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
114
- */
115
- inline static simsimd_capability_t simsimd_capabilities(void) {
116
-
117
- #if SIMSIMD_TARGET_X86
118
-
119
- /// The states of 4 registers populated for a specific "cpuid" assembly call
120
- union four_registers_t {
121
- int array[4];
122
- struct separate_t {
123
- unsigned eax, ebx, ecx, edx;
124
- } named;
125
- } info1, info7;
126
-
127
- #ifdef _MSC_VER
128
- __cpuidex(info1.array, 1, 0);
129
- __cpuidex(info7.array, 7, 0);
130
- #else
131
- __asm__ __volatile__("cpuid"
132
- : "=a"(info1.named.eax), "=b"(info1.named.ebx), "=c"(info1.named.ecx), "=d"(info1.named.edx)
133
- : "a"(1), "c"(0));
134
- __asm__ __volatile__("cpuid"
135
- : "=a"(info7.named.eax), "=b"(info7.named.ebx), "=c"(info7.named.ecx), "=d"(info7.named.edx)
136
- : "a"(7), "c"(0));
137
- #endif
138
-
139
- // Check for AVX2 (Function ID 7, EBX register)
140
- // https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L148
141
- unsigned supports_avx2 = (info7.named.ebx & 0x00000020) != 0;
142
- // Check for F16C (Function ID 1, ECX register)
143
- // https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L107
144
- unsigned supports_f16c = (info1.named.ecx & 0x20000000) != 0;
145
- // Check for AVX512F (Function ID 7, EBX register)
146
- // https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L155
147
- unsigned supports_avx512f = (info7.named.ebx & 0x00010000) != 0;
148
- // Check for AVX512FP16 (Function ID 7, EDX register)
149
- // https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L198C9-L198C23
150
- unsigned supports_avx512fp16 = (info7.named.edx & 0x00800000) != 0;
151
- // Check for VPOPCNTDQ (Function ID 1, ECX register)
152
- // https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L182C30-L182C40
153
- unsigned supports_avx512vpopcntdq = (info1.named.ecx & 0x00004000) != 0;
154
- // Check for VNNI (Function ID 1, ECX register)
155
- // https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L180
156
- unsigned supports_avx512vnni = (info1.named.ecx & 0x00000800) != 0;
157
-
158
- return (simsimd_capability_t)( //
159
- (simsimd_cap_x86_avx2_k * supports_avx2) | //
160
- (simsimd_cap_x86_avx512_k * supports_avx512f) | //
161
- (simsimd_cap_x86_avx2fp16_k * (supports_avx2 && supports_f16c)) | //
162
- (simsimd_cap_x86_avx512fp16_k * (supports_avx512fp16 && supports_avx512f)) | //
163
- (simsimd_cap_x86_avx512vpopcntdq_k * (supports_avx512vpopcntdq)) | //
164
- (simsimd_cap_x86_avx512vnni_k * (supports_avx512vnni)) | //
165
- (simsimd_cap_serial_k));
166
-
167
- #endif // SIMSIMD_TARGET_X86
168
-
169
- #if SIMSIMD_TARGET_ARM
170
-
171
- // Every 64-bit Arm CPU supports NEON
172
- unsigned supports_neon = 1;
173
- unsigned supports_sve = 0;
174
- unsigned supports_sve2 = 0;
175
-
176
- #ifdef __linux__
177
- unsigned long hwcap = getauxval(AT_HWCAP);
178
- unsigned long hwcap2 = getauxval(AT_HWCAP2);
179
- supports_sve = (hwcap & HWCAP_SVE) != 0;
180
- supports_sve2 = (hwcap2 & HWCAP2_SVE2) != 0;
181
- #endif
182
-
183
- return (simsimd_capability_t)( //
184
- (simsimd_cap_arm_neon_k * supports_neon) | //
185
- (simsimd_cap_arm_sve_k * supports_sve) | //
186
- (simsimd_cap_arm_sve2_k * supports_sve2) | //
187
- (simsimd_cap_serial_k));
188
-
189
- #endif // SIMSIMD_TARGET_ARM
190
-
191
- return simsimd_cap_serial_k;
192
- }
193
-
194
- #pragma GCC diagnostic push
195
- #pragma GCC diagnostic ignored "-Wcast-function-type"
196
- #pragma clang diagnostic push
197
- #pragma clang diagnostic ignored "-Wcast-function-type"
198
-
199
- /**
200
- * @brief Determines the best suited metric implementation based on the given datatype,
201
- * supported and allowed by hardware capabilities.
202
- *
203
- * @param kind The kind of metric to be evaluated.
204
- * @param datatype The data type for which the metric needs to be evaluated.
205
- * @param supported The hardware capabilities supported by the CPU.
206
- * @param allowed The hardware capabilities allowed for use.
207
- * @param metric_output Output variable for the selected similarity function.
208
- * @param capability_output Output variable for the utilized hardware capabilities.
209
- */
210
- inline static void simsimd_find_metric_punned( //
211
- simsimd_metric_kind_t kind, //
212
- simsimd_datatype_t datatype, //
213
- simsimd_capability_t supported, //
214
- simsimd_capability_t allowed, //
215
- simsimd_metric_punned_t* metric_output, //
216
- simsimd_capability_t* capability_output) {
217
-
218
- simsimd_metric_punned_t* m = metric_output;
219
- simsimd_capability_t* c = capability_output;
220
- simsimd_capability_t viable = (simsimd_capability_t)(supported & allowed);
221
- *m = (simsimd_metric_punned_t)0;
222
- *c = (simsimd_capability_t)0;
223
-
224
- // clang-format off
225
- switch (datatype) {
226
-
227
- case simsimd_datatype_unknown_k: break;
228
-
229
- // Double-precision floating-point vectors
230
- case simsimd_datatype_f64_k:
231
-
232
- #if SIMSIMD_TARGET_X86_AVX512
233
- if (viable & simsimd_cap_x86_avx512_k)
234
- switch (kind) {
235
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f64_ip, *c = simsimd_cap_x86_avx512_k; return;
236
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f64_cos, *c = simsimd_cap_x86_avx512_k; return;
237
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f64_l2sq, *c = simsimd_cap_x86_avx512_k; return;
238
- default: break;
239
- }
240
- #endif
241
- if (viable & simsimd_cap_serial_k)
242
- switch (kind) {
243
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f64_ip, *c = simsimd_cap_serial_k; return;
244
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f64_cos, *c = simsimd_cap_serial_k; return;
245
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f64_l2sq, *c = simsimd_cap_serial_k; return;
246
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f64_js, *c = simsimd_cap_serial_k; return;
247
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f64_kl, *c = simsimd_cap_serial_k; return;
248
- default: break;
249
- }
250
-
251
- break;
252
-
253
- // Single-precision floating-point vectors
254
- case simsimd_datatype_f32_k:
255
-
256
- #if SIMSIMD_TARGET_ARM_NEON
257
- if (viable & simsimd_cap_arm_neon_k)
258
- switch (kind) {
259
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_ip, *c = simsimd_cap_arm_neon_k; return;
260
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_cos, *c = simsimd_cap_arm_neon_k; return;
261
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_l2sq, *c = simsimd_cap_arm_neon_k; return;
262
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_js, *c = simsimd_cap_arm_neon_k; return;
263
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f32_kl, *c = simsimd_cap_arm_neon_k; return;
264
- default: break;
265
- }
266
- #endif
267
- #if SIMSIMD_TARGET_X86_AVX512
268
- if (viable & simsimd_cap_x86_avx512_k)
269
- switch (kind) {
270
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_ip, *c = simsimd_cap_x86_avx512_k; return;
271
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_cos, *c = simsimd_cap_x86_avx512_k; return;
272
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_l2sq, *c = simsimd_cap_x86_avx512_k; return;
273
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_js, *c = simsimd_cap_x86_avx512_k; return;
274
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f32_kl, *c = simsimd_cap_x86_avx512_k; return;
275
- default: break;
276
- }
277
- #endif
278
- if (viable & simsimd_cap_serial_k)
279
- switch (kind) {
280
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_ip, *c = simsimd_cap_serial_k; return;
281
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_cos, *c = simsimd_cap_serial_k; return;
282
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_l2sq, *c = simsimd_cap_serial_k; return;
283
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_js, *c = simsimd_cap_serial_k; return;
284
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f32_kl, *c = simsimd_cap_serial_k; return;
285
- default: break;
286
- }
287
-
288
- break;
289
-
290
- // Half-precision floating-point vectors
291
- case simsimd_datatype_f16_k:
292
-
293
- #if SIMSIMD_TARGET_ARM_SVE
294
- if (viable & simsimd_cap_arm_sve_k)
295
- switch (kind) {
296
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_ip, *c = simsimd_cap_arm_sve_k; return;
297
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_cos, *c = simsimd_cap_arm_sve_k; return;
298
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_sve_f16_l2sq, *c = simsimd_cap_arm_sve_k; return;
299
- default: break;
300
- }
301
- #endif
302
- #if SIMSIMD_TARGET_ARM_NEON
303
- if (viable & simsimd_cap_arm_neon_k)
304
- switch (kind) {
305
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_ip, *c = simsimd_cap_arm_neon_k; return;
306
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_cos, *c = simsimd_cap_arm_neon_k; return;
307
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_l2sq, *c = simsimd_cap_arm_neon_k; return;
308
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_js, *c = simsimd_cap_arm_neon_k; return;
309
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_neon_f16_kl, *c = simsimd_cap_arm_neon_k; return;
310
- default: break;
311
- }
312
- #endif
313
- #if SIMSIMD_TARGET_X86_AVX512
314
- if (viable & simsimd_cap_x86_avx512fp16_k)
315
- switch (kind) {
316
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_ip, *c = simsimd_cap_x86_avx512fp16_k; return;
317
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_cos, *c = simsimd_cap_x86_avx512fp16_k; return;
318
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_l2sq, *c = simsimd_cap_x86_avx512fp16_k; return;
319
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_js, *c = simsimd_cap_x86_avx512fp16_k; return;
320
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_f16_kl, *c = simsimd_cap_x86_avx512fp16_k; return;
321
- default: break;
322
- }
323
- #endif
324
- #if SIMSIMD_TARGET_X86_AVX2
325
- if (viable & simsimd_cap_x86_avx2fp16_k)
326
- switch (kind) {
327
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_ip, *c = simsimd_cap_x86_avx2fp16_k; return;
328
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_cos, *c = simsimd_cap_x86_avx2fp16_k; return;
329
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_l2sq, *c = simsimd_cap_x86_avx2fp16_k; return;
330
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_js, *c = simsimd_cap_x86_avx2fp16_k; return;
331
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_f16_kl, *c = simsimd_cap_x86_avx2fp16_k; return;
332
- default: break;
333
- }
334
- #endif
335
-
336
- if (viable & simsimd_cap_serial_k)
337
- switch (kind) {
338
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_ip, *c = simsimd_cap_serial_k; return;
339
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_cos, *c = simsimd_cap_serial_k; return;
340
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_l2sq, *c = simsimd_cap_serial_k; return;
341
- case simsimd_metric_js_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_js, *c = simsimd_cap_serial_k; return;
342
- case simsimd_metric_kl_k: *m = (simsimd_metric_punned_t)&simsimd_serial_f16_kl, *c = simsimd_cap_serial_k; return;
343
- default: break;
344
- }
345
-
346
- break;
347
-
348
- // Single-byte integer vectors
349
- case simsimd_datatype_i8_k:
350
- #if SIMSIMD_TARGET_ARM_NEON
351
- if (viable & simsimd_cap_arm_neon_k)
352
- switch (kind) {
353
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_ip, *c = simsimd_cap_arm_neon_k; return;
354
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_cos, *c = simsimd_cap_arm_neon_k; return;
355
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_neon_i8_l2sq, *c = simsimd_cap_arm_neon_k; return;
356
- default: break;
357
- }
358
- #endif
359
- #if SIMSIMD_TARGET_X86_AVX512
360
- if (viable & simsimd_cap_x86_avx512vnni_k)
361
- switch (kind) {
362
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_ip, *c = simsimd_cap_x86_avx512vnni_k; return;
363
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_cos, *c = simsimd_cap_x86_avx512vnni_k; return;
364
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_i8_l2sq, *c = simsimd_cap_x86_avx512vnni_k; return;
365
- default: break;
366
- }
367
- #endif
368
- #if SIMSIMD_TARGET_X86_AVX2
369
- if (viable & simsimd_cap_x86_avx2_k)
370
- switch (kind) {
371
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_i8_ip, *c = simsimd_cap_x86_avx2_k; return;
372
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_i8_cos, *c = simsimd_cap_x86_avx2_k; return;
373
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_avx2_i8_l2sq, *c = simsimd_cap_x86_avx2_k; return;
374
- default: break;
375
- }
376
- #endif
377
-
378
- if (viable & simsimd_cap_serial_k)
379
- switch (kind) {
380
- case simsimd_metric_ip_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_ip, *c = simsimd_cap_serial_k; return;
381
- case simsimd_metric_cos_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_cos, *c = simsimd_cap_serial_k; return;
382
- case simsimd_metric_l2sq_k: *m = (simsimd_metric_punned_t)&simsimd_serial_i8_l2sq, *c = simsimd_cap_serial_k; return;
383
- default: break;
384
- }
385
-
386
- break;
387
-
388
- // Binary vectors
389
- case simsimd_datatype_b8_k:
390
-
391
- #if SIMSIMD_TARGET_ARM_NEON
392
- if (viable & simsimd_cap_arm_neon_k)
393
- switch (kind) {
394
- case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_neon_b8_hamming, *c = simsimd_cap_arm_neon_k; return;
395
- case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_neon_b8_jaccard, *c = simsimd_cap_arm_neon_k; return;
396
- default: break;
397
- }
398
- #endif
399
- #if SIMSIMD_TARGET_ARM_SVE
400
- if (viable & simsimd_cap_arm_sve_k)
401
- switch (kind) {
402
- case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_sve_b8_hamming, *c = simsimd_cap_arm_sve_k; return;
403
- case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_sve_b8_jaccard, *c = simsimd_cap_arm_sve_k; return;
404
- default: break;
405
- }
406
- #endif
407
- #if SIMSIMD_TARGET_X86_AVX512
408
- if (viable & simsimd_cap_x86_avx512vpopcntdq_k)
409
- switch (kind) {
410
- case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_b8_hamming, *c = simsimd_cap_x86_avx512vpopcntdq_k; return;
411
- case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_avx512_b8_jaccard, *c = simsimd_cap_x86_avx512vpopcntdq_k; return;
412
- default: break;
413
- }
414
- #endif
415
-
416
- if (viable & simsimd_cap_serial_k)
417
- switch (kind) {
418
- case simsimd_metric_hamming_k: *m = (simsimd_metric_punned_t)&simsimd_serial_b8_hamming, *c = simsimd_cap_serial_k; return;
419
- case simsimd_metric_jaccard_k: *m = (simsimd_metric_punned_t)&simsimd_serial_b8_jaccard, *c = simsimd_cap_serial_k; return;
420
- default: break;
421
- }
422
-
423
- break;
424
- }
425
- // clang-format on
426
- }
427
-
428
- #pragma clang diagnostic pop
429
- #pragma GCC diagnostic pop
430
-
431
- /**
432
- * @brief Selects the most suitable metric implementation based on the given metric kind, datatype,
433
- * and allowed capabilities. @b Don't call too often and prefer caching the `simsimd_capabilities()`.
434
- *
435
- * @param kind The kind of metric to be evaluated.
436
- * @param datatype The data type for which the metric needs to be evaluated.
437
- * @param allowed The hardware capabilities allowed for use.
438
- * @return A function pointer to the selected metric implementation.
439
- */
440
- inline static simsimd_metric_punned_t simsimd_metric_punned( //
441
- simsimd_metric_kind_t kind, //
442
- simsimd_datatype_t datatype, //
443
- simsimd_capability_t allowed) {
444
-
445
- simsimd_metric_punned_t result = 0;
446
- simsimd_capability_t c = simsimd_cap_serial_k;
447
- simsimd_capability_t supported = simsimd_capabilities();
448
- simsimd_find_metric_punned(kind, datatype, supported, allowed, &result, &c);
449
- return result;
450
- }
451
-
452
- #ifdef __cplusplus
453
- }
454
- #endif
455
-
456
- #endif