use bytemuck::cast_slice;
use num_complex::Complex;
use num_traits::Float;
pub fn deinterleave<T: Copy>(input: &[T]) -> (Vec<T>, Vec<T>) {
input.chunks_exact(2).map(|c| (c[0], c[1])).unzip()
}
pub fn deinterleave_complex64(signal: &[Complex<f64>]) -> (Vec<f64>, Vec<f64>) {
let complex_t: &[f64] = cast_slice(signal);
deinterleave(complex_t)
}
pub fn deinterleave_complex32(signal: &[Complex<f32>]) -> (Vec<f32>, Vec<f32>) {
let complex_t: &[f32] = cast_slice(signal);
deinterleave(complex_t)
}
pub fn combine_re_im<T: Float>(reals: &[T], imags: &[T]) -> Vec<Complex<T>> {
assert_eq!(reals.len(), imags.len());
reals
.iter()
.zip(imags.iter())
.map(|(z_re, z_im)| Complex::new(*z_re, *z_im))
.collect()
}
#[cfg(test)]
mod tests {
use rand::distr::StandardUniform;
use rand::rngs::SmallRng;
use rand::RngExt;
use super::*;
fn gen_test_vec(len: usize) -> Vec<usize> {
(0..len).collect()
}
fn deinterleave_naive<T: Copy>(input: &[T]) -> (Vec<T>, Vec<T>) {
input.chunks_exact(2).map(|c| (c[0], c[1])).unzip()
}
#[test]
fn deinterleaving_correctness() {
for len in [0, 1, 2, 3, 15, 16, 17, 127, 128, 129, 130, 135, 100500] {
let input = gen_test_vec(len);
let (naive_a, naive_b) = deinterleave_naive(&input);
let (opt_a, opt_b) = deinterleave(&input);
assert_eq!(naive_a, opt_a);
assert_eq!(naive_b, opt_b);
}
}
#[test]
fn test_separate_and_combine_re_im() {
let mut rng = rand::make_rng::<SmallRng>();
let complex_vec: Vec<f32> = (&mut rng)
.sample_iter(StandardUniform)
.take(16384)
.collect();
let (reals, imags) = deinterleave(&complex_vec);
let recombined_vec = combine_re_im(&reals, &imags);
let recombined_flat: &[f32] = cast_slice(recombined_vec.as_slice());
assert_eq!(complex_vec, recombined_flat);
}
}