diff --git a/Cargo.lock b/Cargo.lock index 21bee31..2dbcc51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -286,7 +286,7 @@ dependencies = [ [[package]] name = "ndrustfft" -version = "0.2.2" +version = "0.3.0" dependencies = [ "criterion", "ndarray", diff --git a/Cargo.toml b/Cargo.toml index 13344a7..0420fd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ndrustfft" -version = "0.2.2" +version = "0.3.0" authors = ["preiter "] edition = "2018" description = "N-dimensional FFT, real-to-complex FFT and real-to-real DCT" @@ -14,11 +14,11 @@ name = "ndrustfft" path = "src/lib.rs" [dependencies] -ndarray = { version = "0.15.0", features = ["rayon"] } +ndarray = { version = "0.15", features = ["rayon"] } rustfft = "6.0" -num-traits = "0.2.12" -rustdct = "0.6" -realfft = "2.0.1" +num-traits = "0.2" +rustdct = "0.7" +realfft = "3.0" [dev-dependencies] criterion = { version = "0.3.4", features = ["html_reports"] } diff --git a/README.md b/README.md index c041d8b..cbc4456 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,17 @@ that enables performing FFTs and DCTs of complex- and real-valued data on *n*-dimensional arrays (ndarray). ndrustfft provides Handler structs for FFT's and DCTs, which must be provided alongside -with the arrays to the respective function (see below) . +with the arrays to the respective functions (see below) . The Handlers implement a process function, which is a wrapper around Rustfft's -process function with additional functionality. +process. Transforms along the outermost axis are in general the fastest, while transforms along -other axis' will create temporary copies of the input array. +other axis' will temporarily create copies of the input array. -### Implemented transforms +### Parallel +The library ships all functions with a parallel version +which leverages the parallel iterators of the ndarray crate. + +### Available transforms #### Complex-to-complex - `fft` : [`ndfft`], [`ndfft_par`] - `ifft`: [`ndifft`],[`ndifft_par`] @@ -27,19 +31,6 @@ other axis' will create temporary copies of the input array. - `dct3`: [`nddct3`],[`nddct3_par`] - `dct4`: [`nddct4`],[`nddct4_par`] -`ndrustfft` >= v0.2.2: - -Real-to-complex transforms now behave like numpys rfft. -The first element (for odd and even input) and the last element (for even input) -of the coefficient array should be real due to Hermitian symmetry. -Thus, the solution of the inverse transform is independent of the imaginary -part of the first and last element (for even input). Note, this is different -to the behaviour of the `RealFft` crate. - -### Parallel -The library ships all functions with a parallel version -which leverages the parallel abilities of ndarray. - ### Example 2-Dimensional real-to-complex fft along first axis ```rust @@ -61,4 +52,12 @@ ndfft_r2c( ); ``` +## Versions +- v0.3.0: Upgrade `RealFft` to 3.0.0 and `RustDCT` to 0.7 +- \>= v0.2.2: + +The first and last elements of real-to-complex transforms are +per definition purely real. This is now enforced actively, by +setting the complex part to zero - similar to numpys rfft. + License: MIT diff --git a/benches/ndrustfft.rs b/benches/ndrustfft.rs index 6ca45be..e08b7bd 100644 --- a/benches/ndrustfft.rs +++ b/benches/ndrustfft.rs @@ -3,11 +3,12 @@ use ndarray::{Array, Dim, Ix}; use ndrustfft::{nddct1, DctHandler}; use ndrustfft::{ndfft, Complex, FftHandler}; use ndrustfft::{ndfft_r2c, R2cFftHandler}; -const SIZES: [usize; 4] = [128, 264, 512, 1024]; +const FFT_SIZES: [usize; 4] = [128, 264, 512, 1024]; +const DCT_SIZES: [usize; 4] = [129, 265, 513, 1025]; pub fn bench_fft2d(c: &mut Criterion) { let mut group = c.benchmark_group("fft2d"); - for n in SIZES.iter() { + for n in FFT_SIZES.iter() { let name = format!("Size: {}", *n); let mut data = Array::, Dim<[Ix; 2]>>::zeros((*n, *n)); let mut vhat = Array::, Dim<[Ix; 2]>>::zeros((*n, *n)); @@ -25,7 +26,7 @@ pub fn bench_fft2d(c: &mut Criterion) { pub fn bench_rfft2d(c: &mut Criterion) { let mut group = c.benchmark_group("rfft2d"); - for n in SIZES.iter() { + for n in FFT_SIZES.iter() { let name = format!("Size: {}", *n); let m = *n / 2 + 1; let mut data = Array::>::zeros((*n, *n)); @@ -43,7 +44,7 @@ pub fn bench_rfft2d(c: &mut Criterion) { pub fn bench_dct2d(c: &mut Criterion) { let mut group = c.benchmark_group("dct2d"); - for n in SIZES.iter() { + for n in DCT_SIZES.iter() { let name = format!("Size: {}", *n); let mut data = Array::>::zeros((*n, *n)); let mut vhat = Array::>::zeros((*n, *n)); diff --git a/benches/ndrustfft_par.rs b/benches/ndrustfft_par.rs index 283ed19..e11b4b7 100644 --- a/benches/ndrustfft_par.rs +++ b/benches/ndrustfft_par.rs @@ -3,12 +3,12 @@ use ndarray::{Array, Dim, Ix}; use ndrustfft::{nddct1_par, DctHandler}; use ndrustfft::{ndfft_par, Complex, FftHandler}; use ndrustfft::{ndfft_r2c_par, R2cFftHandler}; - -const SIZES: [usize; 4] = [128, 264, 512, 1024]; +const FFT_SIZES: [usize; 4] = [128, 264, 512, 1024]; +const DCT_SIZES: [usize; 4] = [129, 265, 513, 1025]; pub fn bench_fft2d(c: &mut Criterion) { let mut group = c.benchmark_group("fft2d_par"); - for n in SIZES.iter() { + for n in FFT_SIZES.iter() { let name = format!("Size: {}", *n); let mut data = Array::, Dim<[Ix; 2]>>::zeros((*n, *n)); let mut vhat = Array::, Dim<[Ix; 2]>>::zeros((*n, *n)); @@ -26,7 +26,7 @@ pub fn bench_fft2d(c: &mut Criterion) { pub fn bench_rfft2d(c: &mut Criterion) { let mut group = c.benchmark_group("rfft2d_par"); - for n in SIZES.iter() { + for n in FFT_SIZES.iter() { let name = format!("Size: {}", *n); let m = *n / 2 + 1; let mut data = Array::>::zeros((*n, *n)); @@ -44,7 +44,7 @@ pub fn bench_rfft2d(c: &mut Criterion) { pub fn bench_dct2d(c: &mut Criterion) { let mut group = c.benchmark_group("dct2d_par"); - for n in SIZES.iter() { + for n in DCT_SIZES.iter() { let name = format!("Size: {}", *n); let mut data = Array::>::zeros((*n, *n)); let mut vhat = Array::>::zeros((*n, *n)); diff --git a/src/lib.rs b/src/lib.rs index b0314ac..1f91c2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,13 +5,17 @@ //! data on *n*-dimensional arrays (ndarray). //! //! ndrustfft provides Handler structs for FFT's and DCTs, which must be provided alongside -//! with the arrays to the respective function (see below) . +//! with the arrays to the respective functions (see below) . //! The Handlers implement a process function, which is a wrapper around Rustfft's -//! process function with additional functionality. +//! process. //! Transforms along the outermost axis are in general the fastest, while transforms along -//! other axis' will create temporary copies of the input array. +//! other axis' will temporarily create copies of the input array. //! -//! ## Implemented transforms +//! ## Parallel +//! The library ships all functions with a parallel version +//! which leverages the parallel iterators of the ndarray crate. +//! +//! ## Available transforms //! ### Complex-to-complex //! - `fft` : [`ndfft`], [`ndfft_par`] //! - `ifft`: [`ndifft`],[`ndifft_par`] @@ -25,19 +29,6 @@ //! - `dct3`: [`nddct3`],[`nddct3_par`] //! - `dct4`: [`nddct4`],[`nddct4_par`] //! -//! `ndrustfft` >= v0.2.2: -//! -//! Real-to-complex transforms now behave like numpys rfft. -//! The first element (for odd and even input) and the last element (for even input) -//! of the coefficient array should be real due to Hermitian symmetry. -//! Thus, the solution of the inverse transform is independent of the imaginary -//! part of the first and last element (for even input). Note, this is different -//! to the behaviour of the `RealFft` crate. -//! -//! ## Parallel -//! The library ships all functions with a parallel version -//! which leverages the parallel abilities of ndarray. -//! //! ## Example //! 2-Dimensional real-to-complex fft along first axis //! ``` @@ -58,8 +49,16 @@ //! 0, //! ); //! ``` +//! +//! # Versions +//! - v0.3.0: Upgrade `RealFft` to 3.0.0 and `RustDCT` to 0.7 +//! - \>= v0.2.2: +//! +//! The first and last elements of real-to-complex transforms are +//! per definition purely real. This is now enforced actively, by +//! setting the complex part to zero - similar to numpys rfft. #![warn(missing_docs)] -#![warn(missing_doc_code_examples)] +#![warn(rustdoc::missing_doc_code_examples)] extern crate ndarray; extern crate rustfft; use ndarray::{Array1, ArrayBase, Dimension, Zip}; @@ -117,7 +116,7 @@ macro_rules! create_transform { }; } -/// Similar to create_transform, but supports parallel computation. +/// Similar to ``create_transform``, but supports parallel computation. macro_rules! create_transform_par { ($(#[$meta:meta])* $i: ident, $a: ty, $b: ty, $h: ty, $p: ident) => { $(#[$meta])* @@ -189,10 +188,8 @@ macro_rules! create_transform_par { #[derive(Clone)] pub struct FftHandler { n: usize, - m: usize, plan_fwd: Arc>, plan_bwd: Arc>, - buffer: Vec>, } impl FftHandler { @@ -216,13 +213,10 @@ impl FftHandler { let mut planner = FftPlanner::::new(); let fwd = planner.plan_fft_forward(n); let bwd = planner.plan_fft_inverse(n); - let buffer = vec![Complex::zero(); n]; FftHandler:: { n, - m: n / 2 + 1, plan_fwd: Arc::clone(&fwd), plan_bwd: Arc::clone(&bwd), - buffer, } }