use num_complex::Complex;
use num_traits::Zero;
use std::sync::Arc;
use rand::distributions::{Distribution, Uniform};
use rand::{rngs::StdRng, SeedableRng};
use crate::algorithm::{butterflies, DFT};
use crate::FFT;
const RNG_SEED: [u8; 32] = [
1, 9, 1, 0, 1, 1, 4, 3, 1, 4, 9, 8, 4, 1, 4, 8, 2, 8, 1, 2, 2, 2, 6, 1, 2, 3, 4, 5, 6, 7, 8, 9,
];
pub fn random_signal(length: usize) -> Vec<Complex<f32>> {
let mut sig = Vec::with_capacity(length);
let normal_dist = Uniform::new(0.0, 10.0);
let mut rng: StdRng = SeedableRng::from_seed(RNG_SEED);
for _ in 0..length {
sig.push(Complex {
re: (normal_dist.sample(&mut rng) as f32),
im: (normal_dist.sample(&mut rng) as f32),
});
}
return sig;
}
pub fn compare_vectors(vec1: &[Complex<f32>], vec2: &[Complex<f32>]) -> bool {
assert_eq!(vec1.len(), vec2.len());
let mut sse = 0f32;
for (&a, &b) in vec1.iter().zip(vec2.iter()) {
sse = sse + (a - b).norm();
}
return (sse / vec1.len() as f32) < 0.1f32;
}
pub fn check_fft_algorithm(fft: &dyn FFT<f32>, size: usize, inverse: bool) {
assert_eq!(fft.len(), size, "Algorithm reported incorrect size");
assert_eq!(
fft.is_inverse(),
inverse,
"Algorithm reported incorrect inverse value"
);
let n = 5;
let dft = DFT::new(size, inverse);
let mut expected_input = random_signal(size * n);
let mut actual_input = expected_input.clone();
let mut multi_input = expected_input.clone();
let mut expected_output = vec![Zero::zero(); size * n];
let mut actual_output = expected_output.clone();
let mut multi_output = expected_output.clone();
dft.process_multi(&mut expected_input, &mut expected_output);
fft.process_multi(&mut multi_input, &mut multi_output);
for (input_chunk, output_chunk) in actual_input
.chunks_exact_mut(size)
.zip(actual_output.chunks_exact_mut(size))
{
fft.process(input_chunk, output_chunk);
}
assert!(
compare_vectors(&expected_output, &multi_output),
"process_multi() failed, length = {}, inverse = {}",
size,
inverse
);
}
pub fn make_butterfly(len: usize, inverse: bool) -> Arc<dyn butterflies::FFTButterfly<f32>> {
match len {
2 => Arc::new(butterflies::Butterfly2::new(inverse)),
3 => Arc::new(butterflies::Butterfly3::new(inverse)),
4 => Arc::new(butterflies::Butterfly4::new(inverse)),
5 => Arc::new(butterflies::Butterfly5::new(inverse)),
6 => Arc::new(butterflies::Butterfly6::new(inverse)),
7 => Arc::new(butterflies::Butterfly7::new(inverse)),
8 => Arc::new(butterflies::Butterfly8::new(inverse)),
16 => Arc::new(butterflies::Butterfly16::new(inverse)),
_ => panic!("Invalid butterfly size: {}", len),
}
}