1use std::{cmp::Ordering, ops::{Add, AddAssign, Div, Mul, Sub}};
2use num::{Float, NumCast};
3
4pub fn count<T>(data: &[T]) -> usize {
6 data.iter().count()
7}
8
9pub fn min<T>(data: &[T]) -> Option<T>
11where
12 T: PartialOrd + Copy,
13{
14 if data.is_empty() {
15 return None;
16 }
17
18 let mut min_result = data[0];
19
20 for &item in data.iter().skip(1) {
21 if min_result > item {
22 min_result = item;
23 }
24 }
25
26 Some(min_result)
27}
28
29
30pub fn max<T>(data: &[T]) -> Option<T>
32where
33 T: PartialOrd + Copy,
34{
35 if data.is_empty() {
36 return None;
37 }
38
39 let mut max_result = data[0];
40
41 for &item in data.iter().skip(1) {
42 if max_result < item {
43 max_result = item;
44 }
45 }
46
47 Some(max_result)
48}
49
50pub fn avg<T>(data: &[T]) -> Option<f64>
52where
53 T: std::convert::Into<f64> + Copy,
54{
55 if data.is_empty() {
56 return None;
57 }
58
59 let mut result = 0.0;
60 let mut count = 0;
61
62 for &item in data {
63 let value: f64 = item.into();
64 result += value;
65 count += 1;
66 }
67
68 Some(result / count as f64)
69}
70
71pub fn median<T>(numbers: &mut [T]) -> Option<T>
73where
74 T: PartialOrd + Copy + Add<Output = T> + Div<Output = T> + From<u8>,
75{
76
77 if numbers.is_empty() {
78 return None;
79 }
80 numbers.sort_by(|a, b| {
81 a.partial_cmp(b).unwrap_or_else(|| {
82 Ordering::Equal
84 })
85 });
86
87 let len = numbers.len();
88 let mid = len / 2;
89
90 if len % 2 == 0 {
91 Some((numbers[mid - 1] + numbers[mid]) / T::from(2u8))
93 } else {
94 Some(numbers[mid])
96 }
97}
98
99pub fn std_dev<T, U>(data: &[T]) -> U
101where
102 T: NumCast + Copy,
103 U: Float + AddAssign + NumCast,
104{
105 if data.len() < 2 {
106 return U::zero();
107 }
108
109 let n = U::from(data.len()).unwrap();
110 let n_minus_one = U::from(data.len() - 1).unwrap();
111
112 let sum = data.iter()
114 .map(|&x| U::from(x).unwrap())
115 .fold(U::zero(), |acc, x| acc + x);
116
117 let mean = sum / n;
118
119 let variance = data.iter()
121 .map(|&x| {
122 let val = U::from(x).unwrap();
123 let diff = val - mean;
124 diff * diff
125 })
126 .fold(U::zero(), |acc, x| acc + x) / n_minus_one;
127
128 variance.sqrt()
129}