extern crate alloc;
use alloc::vec::Vec;
use mixed_num::traits::*;
use num::complex::Complex;
pub fn is_power_of_two<T>( x: T) -> bool
where T: num::traits::int::PrimInt
{
if T::zero()<x && (x & (x - T::one())) == T::zero()
{
return true
}
return false
}
pub fn log2( x: usize ) -> usize
{
let mut k: usize = x;
let mut i = 0;
while k != 0
{
k >>= 1;
i+=1;
}
return i - 1;
}
fn bitreverse_order<T>( arr: &mut [Complex<T>] )
where T: core::marker::Copy
{
let n:usize = arr.len();
let mut target_index:usize = 0;
for index in 0..n
{
if index<target_index
{
let temp = arr[target_index];
arr[target_index] = arr[index];
arr[index] = temp;
}
let mut mask:usize = n;
mask >>=1;
while target_index & mask != 0
{
target_index &= !mask;
mask >>=1;
}
target_index |= mask;
}
}
pub fn fft<T>( array: &mut [Complex<T>] )
where T: MixedNum + MixedNumSigned + MixedTrigonometry + MixedSqrt + MixedNumConversion<i32> + MixedReal + MixedOps + MixedPi + MixedOne
{
fft_processor(array, T::mixed_from_num(1));
bitreverse_order(array); }
pub fn ifft<T>( vec: &mut Vec<Complex<T>> )
where T: MixedNum + MixedNumSigned + MixedTrigonometry + MixedSqrt + MixedNumConversion<i32> + MixedReal + MixedOps + MixedPi + MixedOne
{
fft_processor(vec, T::mixed_from_num(-1i32));
bitreverse_order(vec); }
fn butterfly_df<T>( a: &mut Complex<T>, b: &mut Complex<T>, w:Complex<T> )
where T: MixedNum + MixedNumSigned + MixedTrigonometry + MixedSqrt + MixedOps
{
let temp_a = crate::complex::add(*a,*b);
let temp_b = crate::complex::mul_cartesian(crate::complex::sub(*a, *b), w);
*a = temp_a;
*b = temp_b;
}
fn fft_processor<T>( array: &mut [Complex<T>], dir: T )
where T: MixedNum + MixedReal + MixedNumSigned + MixedTrigonometry + MixedSqrt + MixedNumConversion<i32> + MixedOne + MixedPi + MixedOps
{
let scale_factor:T;
if dir == T::mixed_one()
{
scale_factor=T::mixed_from_num(2i32);
}
else
{
scale_factor=T::mixed_from_num(1i32);
}
let n = array.len();
let mut w = Vec::<Complex<T>>::with_capacity(n/2);
w.push( Complex::new( <T>::mixed_from_num(1i32), <T>::mixed_from_num(0i32) ) );
let mut angle:T = dir*-<T>::mixed_pi()*T::mixed_from_num(2);
for _i in 0..log2(n)
{
angle = angle / <T>::mixed_from_num(2);
}
let mut phase_inc = angle;
for _i in 1..n/2
{
let imag = phase_inc.mixed_sin();
let real = phase_inc.mixed_cos();
phase_inc = phase_inc+angle;
w.push( Complex::new( real, imag ) );
}
let mut num_butt: usize = n/2;
let mut num_blocks: usize = 1;
let stages = log2(n);
let mut w_idx_step_size = 1;
for _stage in 1..=stages
{
for block in 0..num_blocks
{
let pa = block*n/num_blocks;
let pb = block*n/num_blocks + num_butt;
for butt in 0..num_butt
{
let mut a = crate::complex::div_cartesian( array[pa+butt], scale_factor );
let mut b = crate::complex::div_cartesian( array[pb+butt], scale_factor );
let w_idx:usize = w_idx_step_size*(butt);
let w_temp = w[ w_idx ];
butterfly_df( &mut a, &mut b, w_temp );
array[pa+butt] = a;
array[pb+butt] = b;
}
}
w_idx_step_size *= 2;
num_blocks *= 2;
num_butt /= 2;
}
}