embfft 0.2.1

Non-blocking FFT for embedded systems
Documentation
/* embfft | lib.rs
 * Copyright (c) 2025 L. Sartory
 * SPDX-License-Identifier: MIT
 */

/******************************************************************************/

#![no_std]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]

/******************************************************************************/

mod common;
mod cordic;
mod fft;
mod ifft;

pub use crate::fft::EmbFft;
pub use crate::ifft::EmbIfft;

/******************************************************************************/

#[cfg(test)]
mod tests {
    use approx::assert_ulps_eq;

    #[test]
    fn test_f32() {
        let mut data: [(f32, f32); 64] = [
            ( 1.0, 1.0), ( 2.0, 1.0), ( 3.0, 1.0), ( 4.0, 1.0), ( 5.0, 1.0), ( 6.0, 1.0), ( 7.0, 1.0), ( 8.0, 1.0),
            ( 9.0, 1.0), (10.0, 1.0), (11.0, 1.0), (12.0, 1.0), (13.0, 1.0), (14.0, 1.0), (15.0, 1.0), (16.0, 1.0),
            (17.0, 1.0), (18.0, 1.0), (19.0, 1.0), (20.0, 1.0), (21.0, 1.0), (22.0, 1.0), (23.0, 1.0), (24.0, 1.0),
            (25.0, 1.0), (26.0, 1.0), (27.0, 1.0), (28.0, 1.0), (29.0, 1.0), (30.0, 1.0), (31.0, 1.0), (32.0, 1.0),
            (33.0, 1.0), (34.0, 1.0), (35.0, 1.0), (36.0, 1.0), (37.0, 1.0), (38.0, 1.0), (39.0, 1.0), (40.0, 1.0),
            (41.0, 1.0), (42.0, 1.0), (43.0, 1.0), (44.0, 1.0), (45.0, 1.0), (46.0, 1.0), (47.0, 1.0), (48.0, 1.0),
            (49.0, 1.0), (50.0, 1.0), (51.0, 1.0), (52.0, 1.0), (53.0, 1.0), (54.0, 1.0), (55.0, 1.0), (56.0, 1.0),
            (57.0, 1.0), (58.0, 1.0), (59.0, 1.0), (60.0, 1.0), (61.0, 1.0), (62.0, 1.0), (63.0, 1.0), (64.0, 1.0)
        ];

        let expected_data = data.clone();

        crate::EmbFft::new(&mut data).fft();
        crate::EmbIfft::new(&mut data).ifft();

        for (x, y) in core::iter::zip(data, expected_data) {
            assert_ulps_eq!(x.0, y.0, max_ulps = 50);
            assert_ulps_eq!(x.1, y.1, max_ulps = 50);
        }
    }

    #[test]
    fn test_f64() {
        let mut data: [(f64, f64); 64] = [
            ( 1.0, 1.0), ( 2.0, 1.0), ( 3.0, 1.0), ( 4.0, 1.0), ( 5.0, 1.0), ( 6.0, 1.0), ( 7.0, 1.0), ( 8.0, 1.0),
            ( 9.0, 1.0), (10.0, 1.0), (11.0, 1.0), (12.0, 1.0), (13.0, 1.0), (14.0, 1.0), (15.0, 1.0), (16.0, 1.0),
            (17.0, 1.0), (18.0, 1.0), (19.0, 1.0), (20.0, 1.0), (21.0, 1.0), (22.0, 1.0), (23.0, 1.0), (24.0, 1.0),
            (25.0, 1.0), (26.0, 1.0), (27.0, 1.0), (28.0, 1.0), (29.0, 1.0), (30.0, 1.0), (31.0, 1.0), (32.0, 1.0),
            (33.0, 1.0), (34.0, 1.0), (35.0, 1.0), (36.0, 1.0), (37.0, 1.0), (38.0, 1.0), (39.0, 1.0), (40.0, 1.0),
            (41.0, 1.0), (42.0, 1.0), (43.0, 1.0), (44.0, 1.0), (45.0, 1.0), (46.0, 1.0), (47.0, 1.0), (48.0, 1.0),
            (49.0, 1.0), (50.0, 1.0), (51.0, 1.0), (52.0, 1.0), (53.0, 1.0), (54.0, 1.0), (55.0, 1.0), (56.0, 1.0),
            (57.0, 1.0), (58.0, 1.0), (59.0, 1.0), (60.0, 1.0), (61.0, 1.0), (62.0, 1.0), (63.0, 1.0), (64.0, 1.0)
        ];

        let expected_data = data.clone();

        crate::EmbFft::new(&mut data).fft();
        crate::EmbIfft::new(&mut data).ifft();

        for (x, y) in core::iter::zip(data, expected_data) {
            assert_ulps_eq!(x.0, y.0, max_ulps = 500);
            assert_ulps_eq!(x.1, y.1, max_ulps = 500);
        }
    }
}