sklears_compose/execution/
simd_utils.rs1#[must_use]
8pub fn mean_vec(vec: &[f32]) -> f32 {
9 if vec.is_empty() {
10 0.0
11 } else {
12 vec.iter().sum::<f32>() / vec.len() as f32
13 }
14}
15
16#[must_use]
18pub fn variance_vec(vec: &[f32]) -> f32 {
19 if vec.len() <= 1 {
20 return 0.0;
21 }
22 let mean = mean_vec(vec);
23 vec.iter().map(|x| (x - mean).powi(2)).sum::<f32>() / vec.len() as f32
24}
25
26#[must_use]
28pub fn sum_vec(vec: &[f32]) -> f32 {
29 vec.iter().sum()
30}
31
32pub fn add_vec(a: &[f32], b: &[f32], result: &mut [f32]) {
34 assert_eq!(a.len(), b.len());
35 assert_eq!(a.len(), result.len());
36
37 for i in 0..a.len() {
38 result[i] = a[i] + b[i];
39 }
40}
41
42pub fn multiply_vec(a: &[f32], b: &[f32], result: &mut [f32]) {
44 assert_eq!(a.len(), b.len());
45 assert_eq!(a.len(), result.len());
46
47 for i in 0..a.len() {
48 result[i] = a[i] * b[i];
49 }
50}
51
52pub fn divide_vec(a: &[f32], b: &[f32], result: &mut [f32]) {
54 assert_eq!(a.len(), b.len());
55 assert_eq!(a.len(), result.len());
56
57 for i in 0..a.len() {
58 result[i] = a[i] / b[i];
59 }
60}
61
62#[must_use]
64pub fn dot_product(a: &[f32], b: &[f32]) -> f32 {
65 assert_eq!(a.len(), b.len());
66 a.iter().zip(b.iter()).map(|(&x, &y)| x * y).sum()
67}
68
69#[must_use]
71pub fn min_max_vec(vec: &[f32]) -> (f32, f32) {
72 if vec.is_empty() {
73 return (0.0, 0.0);
74 }
75
76 let mut min_val = vec[0];
77 let mut max_val = vec[0];
78
79 for &val in vec.iter().skip(1) {
80 if val < min_val {
81 min_val = val;
82 }
83 if val > max_val {
84 max_val = val;
85 }
86 }
87
88 (min_val, max_val)
89}
90
91pub fn divide_vec_inplace(target: &mut [f32], divisor: &[f32]) {
93 assert_eq!(target.len(), divisor.len());
94
95 for i in 0..target.len() {
96 target[i] /= divisor[i];
97 }
98}
99
100pub fn multiply_vec_inplace(target: &mut [f32], multiplier: &[f32]) {
102 assert_eq!(target.len(), multiplier.len());
103
104 for i in 0..target.len() {
105 target[i] *= multiplier[i];
106 }
107}
108
109pub fn scale_vec(vec: &[f32], scale: f32, result: &mut [f32]) {
111 assert_eq!(vec.len(), result.len());
112
113 for i in 0..vec.len() {
114 result[i] = vec[i] * scale;
115 }
116}
117
118pub fn normalize_vec(vec: &mut [f32]) {
120 let norm = dot_product(vec, vec).sqrt();
121 if norm > 0.0 {
122 for val in vec {
123 *val /= norm;
124 }
125 }
126}
127
128#[must_use]
130pub fn l2_norm(vec: &[f32]) -> f32 {
131 dot_product(vec, vec).sqrt()
132}
133
134#[must_use]
136pub fn l1_norm(vec: &[f32]) -> f32 {
137 vec.iter().map(|&x| x.abs()).sum()
138}
139
140pub fn abs_vec(vec: &[f32], result: &mut [f32]) {
142 assert_eq!(vec.len(), result.len());
143
144 for i in 0..vec.len() {
145 result[i] = vec[i].abs();
146 }
147}
148
149pub fn sqrt_vec(vec: &[f32], result: &mut [f32]) {
151 assert_eq!(vec.len(), result.len());
152
153 for i in 0..vec.len() {
154 result[i] = vec[i].sqrt();
155 }
156}
157
158pub fn exp_vec(vec: &[f32], result: &mut [f32]) {
160 assert_eq!(vec.len(), result.len());
161
162 for i in 0..vec.len() {
163 result[i] = vec[i].exp();
164 }
165}
166
167pub fn log_vec(vec: &[f32], result: &mut [f32]) {
169 assert_eq!(vec.len(), result.len());
170
171 for i in 0..vec.len() {
172 result[i] = vec[i].ln();
173 }
174}
175
176#[must_use]
178pub fn euclidean_distance(a: &[f32], b: &[f32]) -> f32 {
179 assert_eq!(a.len(), b.len());
180
181 a.iter()
182 .zip(b.iter())
183 .map(|(&x, &y)| (x - y).powi(2))
184 .sum::<f32>()
185 .sqrt()
186}
187
188#[must_use]
190pub fn cosine_similarity(a: &[f32], b: &[f32]) -> f32 {
191 assert_eq!(a.len(), b.len());
192
193 let dot = dot_product(a, b);
194 let norm_a = l2_norm(a);
195 let norm_b = l2_norm(b);
196
197 if norm_a > 0.0 && norm_b > 0.0 {
198 dot / (norm_a * norm_b)
199 } else {
200 0.0
201 }
202}