milliams / plotlib
1
use std::f64;
2
use std::iter::{Skip, Zip};
3
use std::slice::Iter;
4

5
pub trait PairWise<T> {
6
    fn pairwise(&self) -> Zip<Iter<T>, Skip<Iter<T>>>;
7
}
8

9
impl<T> PairWise<T> for [T] {
10 1
    fn pairwise(&self) -> Zip<Iter<T>, Skip<Iter<T>>> {
11 1
        self.iter().zip(self.iter().skip(1))
12
    }
13
}
14

15 1
fn _mean(s: &[f64]) -> f64 {
16 1
    s.iter().map(|v| v / s.len() as f64).sum()
17
}
18

19 1
pub fn median(s: &[f64]) -> f64 {
20 1
    let mut s = s.to_owned();
21 1
    s.sort_by(|a, b| a.partial_cmp(b).unwrap());
22 1
    match s.len() % 2 {
23 1
        0 => (s[(s.len() / 2) - 1] / 2.) + (s[(s.len() / 2)] / 2.),
24 1
        _ => s[s.len() / 2],
25
    }
26
}
27

28 1
pub fn quartiles(s: &[f64]) -> (f64, f64, f64) {
29 1
    if s.len() == 1 {
30 1
        return (s[0], s[0], s[0]);
31
    }
32 1
    let mut s = s.to_owned();
33 1
    s.sort_by(|a, b| a.partial_cmp(b).unwrap());
34 1
    let (a, b) = if s.len() % 2 == 0 {
35 1
        s.split_at(s.len() / 2)
36
    } else {
37 1
        (&s[..(s.len() / 2)], &s[((s.len() / 2) + 1)..])
38
    };
39 1
    (median(a), median(&s), median(b))
40
}
41

42
/// Given a slice of numbers, return the minimum and maximum values
43 0
pub fn range(s: &[f64]) -> (f64, f64) {
44 0
    let mut min = f64::INFINITY;
45 0
    let mut max = f64::NEG_INFINITY;
46 0
    for &v in s {
47 0
        min = min.min(v);
48 0
        max = max.max(v);
49
    }
50 0
    (min, max)
51
}
52

53
/// Floor or ceiling the min or max to zero to avoid them both having the same value
54 1
pub fn pad_range_to_zero(min: f64, max: f64) -> (f64, f64) {
55 1
    if (min - max).abs() < std::f64::EPSILON {
56
        (
57 1
            if min > 0. { 0. } else { min },
58 1
            if max < 0. { 0. } else { max },
59
        )
60
    } else {
61 1
        (min, max)
62
    }
63
}
64

65
#[cfg(test)]
66
mod tests {
67
    use super::*;
68

69
    #[test]
70 1
    fn test_pairwise() {
71 1
        let a = [1, 2, 3, 4, 5];
72 1
        assert_eq!(a.pairwise().nth(0).unwrap(), (&1, &2));
73 1
        assert_eq!(a.pairwise().last().unwrap(), (&4, &5));
74 1
        assert_eq!(a.pairwise().len(), a.len() - 1);
75

76 1
        let a = [1, 2];
77 1
        assert_eq!(a.pairwise().nth(0).unwrap(), (&1, &2));
78 1
        assert_eq!(a.pairwise().last().unwrap(), (&1, &2));
79 1
        assert_eq!(a.pairwise().len(), a.len() - 1);
80

81 1
        let a = [1];
82 1
        assert!(a.pairwise().nth(0).is_none());
83

84 1
        let b: Vec<f64> = vec![0.0, 0.1, 0.2];
85 1
        assert_eq!(b.pairwise().nth(0).unwrap(), (&0.0, &0.1));
86
    }
87

88
    #[test]
89 1
    fn test_mean() {
90
        // TODO should error: mean(&[]);
91 1
        assert_eq!(_mean(&[1.]), 1.);
92 1
        assert_eq!(_mean(&[1., 2.]), 1.5);
93 1
        assert_eq!(_mean(&[1., 2., 3.]), 2.);
94
    }
95

96
    #[test]
97 1
    fn test_median() {
98
        // TODO should error: median(&[]);
99 1
        assert_eq!(median(&[1.]), 1.);
100 1
        assert_eq!(median(&[1., 2.]), 1.5);
101 1
        assert_eq!(median(&[1., 2., 4.]), 2.);
102 1
        assert_eq!(median(&[1., 2., 3., 7.]), 2.5);
103
    }
104

105
    #[test]
106 1
    fn test_quartiles() {
107
        // TODO should error: quartiles(&[]);
108 1
        assert_eq!(quartiles(&[1.]), (1., 1., 1.));
109 1
        assert_eq!(quartiles(&[1., 2.]), (1., 1.5, 2.));
110 1
        assert_eq!(quartiles(&[1., 2., 4.]), (1., 2., 4.));
111 1
        assert_eq!(quartiles(&[1., 2., 3., 4.]), (1.5, 2.5, 3.5));
112
    }
113

114
    #[test]
115 1
    fn test_pad_range_to_zero() {
116 1
        assert_eq!(pad_range_to_zero(2.0, 2.0), (0.0, 2.0));
117 1
        assert_eq!(pad_range_to_zero(-2.0, 2.0), (-2.0, 2.0));
118 1
        assert_eq!(pad_range_to_zero(-2.0, -2.0), (-2.0, 0.0));
119
    }
120
}

Read our documentation on viewing source code .

Loading