1use std::{cmp::Ordering, ops::AddAssign};
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: &[T]) -> Option<T>
73where
74 T: PartialOrd + Clone,
75{
76 if numbers.is_empty() {
77 return None;
78 }
79
80 let len = numbers.len();
81 let mid = len / 2;
82
83 if len == 1 {
85 return Some(numbers[0].clone());
86 }
87
88 let mut sorted_numbers = numbers.to_vec();
90 sorted_numbers.sort_by(|a, b| {
91 a.partial_cmp(b).unwrap_or_else(|| {
92 Ordering::Equal
94 })
95 });
96
97 if len % 2 == 0 {
98 Some(sorted_numbers[mid - 1].clone())
102 } else {
103 Some(sorted_numbers[mid].clone())
105 }
106}
107
108pub fn std_dev<T, U>(data: &[T]) -> U
110where
111 T: NumCast + Copy,
112 U: Float + AddAssign + NumCast,
113{
114 if data.len() < 2 {
115 return U::zero();
116 }
117
118 let n = U::from(data.len()).unwrap();
119 let n_minus_one = U::from(data.len() - 1).unwrap();
120
121 let sum = data.iter()
123 .map(|&x| U::from(x).unwrap())
124 .fold(U::zero(), |acc, x| acc + x);
125
126 let mean = sum / n;
127
128 let variance = data.iter()
130 .map(|&x| {
131 let val = U::from(x).unwrap();
132 let diff = val - mean;
133 diff * diff
134 })
135 .fold(U::zero(), |acc, x| acc + x) / n_minus_one;
136
137 variance.sqrt()
138}