aether_primitives/
lib.rs

1extern crate num_complex;
2
3/// Shorthand for Complex<f32>
4/// Default sample type
5/// This type is repr(C), thus 2 f32s back-to-back equivalent to [f32;2]
6#[allow(non_camel_case_types)]
7pub type cf32 = num_complex::Complex32;
8
9/// Error Vector Magnitude assertion
10/// Checks each element and panics if an element in the ```actual```
11/// EVM = 10 log (P_error/P_ref) => Error vector in relation to the actually expected signal in dB.
12/// The error vector is defined as the vector between the reference symbol and the actually received signal.
13/// We achieve this by computing the norm of (actual-ref)
14/// If no EVM threshold is provided -80dB = 1e-8 = 10nano is used
15#[macro_export]
16macro_rules! assert_evm {
17
18    ($actual:expr, $ref:expr) => {
19        assert_evm!($actual,$ref,-80.0)
20    };
21
22    ($actual:expr, $ref:expr, $evm_limit_db:expr) => {
23        assert_eq!($actual.len(),$ref.len(), "Input slices/vectors must be same length");
24        for (idx, (act, re)) in $actual.iter().zip($ref).enumerate() {
25            let evm = (act - re).norm();
26            let limit = re.norm() * ($evm_limit_db / 10f32).powi(10);
27
28            if evm > limit {
29                let evm_db = evm.log10()*10f32;
30                panic!(
31                    "EVM limit exceeded: Got {}({}dB) > limit {}({}dB) for element {}. Actual {}, Expected {}",
32                    evm,evm_db,limit, $evm_limit_db, idx, act, re
33                );
34            }
35        }
36    };
37}
38
39#[macro_export]
40macro_rules! vec_align {
41    [$init:expr; $len:expr] => {
42        unimplemented!()
43    }
44}
45
46/// Neat operations on vectors and slices
47pub mod vecops;
48
49/// Fourier Transform-related
50pub mod fft;
51
52/// Resampling (up/down), Interpolation
53pub mod sampling;
54
55/// Pseudo-Random Sequence Generation
56pub mod sequence;
57
58#[cfg(test)]
59mod test {
60    use super::cf32;
61
62    #[test]
63    fn evm_correct() {
64        let refr = vec![
65            cf32::new(1f32, 0f32),
66            cf32::new(1f32, 0f32),
67            cf32::new(1f32, 0f32),
68            cf32::new(1f32, 0f32),
69        ];
70        let act = vec![
71            cf32::new(1f32, 0f32),
72            cf32::new(1f32, 0f32),
73            cf32::new(1f32, 0f32),
74            cf32::new(0.9f32, 0f32),
75        ];
76        // error should be <= 0.1
77        assert_evm!(act, refr, (-10.0));
78    }
79
80    #[test]
81    #[should_panic]
82    fn evm_fail() {
83        let refr = vec![
84            cf32::new(1f32, 0f32),
85            cf32::new(1f32, 0f32),
86            cf32::new(1f32, 0f32),
87            cf32::new(1f32, 0f32),
88        ];
89        let act = vec![
90            cf32::new(1f32, 0f32),
91            cf32::new(1f32, 0f32),
92            cf32::new(1f32, 0f32),
93            cf32::new(0.9f32, 0f32),
94        ];
95        // error should be <= 0.0
96        assert_evm!(act, refr, (0.0));
97    }
98
99    #[test]
100    fn vec_align() {
101        let _v = vec_align![cf32::default(); 2048];
102    }
103
104}