usearch 2.15.1 → 2.15.3

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/simsimd/build.rs CHANGED
@@ -17,7 +17,17 @@ fn main() {
17
17
 
18
18
  let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
19
19
  let flags_to_try = match target_arch.as_str() {
20
- "arm" | "aarch64" => vec!["SIMSIMD_TARGET_NEON", "SIMSIMD_TARGET_SVE"],
20
+ "arm" | "aarch64" => vec![
21
+ "SIMSIMD_TARGET_SVE2",
22
+ "SIMSIMD_TARGET_SVE_BF16",
23
+ "SIMSIMD_TARGET_SVE_F16",
24
+ "SIMSIMD_TARGET_SVE_I8",
25
+ "SIMSIMD_TARGET_SVE",
26
+ "SIMSIMD_TARGET_NEON_BF16",
27
+ "SIMSIMD_TARGET_NEON_F16",
28
+ "SIMSIMD_TARGET_NEON_I8",
29
+ "SIMSIMD_TARGET_NEON",
30
+ ],
21
31
  _ => vec![
22
32
  "SIMSIMD_TARGET_SAPPHIRE",
23
33
  "SIMSIMD_TARGET_GENOA",
package/simsimd/c/lib.c CHANGED
@@ -20,6 +20,9 @@
20
20
  #if !defined(SIMSIMD_TARGET_SVE) && (defined(__linux__))
21
21
  #define SIMSIMD_TARGET_SVE 1
22
22
  #endif
23
+ #if !defined(SIMSIMD_TARGET_SVE2) && (defined(__linux__))
24
+ #define SIMSIMD_TARGET_SVE2 1
25
+ #endif
23
26
  #if !defined(SIMSIMD_TARGET_HASWELL) && (defined(_MSC_VER) || defined(__APPLE__) || defined(__linux__))
24
27
  #define SIMSIMD_TARGET_HASWELL 1
25
28
  #endif
@@ -42,18 +45,11 @@
42
45
  extern "C" {
43
46
  #endif
44
47
 
45
- simsimd_capability_t simsimd_capabilities(void) {
46
- static simsimd_capability_t static_capabilities = simsimd_cap_any_k;
47
- if (static_capabilities == simsimd_cap_any_k)
48
- static_capabilities = simsimd_capabilities_implementation();
49
- return static_capabilities;
50
- }
51
-
52
48
  // Every time a function is called, it checks if the metric is already loaded. If not, it fetches it.
53
49
  // If no metric is found, it returns NaN. We can obtain NaN by dividing 0.0 by 0.0, but that annoys
54
50
  // the MSVC compiler. Instead we can directly write-in the signaling NaN (0x7FF0000000000001)
55
51
  // or the qNaN (0x7FF8000000000000).
56
- #define SIMSIMD_METRIC_DECLARATION(name, extension, type) \
52
+ #define SIMSIMD_DECLARATION_DENSE(name, extension, type) \
57
53
  SIMSIMD_DYNAMIC void simsimd_##name##_##extension(simsimd_##type##_t const* a, simsimd_##type##_t const* b, \
58
54
  simsimd_size_t n, simsimd_distance_t* results) { \
59
55
  static simsimd_metric_punned_t metric = 0; \
@@ -69,45 +65,100 @@ simsimd_capability_t simsimd_capabilities(void) {
69
65
  metric(a, b, n, results); \
70
66
  }
71
67
 
68
+ #define SIMSIMD_DECLARATION_SPARSE(name, extension, type) \
69
+ SIMSIMD_DYNAMIC void simsimd_##name##_##extension(simsimd_##type##_t const* a, simsimd_##type##_t const* b, \
70
+ simsimd_size_t a_length, simsimd_size_t b_length, \
71
+ simsimd_distance_t* result) { \
72
+ static simsimd_metric_sparse_punned_t metric = 0; \
73
+ if (metric == 0) { \
74
+ simsimd_capability_t used_capability; \
75
+ simsimd_find_metric_punned(simsimd_metric_##name##_k, simsimd_datatype_##extension##_k, \
76
+ simsimd_capabilities(), simsimd_cap_any_k, (simsimd_metric_punned_t*)(&metric), \
77
+ &used_capability); \
78
+ if (!metric) { \
79
+ *(simsimd_u64_t*)result = 0x7FF0000000000001ull; \
80
+ return; \
81
+ } \
82
+ } \
83
+ metric(a, b, a_length, b_length, result); \
84
+ }
85
+
86
+ #define SIMSIMD_DECLARATION_CURVED(name, extension, type) \
87
+ SIMSIMD_DYNAMIC void simsimd_##name##_##extension(simsimd_##type##_t const* a, simsimd_##type##_t const* b, \
88
+ simsimd_##type##_t const* c, simsimd_size_t n, \
89
+ simsimd_distance_t* result) { \
90
+ static simsimd_metric_curved_punned_t metric = 0; \
91
+ if (metric == 0) { \
92
+ simsimd_capability_t used_capability; \
93
+ simsimd_find_metric_punned(simsimd_metric_##name##_k, simsimd_datatype_##extension##_k, \
94
+ simsimd_capabilities(), simsimd_cap_any_k, (simsimd_metric_punned_t*)(&metric), \
95
+ &used_capability); \
96
+ if (!metric) { \
97
+ *(simsimd_u64_t*)result = 0x7FF0000000000001ull; \
98
+ return; \
99
+ } \
100
+ } \
101
+ metric(a, b, c, n, result); \
102
+ }
103
+
72
104
  // Dot products
73
- SIMSIMD_METRIC_DECLARATION(dot, f16, f16)
74
- SIMSIMD_METRIC_DECLARATION(dot, bf16, bf16)
75
- SIMSIMD_METRIC_DECLARATION(dot, f32, f32)
76
- SIMSIMD_METRIC_DECLARATION(dot, f64, f64)
77
- SIMSIMD_METRIC_DECLARATION(dot, f16c, f16)
78
- SIMSIMD_METRIC_DECLARATION(dot, bf16c, bf16)
79
- SIMSIMD_METRIC_DECLARATION(dot, f32c, f32)
80
- SIMSIMD_METRIC_DECLARATION(dot, f64c, f64)
81
- SIMSIMD_METRIC_DECLARATION(vdot, f16c, f16)
82
- SIMSIMD_METRIC_DECLARATION(vdot, bf16c, bf16)
83
- SIMSIMD_METRIC_DECLARATION(vdot, f32c, f32)
84
- SIMSIMD_METRIC_DECLARATION(vdot, f64c, f64)
105
+ SIMSIMD_DECLARATION_DENSE(dot, f16, f16)
106
+ SIMSIMD_DECLARATION_DENSE(dot, bf16, bf16)
107
+ SIMSIMD_DECLARATION_DENSE(dot, f32, f32)
108
+ SIMSIMD_DECLARATION_DENSE(dot, f64, f64)
109
+ SIMSIMD_DECLARATION_DENSE(dot, f16c, f16)
110
+ SIMSIMD_DECLARATION_DENSE(dot, bf16c, bf16)
111
+ SIMSIMD_DECLARATION_DENSE(dot, f32c, f32)
112
+ SIMSIMD_DECLARATION_DENSE(dot, f64c, f64)
113
+ SIMSIMD_DECLARATION_DENSE(vdot, f16c, f16)
114
+ SIMSIMD_DECLARATION_DENSE(vdot, bf16c, bf16)
115
+ SIMSIMD_DECLARATION_DENSE(vdot, f32c, f32)
116
+ SIMSIMD_DECLARATION_DENSE(vdot, f64c, f64)
85
117
 
86
118
  // Spatial distances
87
- SIMSIMD_METRIC_DECLARATION(cos, i8, i8)
88
- SIMSIMD_METRIC_DECLARATION(cos, f16, f16)
89
- SIMSIMD_METRIC_DECLARATION(cos, bf16, bf16)
90
- SIMSIMD_METRIC_DECLARATION(cos, f32, f32)
91
- SIMSIMD_METRIC_DECLARATION(cos, f64, f64)
92
- SIMSIMD_METRIC_DECLARATION(l2sq, i8, i8)
93
- SIMSIMD_METRIC_DECLARATION(l2sq, f16, f16)
94
- SIMSIMD_METRIC_DECLARATION(l2sq, bf16, bf16)
95
- SIMSIMD_METRIC_DECLARATION(l2sq, f32, f32)
96
- SIMSIMD_METRIC_DECLARATION(l2sq, f64, f64)
119
+ SIMSIMD_DECLARATION_DENSE(cos, i8, i8)
120
+ SIMSIMD_DECLARATION_DENSE(cos, f16, f16)
121
+ SIMSIMD_DECLARATION_DENSE(cos, bf16, bf16)
122
+ SIMSIMD_DECLARATION_DENSE(cos, f32, f32)
123
+ SIMSIMD_DECLARATION_DENSE(cos, f64, f64)
124
+ SIMSIMD_DECLARATION_DENSE(l2sq, i8, i8)
125
+ SIMSIMD_DECLARATION_DENSE(l2sq, f16, f16)
126
+ SIMSIMD_DECLARATION_DENSE(l2sq, bf16, bf16)
127
+ SIMSIMD_DECLARATION_DENSE(l2sq, f32, f32)
128
+ SIMSIMD_DECLARATION_DENSE(l2sq, f64, f64)
129
+ SIMSIMD_DECLARATION_DENSE(l2, i8, i8)
130
+ SIMSIMD_DECLARATION_DENSE(l2, f16, f16)
131
+ SIMSIMD_DECLARATION_DENSE(l2, bf16, bf16)
132
+ SIMSIMD_DECLARATION_DENSE(l2, f32, f32)
133
+ SIMSIMD_DECLARATION_DENSE(l2, f64, f64)
97
134
 
98
135
  // Binary distances
99
- SIMSIMD_METRIC_DECLARATION(hamming, b8, b8)
100
- SIMSIMD_METRIC_DECLARATION(jaccard, b8, b8)
136
+ SIMSIMD_DECLARATION_DENSE(hamming, b8, b8)
137
+ SIMSIMD_DECLARATION_DENSE(jaccard, b8, b8)
101
138
 
102
139
  // Probability distributions
103
- SIMSIMD_METRIC_DECLARATION(kl, f16, f16)
104
- SIMSIMD_METRIC_DECLARATION(kl, bf16, bf16)
105
- SIMSIMD_METRIC_DECLARATION(kl, f32, f32)
106
- SIMSIMD_METRIC_DECLARATION(kl, f64, f64)
107
- SIMSIMD_METRIC_DECLARATION(js, f16, f16)
108
- SIMSIMD_METRIC_DECLARATION(js, bf16, bf16)
109
- SIMSIMD_METRIC_DECLARATION(js, f32, f32)
110
- SIMSIMD_METRIC_DECLARATION(js, f64, f64)
140
+ SIMSIMD_DECLARATION_DENSE(kl, f16, f16)
141
+ SIMSIMD_DECLARATION_DENSE(kl, bf16, bf16)
142
+ SIMSIMD_DECLARATION_DENSE(kl, f32, f32)
143
+ SIMSIMD_DECLARATION_DENSE(kl, f64, f64)
144
+ SIMSIMD_DECLARATION_DENSE(js, f16, f16)
145
+ SIMSIMD_DECLARATION_DENSE(js, bf16, bf16)
146
+ SIMSIMD_DECLARATION_DENSE(js, f32, f32)
147
+ SIMSIMD_DECLARATION_DENSE(js, f64, f64)
148
+
149
+ // Sparse sets
150
+ SIMSIMD_DECLARATION_SPARSE(intersect, u16, u16)
151
+ SIMSIMD_DECLARATION_SPARSE(intersect, u32, u32)
152
+
153
+ // Curved spaces
154
+ SIMSIMD_DECLARATION_CURVED(bilinear, f64, f64)
155
+ SIMSIMD_DECLARATION_CURVED(mahalanobis, f64, f64)
156
+ SIMSIMD_DECLARATION_CURVED(bilinear, f32, f32)
157
+ SIMSIMD_DECLARATION_CURVED(mahalanobis, f32, f32)
158
+ SIMSIMD_DECLARATION_CURVED(bilinear, f16, f16)
159
+ SIMSIMD_DECLARATION_CURVED(mahalanobis, f16, f16)
160
+ SIMSIMD_DECLARATION_CURVED(bilinear, bf16, bf16)
161
+ SIMSIMD_DECLARATION_CURVED(mahalanobis, bf16, bf16)
111
162
 
112
163
  SIMSIMD_DYNAMIC int simsimd_uses_neon(void) { return (simsimd_capabilities() & simsimd_cap_neon_k) != 0; }
113
164
  SIMSIMD_DYNAMIC int simsimd_uses_neon_f16(void) { return (simsimd_capabilities() & simsimd_cap_neon_f16_k) != 0; }
@@ -122,6 +173,87 @@ SIMSIMD_DYNAMIC int simsimd_uses_skylake(void) { return (simsimd_capabilities()
122
173
  SIMSIMD_DYNAMIC int simsimd_uses_ice(void) { return (simsimd_capabilities() & simsimd_cap_ice_k) != 0; }
123
174
  SIMSIMD_DYNAMIC int simsimd_uses_genoa(void) { return (simsimd_capabilities() & simsimd_cap_genoa_k) != 0; }
124
175
  SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void) { return (simsimd_capabilities() & simsimd_cap_sapphire_k) != 0; }
176
+ SIMSIMD_DYNAMIC int simsimd_uses_dynamic_dispatch(void) { return 1; }
177
+
178
+ SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void) {
179
+ static simsimd_capability_t static_capabilities = simsimd_cap_any_k;
180
+ if (static_capabilities != simsimd_cap_any_k)
181
+ return static_capabilities;
182
+
183
+ static_capabilities = _simsimd_capabilities_implementation();
184
+
185
+ // In multithreaded applications we need to ensure that the function pointers are pre-initialized,
186
+ // so the first time we are probing for capabilities, we should also probe all of our metrics
187
+ // with dummy inputs:
188
+ simsimd_distance_t dummy_results_buffer[2];
189
+ simsimd_distance_t* dummy_results = &dummy_results_buffer[0];
190
+ void* dummy = 0;
191
+
192
+ // Dense:
193
+ simsimd_dot_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
194
+ simsimd_dot_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
195
+ simsimd_dot_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
196
+ simsimd_dot_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
197
+ simsimd_dot_f16c((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
198
+ simsimd_dot_bf16c((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
199
+ simsimd_dot_f32c((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
200
+ simsimd_dot_f64c((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
201
+ simsimd_vdot_f16c((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
202
+ simsimd_vdot_bf16c((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
203
+ simsimd_vdot_f32c((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
204
+ simsimd_vdot_f64c((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
205
+ simsimd_cos_i8((simsimd_i8_t*)dummy, (simsimd_i8_t*)dummy, 0, dummy_results);
206
+ simsimd_cos_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
207
+ simsimd_cos_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
208
+ simsimd_cos_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
209
+ simsimd_cos_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
210
+ simsimd_l2sq_i8((simsimd_i8_t*)dummy, (simsimd_i8_t*)dummy, 0, dummy_results);
211
+ simsimd_l2sq_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
212
+ simsimd_l2sq_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
213
+ simsimd_l2sq_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
214
+ simsimd_l2sq_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
215
+ simsimd_l2_i8((simsimd_i8_t*)dummy, (simsimd_i8_t*)dummy, 0, dummy_results);
216
+ simsimd_l2_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
217
+ simsimd_l2_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
218
+ simsimd_l2_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
219
+ simsimd_l2_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
220
+ simsimd_hamming_b8((simsimd_b8_t*)dummy, (simsimd_b8_t*)dummy, 0, dummy_results);
221
+ simsimd_jaccard_b8((simsimd_b8_t*)dummy, (simsimd_b8_t*)dummy, 0, dummy_results);
222
+ simsimd_kl_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
223
+ simsimd_kl_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
224
+ simsimd_kl_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
225
+ simsimd_kl_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
226
+ simsimd_js_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
227
+ simsimd_js_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
228
+ simsimd_js_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
229
+ simsimd_js_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
230
+
231
+ // Sparse
232
+ simsimd_intersect_u16((simsimd_u16_t*)dummy, (simsimd_u16_t*)dummy, 0, 0, dummy_results);
233
+ simsimd_intersect_u32((simsimd_u32_t*)dummy, (simsimd_u32_t*)dummy, 0, 0, dummy_results);
234
+
235
+ // Curved:
236
+ simsimd_bilinear_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
237
+ simsimd_mahalanobis_f64((simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, (simsimd_f64_t*)dummy, 0, dummy_results);
238
+ simsimd_bilinear_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
239
+ simsimd_mahalanobis_f32((simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, (simsimd_f32_t*)dummy, 0, dummy_results);
240
+ simsimd_bilinear_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
241
+ simsimd_mahalanobis_f16((simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, (simsimd_f16_t*)dummy, 0, dummy_results);
242
+ simsimd_bilinear_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
243
+ simsimd_mahalanobis_bf16((simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, (simsimd_bf16_t*)dummy, 0, dummy_results);
244
+
245
+ return static_capabilities;
246
+ }
247
+
248
+ SIMSIMD_DYNAMIC void simsimd_find_metric_punned( //
249
+ simsimd_metric_kind_t kind, //
250
+ simsimd_datatype_t datatype, //
251
+ simsimd_capability_t supported, //
252
+ simsimd_capability_t allowed, //
253
+ simsimd_metric_punned_t* metric_output, //
254
+ simsimd_capability_t* capability_output) {
255
+ _simsimd_find_metric_punned_implementation(kind, datatype, supported, allowed, metric_output, capability_output);
256
+ }
125
257
 
126
258
  #ifdef __cplusplus
127
259
  }
@@ -73,14 +73,14 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_serial(simsimd_b8_t const* a, simsimd_b8_
73
73
  simsimd_i32_t intersection = 0, union_ = 0;
74
74
  for (simsimd_size_t i = 0; i != n_words; ++i)
75
75
  intersection += simsimd_popcount_b8(a[i] & b[i]), union_ += simsimd_popcount_b8(a[i] | b[i]);
76
- *result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
76
+ *result = (union_ != 0) ? 1 - (simsimd_f64_t)intersection / (simsimd_f64_t)union_ : 1;
77
77
  }
78
78
 
79
79
  #if SIMSIMD_TARGET_ARM
80
80
  #if SIMSIMD_TARGET_NEON
81
81
  #pragma GCC push_options
82
- #pragma GCC target("+simd")
83
- #pragma clang attribute push(__attribute__((target("+simd"))), apply_to = function)
82
+ #pragma GCC target("arch=armv8.2-a+simd")
83
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+simd"))), apply_to = function)
84
84
 
85
85
  SIMSIMD_PUBLIC void simsimd_hamming_b8_neon(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words,
86
86
  simsimd_distance_t* result) {
@@ -110,7 +110,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_neon(simsimd_b8_t const* a, simsimd_b8_t
110
110
  // Handle the tail
111
111
  for (; i != n_words; ++i)
112
112
  intersection += simsimd_popcount_b8(a[i] & b[i]), union_ += simsimd_popcount_b8(a[i] | b[i]);
113
- *result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
113
+ *result = (union_ != 0) ? 1 - (simsimd_f64_t)intersection / (simsimd_f64_t)union_ : 1;
114
114
  }
115
115
 
116
116
  #pragma clang attribute pop
@@ -119,8 +119,8 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_neon(simsimd_b8_t const* a, simsimd_b8_t
119
119
 
120
120
  #if SIMSIMD_TARGET_SVE
121
121
  #pragma GCC push_options
122
- #pragma GCC target("+sve")
123
- #pragma clang attribute push(__attribute__((target("+sve"))), apply_to = function)
122
+ #pragma GCC target("arch=armv8.2-a+sve")
123
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve"))), apply_to = function)
124
124
 
125
125
  SIMSIMD_PUBLIC void simsimd_hamming_b8_sve(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words,
126
126
  simsimd_distance_t* result) {
@@ -148,7 +148,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_sve(simsimd_b8_t const* a, simsimd_b8_t c
148
148
  union_ += svaddv_u8(svptrue_b8(), svcnt_u8_x(svptrue_b8(), svorr_u8_m(svptrue_b8(), a_vec, b_vec)));
149
149
  i += svcntb();
150
150
  } while (i < n_words);
151
- *result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
151
+ *result = (union_ != 0) ? 1 - (simsimd_f64_t)intersection / (simsimd_f64_t)union_ : 1;
152
152
  }
153
153
 
154
154
  #pragma clang attribute pop
@@ -159,8 +159,8 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_sve(simsimd_b8_t const* a, simsimd_b8_t c
159
159
  #if SIMSIMD_TARGET_X86
160
160
  #if SIMSIMD_TARGET_ICE
161
161
  #pragma GCC push_options
162
- #pragma GCC target("avx512f", "avx512vl", "bmi2", "avx512bw", "avx512vpopcntdq")
163
- #pragma clang attribute push(__attribute__((target("avx512f,avx512vl,bmi2,avx512bw,avx512vpopcntdq"))), \
162
+ #pragma GCC target("avx2", "avx512f", "avx512vl", "bmi2", "avx512bw", "avx512vpopcntdq")
163
+ #pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2,avx512bw,avx512vpopcntdq"))), \
164
164
  apply_to = function)
165
165
 
166
166
  SIMSIMD_PUBLIC void simsimd_hamming_b8_ice(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words,
@@ -213,7 +213,7 @@ simsimd_jaccard_b8_ice_cycle:
213
213
 
214
214
  simsimd_size_t intersection = _mm512_reduce_add_epi64(intersection_vec),
215
215
  union_ = _mm512_reduce_add_epi64(union_vec);
216
- *result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
216
+ *result = (union_ != 0) ? 1 - (simsimd_f64_t)intersection / (simsimd_f64_t)union_ : 1;
217
217
  }
218
218
 
219
219
  #pragma clang attribute pop
@@ -245,7 +245,7 @@ SIMSIMD_PUBLIC void simsimd_jaccard_b8_haswell(simsimd_b8_t const* a, simsimd_b8
245
245
  union_ += _mm_popcnt_u64(*(simsimd_u64_t const*)a | *(simsimd_u64_t const*)b);
246
246
  for (; n_words; --n_words, ++a, ++b)
247
247
  intersection += _mm_popcnt_u32(*a & *b), union_ += _mm_popcnt_u32(*a | *b);
248
- *result = (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 1;
248
+ *result = (union_ != 0) ? 1 - (simsimd_f64_t)intersection / (simsimd_f64_t)union_ : 1;
249
249
  }
250
250
 
251
251
  #pragma clang attribute pop