Skip to content

Commit

Permalink
-> v0.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Reiter committed Feb 16, 2022
1 parent bffb1fb commit c8fbd6e
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 56 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ndrustfft"
version = "0.2.2"
version = "0.3.0"
authors = ["preiter <[email protected]>"]
edition = "2018"
description = "N-dimensional FFT, real-to-complex FFT and real-to-real DCT"
Expand All @@ -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"] }
Expand Down
33 changes: 16 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`]
Expand All @@ -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
Expand All @@ -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
9 changes: 5 additions & 4 deletions benches/ndrustfft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Complex<f64>, Dim<[Ix; 2]>>::zeros((*n, *n));
let mut vhat = Array::<Complex<f64>, Dim<[Ix; 2]>>::zeros((*n, *n));
Expand All @@ -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::<f64, Dim<[Ix; 2]>>::zeros((*n, *n));
Expand All @@ -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::<f64, Dim<[Ix; 2]>>::zeros((*n, *n));
let mut vhat = Array::<f64, Dim<[Ix; 2]>>::zeros((*n, *n));
Expand Down
10 changes: 5 additions & 5 deletions benches/ndrustfft_par.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Complex<f64>, Dim<[Ix; 2]>>::zeros((*n, *n));
let mut vhat = Array::<Complex<f64>, Dim<[Ix; 2]>>::zeros((*n, *n));
Expand All @@ -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::<f64, Dim<[Ix; 2]>>::zeros((*n, *n));
Expand All @@ -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::<f64, Dim<[Ix; 2]>>::zeros((*n, *n));
let mut vhat = Array::<f64, Dim<[Ix; 2]>>::zeros((*n, *n));
Expand Down
42 changes: 18 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`]
Expand All @@ -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
//! ```
Expand All @@ -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};
Expand Down Expand Up @@ -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])*
Expand Down Expand Up @@ -189,10 +188,8 @@ macro_rules! create_transform_par {
#[derive(Clone)]
pub struct FftHandler<T> {
n: usize,
m: usize,
plan_fwd: Arc<dyn Fft<T>>,
plan_bwd: Arc<dyn Fft<T>>,
buffer: Vec<Complex<T>>,
}

impl<T: FftNum> FftHandler<T> {
Expand All @@ -216,13 +213,10 @@ impl<T: FftNum> FftHandler<T> {
let mut planner = FftPlanner::<T>::new();
let fwd = planner.plan_fft_forward(n);
let bwd = planner.plan_fft_inverse(n);
let buffer = vec![Complex::zero(); n];
FftHandler::<T> {
n,
m: n / 2 + 1,
plan_fwd: Arc::clone(&fwd),
plan_bwd: Arc::clone(&bwd),
buffer,
}
}

Expand Down

0 comments on commit c8fbd6e

Please sign in to comment.