1use std::f64::NAN;
3
4pub fn arithmetic(slice: &[f64]) -> f64 {
19 slice.iter().fold(0., |a, b| a + b) / slice.len() as f64
20}
21
22pub fn geometric(slice: &[f64]) -> f64 {
39 let product = slice.iter().fold(1., |a, b| a * b);
40 match product < 0. {
41 true => NAN,
42 false => product.powf(1. / slice.len() as f64),
43 }
44}
45
46pub fn harmonic(slice: &[f64]) -> f64 {
61 slice.len() as f64 / slice.iter().fold(0., |a, b| a + 1. / b)
62}
63
64#[cfg(test)]
65mod tests {
66 use std::f64::{ NAN, INFINITY, NEG_INFINITY };
67 use round;
68
69 macro_rules! test_mean {
70 ($func:path [ $($name:ident: $params:expr,)* ]) => {
71 $(
72 #[test]
73 fn $name() {
74 let (slice, expected): (&[f64], f64) = $params;
75 let result = $func(slice);
76 match result.is_nan() {
77 true => assert_eq!(expected.is_nan(), true),
78 false => assert_eq!(round::half_up(result, 6), expected),
79 }
80 }
81 )*
82 }
83 }
84
85 test_mean! { super::arithmetic [
86 arithmetic_1: (&[-7., -4., 1., 3., 8.], 0.2),
87 arithmetic_2: (&[-4., 1., 3., 8., 12.], 4.),
88 arithmetic_3: (&[0., 0., 0., 0., 0.], 0.),
89 arithmetic_4: (&[0., 4., 7., 9., 17.], 7.4),
90 arithmetic_5: (&[1., 2., 6., 4., 13.], 5.2),
91 arithmetic_6: (&[1., 5., 10., 20., 25.], 12.2),
92 arithmetic_7: (&[2., 3., 5., 7., 11.], 5.6),
93 arithmetic_8: (&[NEG_INFINITY, 1., 2., 3., 4.], NEG_INFINITY),
94 arithmetic_9: (&[1., 2., 3., 4., INFINITY], INFINITY),
95 ]}
96
97 test_mean! { super::geometric [
98 geometric_1: (&[-7., -4., 1., 3., 8.], 3.676833),
99 geometric_2: (&[-4., 1., 3., 8., 12.], NAN),
100 geometric_3: (&[0., 0., 0., 0., 0.], 0.),
101 geometric_4: (&[0., 4., 7., 9., 17.], 0.),
102 geometric_5: (&[1., 2., 6., 4., 13.], 3.622738),
103 geometric_6: (&[1., 5., 10., 20., 25.], 7.578583),
104 geometric_7: (&[2., 3., 5., 7., 11.], 4.706764),
105 geometric_8: (&[NEG_INFINITY, 1., 2., 3., 4.], NAN),
106 geometric_9: (&[1., 2., 3., 4., INFINITY], INFINITY),
107 ]}
108
109 test_mean! { super::harmonic [
110 harmonic_1: (&[-7., -4., 1., 3., 8.], 4.692737),
111 harmonic_2: (&[-4., 1., 3., 8., 12.], 3.870968),
112 harmonic_3: (&[0., 0., 0., 0., 0.], 0.),
113 harmonic_4: (&[0., 4., 7., 9., 17.], 0.),
114 harmonic_5: (&[1., 2., 6., 4., 13.], 2.508039),
115 harmonic_6: (&[1., 5., 10., 20., 25.], 3.597122),
116 harmonic_7: (&[2., 3., 5., 7., 11.], 3.94602),
117 harmonic_8: (&[NEG_INFINITY, 1., 2., 3., 4.], 2.4),
118 harmonic_9: (&[1., 2., 3., 4., INFINITY], 2.4),
119 ]}
120}