pluto_sdr/
signal.rs

1// Author: Roman Hayn
2// MIT License 2023
3
4pub fn mean(data: &Vec<i16>) -> Option<i16> {
5    let sum = data.iter().map(|&b| b as i64).sum::<i64>() as i16;
6    let count = data.len() as i16;
7
8    match count {
9        positive if positive > 0 => Some(sum / count),
10        _ => None,
11    }
12}
13
14pub fn mean_float(data: &Vec<f32>) -> Option<f32> {
15    let sum = data.iter().map(|&b| b as f64).sum::<f64>() as f32;
16    let count = data.len() as f32;
17
18    match count {
19        positive if positive > 0.0 => Some(sum / count),
20        _ => None,
21    }
22}
23
24/// find the variance of a signal
25pub fn variance(data: &Vec<i16>) -> Option<f32> {
26    match (mean(data), data.len()) {
27        (Some(d_mean), count) if count > 0 => Some(
28            data.iter()
29                .map(|val| {
30                    let diff = d_mean - (*val);
31                    diff as f32 * diff as f32
32                })
33                .sum::<f32>()
34                / count as f32,
35        ),
36        _ => None,
37    }
38}
39
40/// Just like [crate::signal::variance()] but assumes the signal mean is 0.
41pub fn zero_mean_variance_float(data: &Vec<f32>) -> Option<f32> {
42    if data.len() > 0 {
43        return Some(
44            data.iter()
45                .map(|val| {
46                    let diff = *val;
47                    diff * diff
48                })
49                .sum::<f32>()
50                / data.len() as f32,
51        );
52    } else {
53        None
54    }
55}
56
57/// Computes highest 2^n, while 2^n < size.
58/// e.g. 513 -> 512 or 87 -> 64.
59pub fn next_lower_power_two(size: usize) -> usize {
60    let mut two_to_n: usize = 2;
61
62    loop {
63        let temp: usize = two_to_n * 2;
64        if temp > size {
65            break;
66        }
67        two_to_n = temp;
68    }
69    two_to_n
70}
71
72/// Computes next lowest 2^n while 2^n > size.
73/// e.g. 501 -> 512 or 42 -> 64.
74pub fn next_upper_power_two(size: usize) -> usize {
75    let mut two_to_n: usize = 2;
76
77    loop {
78        let temp: usize = two_to_n * 2;
79        two_to_n = temp;
80        if temp >= size {
81            break;
82        }
83    }
84    two_to_n
85}
86
87/// Just like [crate::signal::variance()] but assumes the signal mean is 0.
88pub fn zero_mean_variance(data: &Vec<i16>) -> Option<f32> {
89    if data.len() > 0 {
90        return Some(
91            data.iter()
92                .map(|val| {
93                    let diff = *val;
94                    diff as f32 * diff as f32
95                })
96                .sum::<f32>()
97                / data.len() as f32,
98        );
99    } else {
100        None
101    }
102}
103
104pub fn std_deviation_float(data: &Vec<f32>) -> Option<f32> {
105    match (mean_float(data), data.len()) {
106        (Some(_mean), count) if count > 0 => {
107            let var = data
108                .iter()
109                .map(|val| {
110                    let diff = _mean - (*val);
111                    diff * diff
112                })
113                .sum::<f32>()
114                / count as f32;
115
116            Some(var.sqrt())
117        }
118        _ => None,
119    }
120}
121
122pub fn std_deviation(data: &Vec<i16>) -> Option<f32> {
123    match (mean(data), data.len()) {
124        (Some(_mean), count) if count > 0 => {
125            let var = data
126                .iter()
127                .map(|val| {
128                    let diff = _mean - (*val);
129                    diff as f32 * diff as f32
130                })
131                .sum::<f32>()
132                / count as f32;
133
134            Some(var.sqrt())
135        }
136        _ => None,
137    }
138}
139
140#[cfg(test)]
141mod test {
142    use super::*;
143
144    #[test]
145    fn test_mean() {
146        let vec = vec![0, 1, 2, 4, 5, 6];
147        assert_eq!(mean(&vec).unwrap(), 3);
148    }
149
150    // Should not error on larger i16 values
151    #[test]
152    fn test_mean_big() {
153        let vec = vec![i16::MIN, i16::MIN, i16::MAX, i16::MAX];
154        assert_eq!(mean(&vec).unwrap(), 0);
155    }
156
157    #[test]
158    fn test_variance() {
159        let vec = vec![66, 30, 40, 64];
160        let res = variance(&vec).unwrap();
161        assert_eq!(res, 238.0);
162
163        let vec2 = vec![51, 21, 79, 49];
164        let res2 = variance(&vec2).unwrap();
165        assert_eq!(res2, 421.0);
166    }
167
168    #[test]
169    fn test_zero_mean_variance() {
170        let vec = vec![66, 30, 40, 64];
171        let res = zero_mean_variance(&vec).unwrap();
172        assert_eq!(res, 2738.0);
173
174        let vec2 = vec![51, 21, 79, 49];
175        let res2 = zero_mean_variance(&vec2).unwrap();
176        assert_eq!(res2, 2921.0);
177    }
178
179    #[test]
180    fn test_std_deviation() {
181        let vec = vec![66, 30, 40, 64];
182        println!("{:?}", std_deviation(&vec).unwrap());
183        let res = format!("{:.2}", std_deviation(&vec).unwrap());
184        assert_eq!(res, "15.43"); // 15.427
185
186        let vec2 = vec![51, 21, 79, 49];
187        println!("{:?}", std_deviation(&vec2).unwrap());
188        let res2 = format!("{:.2}", std_deviation(&vec2).unwrap());
189        assert_eq!(res2, "20.52"); // 20.518
190    }
191}