ruFFT-host 0.1.39

ruFFT CPU real transforms, twiddle tables and SIMD butterflies.
Documentation
use ruda_core::tensor::{data::TensorData, host::HostTensor};
use rufft_host::{irfft_f32, irfft_f64, rfft_f32, rfft_f64};
use std::{
    hint::black_box,
    time::{Duration, Instant},
};

fn measure(mut run: impl FnMut()) -> f64 {
    for _ in 0..4 {
        run();
    }
    let mut samples = Vec::new();
    for _ in 0..5 {
        let start = Instant::now();
        let mut count = 0;
        while start.elapsed() < Duration::from_millis(50) {
            run();
            count += 1;
        }
        samples.push(start.elapsed().as_secs_f64() * 1e6 / count as f64);
    }
    samples.sort_by(f64::total_cmp);
    samples[2]
}

#[test]
#[ignore = "bounded CPU timing comparison; run with --ignored --nocapture"]
fn transform_timings() {
    for n in [64, 1024, 16384] {
        for batch in [1, 64] {
            let data: Vec<f64> = (0..n * batch).map(|i| (i as f64 * 0.13).sin()).collect();
            let f64_input = HostTensor::from_data(TensorData::new(data.clone(), [batch, n]));
            let f32_input = HostTensor::from_data(TensorData::new(
                data.iter().map(|&v| v as f32).collect::<Vec<_>>(),
                [batch, n],
            ));
            let (re32, im32) = rfft_f32(f32_input.clone(), 1, None);
            let (re64, im64) = rfft_f64(f64_input.clone(), 1, None);
            let timings = [
                (
                    "rfft_f32",
                    measure(|| {
                        black_box(rfft_f32(f32_input.clone(), 1, None));
                    }),
                ),
                (
                    "irfft_f32",
                    measure(|| {
                        black_box(irfft_f32(re32.clone(), im32.clone(), 1, None));
                    }),
                ),
                (
                    "rfft_f64",
                    measure(|| {
                        black_box(rfft_f64(f64_input.clone(), 1, None));
                    }),
                ),
                (
                    "irfft_f64",
                    measure(|| {
                        black_box(irfft_f64(re64.clone(), im64.clone(), 1, None));
                    }),
                ),
            ];
            for (operation, us) in timings {
                println!("FFT_TIMING,{operation},{n},{batch},{us:.3}");
            }
        }
    }
}