1use avila_fft::{Complex, FftPlanner, fft};
5use std::time::Instant;
6
7fn benchmark_recursive(size: usize, iterations: usize) -> f64 {
8 let input: Vec<Complex<f64>> = (0..size)
9 .map(|i| Complex::new((i as f64).sin(), (i as f64).cos()))
10 .collect();
11
12 let start = Instant::now();
13 for _ in 0..iterations {
14 let _ = fft(&input);
15 }
16 let duration = start.elapsed();
17 duration.as_secs_f64() / (iterations as f64)
18}
19
20fn benchmark_iterative(size: usize, iterations: usize) -> f64 {
21 let input: Vec<Complex<f64>> = (0..size)
22 .map(|i| Complex::new((i as f64).sin(), (i as f64).cos()))
23 .collect();
24
25 let planner = FftPlanner::new(size, false).unwrap();
26
27 let start = Instant::now();
28 for _ in 0..iterations {
29 let _ = planner.process(&input).unwrap();
30 }
31 let duration = start.elapsed();
32 duration.as_secs_f64() / (iterations as f64)
33}
34
35fn main() {
36 println!("=== Benchmark FFT - Avila FFT ===");
37 println!("Compile com --release para resultados precisos!\n");
38
39 let sizes = vec![64, 128, 256, 512, 1024, 2048, 4096];
40
41 println!("{:>6} | {:>12} | {:>12} | {:>10} | {:>12}",
42 "N", "Recursiva", "Iterativa", "Speedup", "Throughput");
43 println!("{}", "-".repeat(70));
44
45 for &size in &sizes {
46 let iterations = (100000 / size).max(10);
48
49 let time_recursive = benchmark_recursive(size, iterations);
50 let time_iterative = benchmark_iterative(size, iterations);
51 let speedup = time_recursive / time_iterative;
52 let throughput = (size as f64) / time_iterative / 1e6; println!("{:6} | {:9.2} µs | {:9.2} µs | {:8.2}x | {:8.1} Ms/s",
55 size,
56 time_recursive * 1e6,
57 time_iterative * 1e6,
58 speedup,
59 throughput
60 );
61 }
62
63 println!("\n=== Análise de Complexidade ===\n");
64
65 println!("Verificando complexidade O(N log N):");
67 let base_size = 256;
68 let base_time = benchmark_iterative(base_size, 1000);
69
70 for &size in &[512, 1024, 2048] {
71 let time = benchmark_iterative(size, 1000);
72 let ratio = size / base_size;
73 let expected_ratio = (ratio as f64) * (size as f64).log2() / (base_size as f64).log2();
74 let actual_ratio = time / base_time;
75
76 println!(" N={:4}: esperado {:.2}x, observado {:.2}x",
77 size, expected_ratio, actual_ratio);
78 }
79
80 println!("\n=== Teste de Precisão ===\n");
81
82 let test_size = 1024;
84 let input: Vec<Complex<f64>> = (0..test_size)
85 .map(|i| Complex::new((i as f64) * 0.1, (i as f64) * 0.05))
86 .collect();
87
88 let result_recursive = fft(&input);
89
90 let planner = FftPlanner::new(test_size, false).unwrap();
91 let result_iterative = planner.process(&input).unwrap();
92
93 let max_error = result_recursive.iter()
94 .zip(result_iterative.iter())
95 .map(|(a, b)| (a.re - b.re).abs().max((a.im - b.im).abs()))
96 .fold(0.0, f64::max);
97
98 println!("Erro máximo entre recursiva e iterativa: {:.2e}", max_error);
99
100 if max_error < 1e-10 {
101 println!("✓ Precisão idêntica!");
102 } else {
103 println!("⚠ Diferença detectada (ainda aceitável)");
104 }
105
106 println!("\n=== Uso de Memória ===\n");
107
108 println!("Recursiva:");
109 println!(" - Cria O(N log N) vetores temporários");
110 println!(" - Stack frames: O(log N)");
111 println!(" - Não recomendada para N grande\n");
112
113 println!("Iterativa:");
114 println!(" - Trabalha in-place após bit-reversal");
115 println!(" - Cache de twiddle factors: O(N/2)");
116 println!(" - Recomendada para produção");
117}