extern crate num_complex;
extern crate num_traits;
use num_complex::Complex;
use num_traits::{Float, FloatConst, One};
#[allow(non_camel_case_types)]
pub type c32 = Complex<f32>;
#[allow(non_camel_case_types)]
pub type c64 = Complex<f64>;
mod complex;
mod real;
pub use real::unpack;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Operation {
Forward,
Backward,
Inverse,
}
#[derive(Clone, Debug)]
pub struct Plan<T> {
n: usize,
factors: Vec<Complex<T>>,
operation: Operation,
}
pub trait Transform<T> {
fn transform(&mut self, &Plan<T>);
}
impl<T> Plan<T>
where
T: Float + FloatConst,
{
pub fn new(operation: Operation, n: usize) -> Self {
assert!(n.is_power_of_two());
let one = T::one();
let two = one + one;
let mut factors = vec![];
let sign = if let Operation::Forward = operation {
-one
} else {
one
};
let mut step = 1;
while step < n {
let (multiplier, mut factor) = {
let theta = T::PI() / T::from(step).unwrap();
let sine = (theta / two).sin();
(
Complex::new(-two * sine * sine, sign * theta.sin()),
Complex::one(),
)
};
for _ in 0..step {
factors.push(factor);
factor = multiplier * factor + factor;
}
step <<= 1;
}
Plan {
n: n,
factors: factors,
operation: operation,
}
}
}
#[inline(always)]
pub fn transform<D: ?Sized, T>(data: &mut D, plan: &Plan<T>)
where
D: Transform<T>,
{
Transform::transform(data, plan);
}