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}