powers_rs/utils.rs
1/// Helper function for evaluating the dot product between two vectors.
2/// This implementation expect f64 slices and does not use any kind
3/// of SSE operations. The slices are expected to have the same length.
4///
5/// ## Example
6///
7/// ```
8/// let a = vec![1.0, 2.0, 3.0];
9/// let b = vec![1.0, 1.0, 1.0];
10///
11/// let dot = powers_rs::utils::dot_product(&a, &b);
12/// assert_eq!(dot, 6.0);
13/// ```
14pub fn dot_product(a: &[f64], b: &[f64]) -> f64 {
15 assert_eq!(a.len(), b.len());
16 let mut product = 0.0;
17 for i in 0..a.len() {
18 product += a[i] * b[i];
19 }
20 product
21}
22
23/// Helper function for generating an uniform probability distribution
24/// from a given number of samples.
25///
26/// ## Example
27///
28/// ```
29/// let count = 5;
30///
31/// let p = powers_rs::utils::uniform_prob_by_count(count);
32/// assert_eq!(p, &[0.2, 0.2, 0.2, 0.2, 0.2]);
33/// ```
34pub fn uniform_prob_by_count(count: usize) -> Vec<f64> {
35 assert!(count > 0);
36 let p = 1.0 / count as f64;
37 vec![p; count]
38}
39
40/// Helper function for evaluating the average of a
41/// series of values.
42///
43/// ## Example
44///
45/// ```
46/// let vals = [1.0, 2.0, 3.0];
47///
48/// let m = powers_rs::utils::mean(&vals);
49/// assert_eq!(m, 2.0);
50/// ```
51pub fn mean(values: &[f64]) -> f64 {
52 let total: f64 = values.iter().sum();
53 let count = values.len();
54 total / count as f64
55}
56
57/// Helper function for evaluating the standard deviation of
58/// a series of values.
59///
60/// ## Example
61///
62/// ```
63/// let vals = [1.0, 1.0, 1.0];
64///
65/// let m = powers_rs::utils::standard_deviation(&vals);
66/// assert_eq!(m, 0.0);
67/// ```
68pub fn standard_deviation(values: &[f64]) -> f64 {
69 let m = mean(values);
70 let deviations: Vec<f64> =
71 values.iter().map(|c| (c - m) * (c - m)).collect();
72 let mean_deviation = mean(&deviations);
73
74 f64::sqrt(mean_deviation)
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_dot_product() {
83 let a = vec![1.0, 2.0, 3.0];
84 let b = vec![4.0, 5.0, 6.0];
85 assert_eq!(dot_product(&a, &b), 32.0);
86 }
87
88 #[test]
89 fn test_uniform_prob_by_count() {
90 let p = uniform_prob_by_count(4);
91 assert_eq!(p, vec![0.25, 0.25, 0.25, 0.25]);
92 }
93
94 #[test]
95 fn test_mean() {
96 let values = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
97 assert_eq!(mean(&values), 5.0);
98 }
99
100 #[test]
101 fn test_standard_deviation() {
102 let values = [2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
103 assert!((standard_deviation(&values) - 2.0).abs() < 1e-9);
104 }
105}