microfft 0.1.0

Embedded-friendly Fast Fourier Transforms
Documentation
use crate::tables;
use num_complex::Complex32;

pub(crate) trait CFft {
    type Half: CFft;

    const N: usize;
    const LOG2_N: usize;

    const M: usize = Self::N / 2;

    const BITREV_TABLE: &'static [u16] = tables::BITREV[Self::LOG2_N];
    const TWIDDLE_TABLE: &'static [Complex32] = tables::TWIDDLE[Self::LOG2_N];

    #[inline]
    fn transform(x: &mut [Complex32]) -> &mut [Complex32] {
        debug_assert_eq!(x.len(), Self::N);

        Self::bit_reverse(x);
        Self::compute_butterflies(x);
        x
    }

    #[inline]
    fn bit_reverse(x: &mut [Complex32]) {
        debug_assert_eq!(x.len(), Self::N);

        for i in 0..Self::N {
            let j = Self::BITREV_TABLE[i] as usize;
            x.swap(i, j);
        }
    }

    #[inline]
    fn compute_butterflies(x: &mut [Complex32]) {
        debug_assert_eq!(x.len(), Self::N);

        let m = Self::M;
        Self::Half::compute_butterflies(&mut x[..m]);
        Self::Half::compute_butterflies(&mut x[m..]);

        for k in 0..m {
            let f = x[k];
            let s = x[k + m];
            let twiddle = Self::TWIDDLE_TABLE[k];
            let prod = twiddle * s;
            x[k] = f + prod;
            x[k + m] = f - prod;
        }
    }
}

pub(crate) struct CFftN1;

impl CFft for CFftN1 {
    type Half = Self;

    const N: usize = 1;
    const LOG2_N: usize = 0;

    #[inline]
    fn compute_butterflies(x: &mut [Complex32]) {
        debug_assert_eq!(x.len(), Self::N);
    }
}

macro_rules! cfft_impls {
    ( $( $I:expr => ($N:expr, $CFftN:ident, $Half:ident), )* ) => {
        $(
            pub(crate) struct $CFftN;

            impl CFft for $CFftN {
                type Half = $Half;

                const N: usize = $N;
                const LOG2_N: usize = $I;
            }
        )*
    };
}

cfft_impls! {
     1 => (2, CFftN2, CFftN1),
     2 => (4, CFftN4, CFftN2),
     3 => (8, CFftN8, CFftN4),
     4 => (16, CFftN16, CFftN8),
     5 => (32, CFftN32, CFftN16),
     6 => (64, CFftN64, CFftN32),
     7 => (128, CFftN128, CFftN64),
     8 => (256, CFftN256, CFftN128),
     9 => (512, CFftN512, CFftN256),
    10 => (1024, CFftN1024, CFftN512),
}