use std::time::Instant;
use gpu_fft::{psd, utils};
fn main() {
let sample_rate = 200.0f32; let frequency = 15.0f32; let duration = 5.0f32; let threshold = 100.0f32;
let input = utils::generate_sine_wave(frequency, sample_rate, duration);
let n_orig = input.len();
println!("Input");
println!(" samples : {n_orig} (zero-padded to {} for FFT)", n_orig.next_power_of_two());
println!(" sample rate: {sample_rate} Hz");
println!(" frequency : {frequency} Hz");
println!(" first 5 : {:.4?}", &input[..5]);
println!();
let t = Instant::now();
let (real, imag) = gpu_fft::fft(&input);
println!("FFT completed in {:?}", t.elapsed());
let n = real.len();
let n_unique = n / 2 + 1;
let spectrum = psd::psd(&real, &imag);
let frequencies = utils::calculate_one_sided_frequencies(n, sample_rate);
let dominant = utils::find_dominant_frequencies(&spectrum[..n_unique], &frequencies, threshold);
println!("Dominant frequencies (0 … {:.0} Hz):", sample_rate / 2.0);
if dominant.is_empty() {
println!(" (none above threshold {threshold})");
} else {
for (freq, power) in &dominant {
println!(" {:>8.2} Hz power {:>10.2}", freq, power);
}
}
println!();
let t = Instant::now();
let output = gpu_fft::ifft(&real, &imag);
println!("IFFT completed in {:?}", t.elapsed());
let reconstructed = &output[..n_orig];
let max_err = input.iter().zip(reconstructed).map(|(a, b)| (a - b).abs()).fold(0.0f32, f32::max);
let acceptable = 5.0 * (n as f32).log2() * f32::EPSILON;
let verdict = if max_err <= acceptable { "✓" } else { "✗ unexpectedly large" };
println!(
"Round-trip max error : {max_err:.2e} (limit 5·log₂N·ε = {acceptable:.2e}) {verdict}"
);
}