use core::ops::MulAssign;
use array_math::{SliceMath, SliceOps};
use num::complex::ComplexFloat;
use option_trait::Maybe;
use crate::{quantities::{Lists, OwnedListOrSingle, Matrix, OwnedList}, transforms::fourier::WhtOrdering};
pub trait Idwht<T, O, OO, const OOO: bool>: Lists<T>
where
T: ComplexFloat,
O: OwnedList<T>,
OO: Maybe<O>
{
fn idwht(self, ordering: WhtOrdering) -> Self::RowsMapped<OO>;
}
impl<'a, T, L> Idwht<T, L::RowOwned, Option<L::RowOwned>, false> for L
where
T: ComplexFloat + MulAssign<T::Real>,
L: Lists<T>,
L::RowOwned: OwnedList<T>,
{
fn idwht(self, ordering: WhtOrdering) -> Self::RowsMapped<Option<L::RowOwned>>
{
self.map_rows_into_owned(|mut h| {
let h_mut = h.as_mut_slice();
if !h_mut.len().is_power_of_two()
{
None
}
else
{
h_mut.ifwht();
match ordering
{
WhtOrdering::Sequency => {
h_mut.bit_rev_permutation();
h_mut.grey_code_permutation();
},
WhtOrdering::Hadamard => (),
WhtOrdering::Dyadic => {
h_mut.bit_rev_permutation()
},
}
Some(h)
}
})
}
}
impl<T, L> Idwht<T, L::RowOwned, L::RowOwned, true> for L
where
T: ComplexFloat + MulAssign<T::Real>,
L: Lists<T> + Matrix<T, Width = usize>,
L::RowOwned: OwnedList<T>,
[(); L::WIDTH.is_power_of_two() as usize - 1]:
{
fn idwht(self, ordering: WhtOrdering) -> Self::RowsMapped<L::RowOwned>
{
self.map_rows_into_owned(|mut h| {
let h_mut = h.as_mut_slice();
h_mut.ifwht();
match ordering
{
WhtOrdering::Sequency => {
h_mut.bit_rev_permutation();
h_mut.grey_code_permutation();
},
WhtOrdering::Hadamard => (),
WhtOrdering::Dyadic => {
h_mut.bit_rev_permutation()
},
}
h
})
}
}
#[cfg(test)]
mod test
{
use crate::transforms::fourier::{WhtOrdering, Dwht, Idwht};
#[test]
fn test()
{
let x = [19, -1, 11, -9, -7, 13, -15, 5].map(|x| x as f32);
let xf: [_; _] = x.dwht(WhtOrdering::Sequency);
let x: [_; _] = xf.idwht(WhtOrdering::Sequency);
println!("{:?}", x);
}
}