#![feature(test)]
extern crate test;
use rustfft::{self, FFTnum, IsInverse, Length};
use std::sync::Arc;
use test::Bencher;
use rustfft::FFT;
use rustfft::num_complex::Complex;
use rustfft::algorithm::*;
use rustfft::algorithm::butterflies::*;
struct Noop {
len: usize,
inverse: bool,
}
impl<T: FFTnum> FFT<T> for Noop {
fn process(&self, _input: &mut [Complex<T>], _output: &mut [Complex<T>]) {}
fn process_multi(&self, _input: &mut [Complex<T>], _output: &mut [Complex<T>]) {}
}
impl<T: FFTnum> FFTButterfly<T> for Noop {
unsafe fn process_inplace(&self, _input: &mut [Complex<T>]) {}
unsafe fn process_multi_inplace(&self, _input: &mut [Complex<T>]) {}
}
impl Length for Noop {
fn len(&self) -> usize { self.len }
}
impl IsInverse for Noop {
fn is_inverse(&self) -> bool { self.inverse }
}
fn bench_fft(b: &mut Bencher, len: usize) {
let mut planner = rustfft::FFTplanner::new(false);
let fft = planner.plan_fft(len);
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; len];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn complex_p2_00000064(b: &mut Bencher) { bench_fft(b, 64); }
#[bench] fn complex_p2_00000256(b: &mut Bencher) { bench_fft(b, 256); }
#[bench] fn complex_p2_00001024(b: &mut Bencher) { bench_fft(b, 1024); }
#[bench] fn complex_p2_00004096(b: &mut Bencher) { bench_fft(b, 4096); }
#[bench] fn complex_p2_00016384(b: &mut Bencher) { bench_fft(b, 16384); }
#[bench] fn complex_p2_00065536(b: &mut Bencher) { bench_fft(b, 65536); }
#[bench] fn complex_p2_01048576(b: &mut Bencher) { bench_fft(b, 1048576); }
#[bench] fn complex_p2_16777216(b: &mut Bencher) { bench_fft(b, 16777216); }
#[bench] fn complex_p7_00343(b: &mut Bencher) { bench_fft(b, 343); }
#[bench] fn complex_p7_02401(b: &mut Bencher) { bench_fft(b, 2401); }
#[bench] fn complex_p7_16807(b: &mut Bencher) { bench_fft(b, 16807); }
#[bench] fn complex_prime_00003(b: &mut Bencher) { bench_fft(b, 3); }
#[bench] fn complex_prime_00005(b: &mut Bencher) { bench_fft(b, 5); }
#[bench] fn complex_prime_00007(b: &mut Bencher) { bench_fft(b, 7); }
#[bench] fn complex_prime_00011(b: &mut Bencher) { bench_fft(b, 11); }
#[bench] fn complex_prime_00013(b: &mut Bencher) { bench_fft(b, 13); }
#[bench] fn complex_prime_00017(b: &mut Bencher) { bench_fft(b, 17); }
#[bench] fn complex_prime_00019(b: &mut Bencher) { bench_fft(b, 19); }
#[bench] fn complex_prime_00023(b: &mut Bencher) { bench_fft(b, 23); }
#[bench] fn complex_prime_00029(b: &mut Bencher) { bench_fft(b, 29); }
#[bench] fn complex_prime_00031(b: &mut Bencher) { bench_fft(b, 31); }
#[bench] fn complex_prime_00151(b: &mut Bencher) { bench_fft(b, 151); }
#[bench] fn complex_prime_00257(b: &mut Bencher) { bench_fft(b, 257); }
#[bench] fn complex_prime_01009(b: &mut Bencher) { bench_fft(b, 1009); }
#[bench] fn complex_prime_02017(b: &mut Bencher) { bench_fft(b, 2017); }
#[bench] fn complex_prime_65537(b: &mut Bencher) { bench_fft(b, 65537); }
#[bench] fn complex_prime_746497(b: &mut Bencher) { bench_fft(b, 746497); }
#[bench] fn complex_primepower_44521(b: &mut Bencher) { bench_fft(b, 44521); } #[bench] fn complex_primepower_160801(b: &mut Bencher) { bench_fft(b, 160801); }
#[bench] fn complex_composite_24576(b: &mut Bencher) { bench_fft(b, 24576); }
#[bench] fn complex_composite_20736(b: &mut Bencher) { bench_fft(b, 20736); }
#[bench] fn complex_composite_32192(b: &mut Bencher) { bench_fft(b, 32192); }
#[bench] fn complex_composite_24028(b: &mut Bencher) { bench_fft(b, 24028); }
#[bench] fn complex_composite_30270(b: &mut Bencher) { bench_fft(b, 30270); }
fn bench_good_thomas(b: &mut Bencher, width: usize, height: usize) {
let mut planner = rustfft::FFTplanner::new(false);
let width_fft = planner.plan_fft(width);
let height_fft = planner.plan_fft(height);
let fft : Arc<dyn FFT<_>> = Arc::new(GoodThomasAlgorithm::new(width_fft, height_fft));
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; width * height];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn good_thomas_0002_3(b: &mut Bencher) { bench_good_thomas(b, 2, 3); }
#[bench] fn good_thomas_0003_4(b: &mut Bencher) { bench_good_thomas(b, 3, 4); }
#[bench] fn good_thomas_0004_5(b: &mut Bencher) { bench_good_thomas(b, 4, 5); }
#[bench] fn good_thomas_0007_32(b: &mut Bencher) { bench_good_thomas(b, 7, 32); }
#[bench] fn good_thomas_0032_27(b: &mut Bencher) { bench_good_thomas(b, 32, 27); }
#[bench] fn good_thomas_0256_243(b: &mut Bencher) { bench_good_thomas(b, 256, 243); }
#[bench] fn good_thomas_2048_3(b: &mut Bencher) { bench_good_thomas(b, 2048, 3); }
#[bench] fn good_thomas_2048_2187(b: &mut Bencher) { bench_good_thomas(b, 2048, 2187); }
fn bench_mixed_radix(b: &mut Bencher, width: usize, height: usize) {
let mut planner = rustfft::FFTplanner::new(false);
let width_fft = planner.plan_fft(width);
let height_fft = planner.plan_fft(height);
let fft : Arc<dyn FFT<_>> = Arc::new(MixedRadix::new(width_fft, height_fft));
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; width * height];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn mixed_radix_0002_3(b: &mut Bencher) { bench_mixed_radix(b, 2, 3); }
#[bench] fn mixed_radix_0003_4(b: &mut Bencher) { bench_mixed_radix(b, 3, 4); }
#[bench] fn mixed_radix_0004_5(b: &mut Bencher) { bench_mixed_radix(b, 4, 5); }
#[bench] fn mixed_radix_0007_32(b: &mut Bencher) { bench_mixed_radix(b, 7, 32); }
#[bench] fn mixed_radix_0032_27(b: &mut Bencher) { bench_mixed_radix(b, 32, 27); }
#[bench] fn mixed_radix_0256_243(b: &mut Bencher) { bench_mixed_radix(b, 256, 243); }
#[bench] fn mixed_radix_2048_3(b: &mut Bencher) { bench_mixed_radix(b, 2048, 3); }
#[bench] fn mixed_radix_2048_2187(b: &mut Bencher) { bench_mixed_radix(b, 2048, 2187); }
fn plan_butterfly(len: usize) -> Arc<dyn FFTButterfly<f32>> {
match len {
2 => Arc::new(Butterfly2::new(false)),
3 => Arc::new(Butterfly3::new(false)),
4 => Arc::new(Butterfly4::new(false)),
5 => Arc::new(Butterfly5::new(false)),
6 => Arc::new(Butterfly6::new(false)),
7 => Arc::new(Butterfly7::new(false)),
8 => Arc::new(Butterfly8::new(false)),
16 => Arc::new(Butterfly16::new(false)),
32 => Arc::new(Butterfly32::new(false)),
_ => panic!("Invalid butterfly size: {}", len),
}
}
fn bench_mixed_radix_butterfly(b: &mut Bencher, width: usize, height: usize) {
let width_fft = plan_butterfly(width);
let height_fft = plan_butterfly(height);
let fft : Arc<dyn FFT<_>> = Arc::new(MixedRadixDoubleButterfly::new(width_fft, height_fft));
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; width * height];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn mixed_radix_butterfly_0002_3(b: &mut Bencher) { bench_mixed_radix_butterfly(b, 2, 3); }
#[bench] fn mixed_radix_butterfly_0003_4(b: &mut Bencher) { bench_mixed_radix_butterfly(b, 3, 4); }
#[bench] fn mixed_radix_butterfly_0004_5(b: &mut Bencher) { bench_mixed_radix_butterfly(b, 4, 5); }
#[bench] fn mixed_radix_butterfly_0007_32(b: &mut Bencher) { bench_mixed_radix_butterfly(b, 7, 32); }
fn bench_good_thomas_butterfly(b: &mut Bencher, width: usize, height: usize) {
let width_fft = plan_butterfly(width);
let height_fft = plan_butterfly(height);
let fft : Arc<dyn FFT<_>> = Arc::new(GoodThomasAlgorithmDoubleButterfly::new(width_fft, height_fft));
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; width * height];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn good_thomas_butterfly_0002_3(b: &mut Bencher) { bench_good_thomas_butterfly(b, 2, 3); }
#[bench] fn good_thomas_butterfly_0003_4(b: &mut Bencher) { bench_good_thomas_butterfly(b, 3, 4); }
#[bench] fn good_thomas_butterfly_0004_5(b: &mut Bencher) { bench_good_thomas_butterfly(b, 4, 5); }
#[bench] fn good_thomas_butterfly_0007_32(b: &mut Bencher) { bench_good_thomas_butterfly(b, 7, 32); }
fn bench_raders(b: &mut Bencher, len: usize) {
let mut planner = rustfft::FFTplanner::new(false);
let inner_fft = planner.plan_fft(len - 1);
let fft : Arc<dyn FFT<_>> = Arc::new(RadersAlgorithm::new(len, inner_fft));
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; len];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn raders_0005(b: &mut Bencher) { bench_raders(b, 5); }
#[bench] fn raders_0017(b: &mut Bencher) { bench_raders(b, 17); }
#[bench] fn raders_0151(b: &mut Bencher) { bench_raders(b, 151); }
#[bench] fn raders_0257(b: &mut Bencher) { bench_raders(b, 257); }
#[bench] fn raders_1009(b: &mut Bencher) { bench_raders(b, 1009); }
#[bench] fn raders_2017(b: &mut Bencher) { bench_raders(b, 2017); }
#[bench] fn raders_65537(b: &mut Bencher) { bench_raders(b, 65537); }
#[bench] fn raders_746497(b: &mut Bencher) { bench_raders(b,746497); }
fn bench_raders_setup(b: &mut Bencher, len: usize) {
let mut planner = rustfft::FFTplanner::new(false);
let inner_fft = planner.plan_fft(len - 1);
b.iter(|| {
let fft : Arc<dyn FFT<f32>> = Arc::new(RadersAlgorithm::new(len, Arc::clone(&inner_fft)));
test::black_box(fft);
});
}
#[bench] fn raders_setup_0005(b: &mut Bencher) { bench_raders_setup(b, 5); }
#[bench] fn raders_setup_0017(b: &mut Bencher) { bench_raders_setup(b, 17); }
#[bench] fn raders_setup_0151(b: &mut Bencher) { bench_raders_setup(b, 151); }
#[bench] fn raders_setup_0257(b: &mut Bencher) { bench_raders_setup(b, 257); }
#[bench] fn raders_setup_1009(b: &mut Bencher) { bench_raders_setup(b, 1009); }
#[bench] fn raders_setup_2017(b: &mut Bencher) { bench_raders_setup(b, 2017); }
#[bench] fn raders_setup_65537(b: &mut Bencher) { bench_raders_setup(b, 65537); }
#[bench] fn raders_setup_746497(b: &mut Bencher) { bench_raders_setup(b,746497); }
fn bench_good_thomas_noop(b: &mut Bencher, width: usize, height: usize) {
let width_fft = Arc::new(Noop { len: width, inverse: false });
let height_fft = Arc::new(Noop { len: height, inverse: false });
let fft : Arc<dyn FFT<_>> = Arc::new(GoodThomasAlgorithm::new(width_fft, height_fft));
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; width * height];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn noop_good_thomas_1000_1001(b: &mut Bencher) { bench_good_thomas_noop(b,1000, 1001); }
#[bench] fn noop_good_thomas_0100_0101(b: &mut Bencher) { bench_good_thomas_noop(b,100, 101); }
#[bench] fn noop_good_thomas_0010_0011(b: &mut Bencher) { bench_good_thomas_noop(b,10, 11); }
#[bench] fn noop_good_thomas_0003_1024(b: &mut Bencher) { bench_good_thomas_noop(b,3, 1024); }
fn bench_mixed_radix_noop(b: &mut Bencher, width: usize, height: usize) {
let width_fft = Arc::new(Noop { len: width, inverse: false });
let height_fft = Arc::new(Noop { len: height, inverse: false });
let fft : Arc<dyn FFT<_>> = Arc::new(MixedRadix::new(width_fft, height_fft));
let mut signal = vec![Complex{re: 0_f32, im: 0_f32}; width * height];
let mut spectrum = signal.clone();
b.iter(|| {fft.process(&mut signal, &mut spectrum);} );
}
#[bench] fn noop_mixed_radix_1000_1001(b: &mut Bencher) { bench_mixed_radix_noop(b,1000, 1001); }
#[bench] fn noop_mixed_radix_0100_0101(b: &mut Bencher) { bench_mixed_radix_noop(b,100, 101); }
#[bench] fn noop_mixed_radix_0010_0011(b: &mut Bencher) { bench_mixed_radix_noop(b,10, 11); }
#[bench] fn noop_mixed_radix_0003_1024(b: &mut Bencher) { bench_mixed_radix_noop(b,3, 1024); }