dsp testing: improve api for tolerance checking
This commit is contained in:
parent
1b02f558f6
commit
43a760e57a
@ -315,9 +315,7 @@ pub fn magnitude_phase(signal: &mut [Complex<f32>]) {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::testing::{
|
||||
complex_array_is_close, complex_array_within_tolerance,
|
||||
};
|
||||
use crate::testing::complex_allclose;
|
||||
|
||||
#[test]
|
||||
fn array_push() {
|
||||
@ -334,41 +332,62 @@ mod tests {
|
||||
fn magnitude_phase_length_1_quadrant_1() {
|
||||
let mut signal: [Complex<f32>; 1] = [(1., 1.)];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(&signal, &[(2_f32.sqrt(), PI / 4.)]));
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[(2_f32.sqrt(), PI / 4.)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
|
||||
signal = [(3_f32.sqrt() / 2., 1. / 2.)];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(&signal, &[(1., PI / 6.)]));
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[(1., PI / 6.)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn magnitude_phase_length_1_quadrant_2() {
|
||||
let mut signal = [(-1., 1.)];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[(2_f32.sqrt(), 3. * PI / 4.)]
|
||||
&[(2_f32.sqrt(), 3. * PI / 4.)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
|
||||
signal = [(-1. / 2., 3_f32.sqrt() / 2.)];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(&signal, &[(1_f32, 2. * PI / 3.)]));
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[(1_f32, 2. * PI / 3.)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn magnitude_phase_length_1_quadrant_3() {
|
||||
let mut signal = [(-1. / 2_f32.sqrt(), -1. / 2_f32.sqrt())];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[(1_f32.sqrt(), -3. * PI / 4.)]
|
||||
&[(1_f32.sqrt(), -3. * PI / 4.)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
|
||||
signal = [(-1. / 2., -2_f32.sqrt())];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[((3. / 2.) as f32, -1.91063323625 as f32)]
|
||||
&[((3. / 2.) as f32, -1.91063323625 as f32)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
}
|
||||
|
||||
@ -376,14 +395,21 @@ mod tests {
|
||||
fn magnitude_phase_length_1_quadrant_4() {
|
||||
let mut signal = [(1. / 2_f32.sqrt(), -1. / 2_f32.sqrt())];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[(1_f32.sqrt(), -1. * PI / 4.)]
|
||||
&[(1_f32.sqrt(), -1. * PI / 4.)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
|
||||
signal = [(3_f32.sqrt() / 2., -1. / 2.)];
|
||||
magnitude_phase(&mut signal);
|
||||
assert!(complex_array_is_close(&signal, &[(1_f32, -PI / 6.)]));
|
||||
assert!(complex_allclose(
|
||||
&signal,
|
||||
&[(1_f32, -PI / 6.)],
|
||||
f32::EPSILON,
|
||||
0.
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -483,7 +509,7 @@ mod tests {
|
||||
}
|
||||
let result = lockin.demodulate(&adc_samples, timestamps).unwrap();
|
||||
assert!(
|
||||
complex_array_within_tolerance(&result, &signal, 0., 1e-5),
|
||||
complex_allclose(&result, &signal, 0., 1e-5),
|
||||
"\nsignal computed: {:?},\nsignal expected: {:?}",
|
||||
result,
|
||||
signal
|
||||
|
@ -1,54 +1,27 @@
|
||||
use super::Complex;
|
||||
|
||||
pub fn f32_is_close(a: f32, b: f32) -> bool {
|
||||
(a - b).abs() <= a.abs().max(b.abs()) * f32::EPSILON
|
||||
pub fn isclose(a: f32, b: f32, rtol: f32, atol: f32) -> bool {
|
||||
(a - b).abs() <= a.abs().max(b.abs()) * rtol + atol
|
||||
}
|
||||
|
||||
pub fn complex_is_close(a: Complex<f32>, b: Complex<f32>) -> bool {
|
||||
f32_is_close(a.0, b.0) && f32_is_close(a.1, b.1)
|
||||
}
|
||||
|
||||
pub fn complex_array_is_close(a: &[Complex<f32>], b: &[Complex<f32>]) -> bool {
|
||||
let mut result: bool = true;
|
||||
a.iter().zip(b.iter()).for_each(|(i, j)| {
|
||||
result &= complex_is_close(*i, *j);
|
||||
});
|
||||
result
|
||||
}
|
||||
|
||||
pub fn within_tolerance(
|
||||
a: f32,
|
||||
b: f32,
|
||||
relative_tolerance: f32,
|
||||
fixed_tolerance: f32,
|
||||
) -> bool {
|
||||
(a - b).abs() <= a.abs().max(b.abs()) * relative_tolerance + fixed_tolerance
|
||||
}
|
||||
|
||||
pub fn complex_within_tolerance(
|
||||
pub fn complex_isclose(
|
||||
a: Complex<f32>,
|
||||
b: Complex<f32>,
|
||||
relative_tolerance: f32,
|
||||
fixed_tolerance: f32,
|
||||
rtol: f32,
|
||||
atol: f32,
|
||||
) -> bool {
|
||||
within_tolerance(a.0, b.0, relative_tolerance, fixed_tolerance)
|
||||
&& within_tolerance(a.1, b.1, relative_tolerance, fixed_tolerance)
|
||||
isclose(a.0, b.0, rtol, atol) && isclose(a.1, b.1, rtol, atol)
|
||||
}
|
||||
|
||||
pub fn complex_array_within_tolerance(
|
||||
pub fn complex_allclose(
|
||||
a: &[Complex<f32>],
|
||||
b: &[Complex<f32>],
|
||||
relative_tolerance: f32,
|
||||
fixed_tolerance: f32,
|
||||
rtol: f32,
|
||||
atol: f32,
|
||||
) -> bool {
|
||||
let mut result: bool = true;
|
||||
a.iter().zip(b.iter()).for_each(|(i, j)| {
|
||||
result &= complex_within_tolerance(
|
||||
*i,
|
||||
*j,
|
||||
relative_tolerance,
|
||||
fixed_tolerance,
|
||||
);
|
||||
result &= complex_isclose(*i, *j, rtol, atol);
|
||||
});
|
||||
result
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user