1mod binary;
9mod cosine;
10mod distance;
11mod dot_product;
12mod int4;
13mod manhattan;
14mod normalize;
15mod quantized;
16mod tier;
17
18#[cfg(test)]
19mod tests;
20
21pub use binary::BinaryVector;
22pub use cosine::{
23 batch_cosine_one_vs_many, batch_cosine_similarity, cosine_similarity, cosine_similarity_fused,
24 cosine_similarity_pre_normalized, query_norm,
25};
26pub use distance::{euclidean_distance, squared_euclidean_distance};
27pub use dot_product::{
28 DotBatch4Kernel, DotKernel, batch_dot_product, dot_product, dot_product_batch4,
29 resolved_dot_product_batch4_kernel, resolved_dot_product_kernel,
30};
31pub use int4::{Int4Params, Int4Vector};
32pub use manhattan::manhattan_distance;
33pub use normalize::normalize;
34pub use quantized::{
35 I8DotKernel, QuantizationParams, QuantizedVector, cosine_similarity_i8, dot_product_i8,
36 dot_product_i8_raw, resolved_i8_dot_kernel,
37};
38pub use tier::{
39 NormalizationHint, PreparedQuery, PreparedQueryWithMeta, QuantizationTier, QuantizedData,
40 approximate_cosine_distance, approximate_cosine_distance_prepared,
41 approximate_cosine_distance_prepared_with_meta, approximate_dot_product,
42 approximate_dot_product_prepared, approximate_int4_batch_prepared,
43 approximate_int4_batch_prepared_into, approximate_int8_batch_prepared,
44 approximate_int8_batch_prepared_into, batch_approximate_cosine_distance_prepared,
45 batch_approximate_cosine_distance_prepared_into, is_unit_norm, prepare_query,
46 prepare_query_with_norm, try_approximate_cosine_distance_prepared,
47 try_approximate_dot_product_prepared,
48};
49
50use std::sync::OnceLock;
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub struct SimdConfig {
57 pub avx512f_enabled: bool,
59 pub avx2_enabled: bool,
61 pub fma_enabled: bool,
63 pub avx512vnni_enabled: bool,
65 pub neon_enabled: bool,
67 pub dotprod_enabled: bool,
71}
72
73impl Default for SimdConfig {
74 fn default() -> Self {
75 Self::detect()
76 }
77}
78
79impl SimdConfig {
80 pub fn detect() -> Self {
82 #[cfg(target_arch = "x86_64")]
83 {
84 let avx512f_enabled = is_x86_feature_detected!("avx512f");
85
86 Self {
87 avx512f_enabled,
88 avx2_enabled: is_x86_feature_detected!("avx2"),
89 fma_enabled: is_x86_feature_detected!("fma"),
90 avx512vnni_enabled: avx512f_enabled
91 && is_x86_feature_detected!("avx512bw")
92 && is_x86_feature_detected!("avx512vnni"),
93 neon_enabled: false,
94 dotprod_enabled: false,
95 }
96 }
97 #[cfg(target_arch = "aarch64")]
98 {
99 Self {
103 avx512f_enabled: false,
104 avx2_enabled: false,
105 fma_enabled: false,
106 avx512vnni_enabled: false,
107 neon_enabled: true,
108 dotprod_enabled: std::arch::is_aarch64_feature_detected!("dotprod"),
109 }
110 }
111 #[cfg(target_arch = "wasm32")]
112 {
113 Self {
119 avx512f_enabled: false,
120 avx2_enabled: false,
121 fma_enabled: false,
122 avx512vnni_enabled: false,
123 neon_enabled: false,
124 dotprod_enabled: false,
125 }
126 }
127 #[cfg(not(any(
128 target_arch = "x86_64",
129 target_arch = "aarch64",
130 target_arch = "wasm32"
131 )))]
132 {
133 Self {
134 avx512f_enabled: false,
135 avx2_enabled: false,
136 fma_enabled: false,
137 avx512vnni_enabled: false,
138 neon_enabled: false,
139 dotprod_enabled: false,
140 }
141 }
142 }
143
144 #[inline]
148 pub fn simd128_enabled(&self) -> bool {
149 cfg!(all(target_arch = "wasm32", target_feature = "simd128"))
150 }
151
152 #[inline]
154 pub fn simd_available(&self) -> bool {
155 self.avx512f_enabled
156 || self.avx512vnni_enabled
157 || self.avx2_enabled
158 || self.neon_enabled
159 || self.simd128_enabled()
160 }
161
162 #[cfg(test)]
164 pub fn scalar_only() -> Self {
165 Self {
166 avx512f_enabled: false,
167 avx2_enabled: false,
168 fma_enabled: false,
169 avx512vnni_enabled: false,
170 neon_enabled: false,
171 dotprod_enabled: false,
172 }
173 }
174}
175
176static SIMD_CONFIG: OnceLock<SimdConfig> = OnceLock::new();
178
179#[inline]
183pub fn simd_config() -> SimdConfig {
184 *SIMD_CONFIG.get_or_init(SimdConfig::detect)
185}