Skip to content

Commit

Permalink
feat: implement hybrid Stockham+Cooley-Tukey FFT
Browse files Browse the repository at this point in the history
  • Loading branch information
sarah el kazdadi committed Sep 7, 2022
0 parents commit d110fa0
Show file tree
Hide file tree
Showing 22 changed files with 8,065 additions and 0 deletions.
61 changes: 61 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Test

on:
push:

env:
CARGO_TERM_COLOR: always

jobs:
cargo-benches:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install FFTW
run: sudo apt install -y libfftw3-dev
- name: Compile benches
run: cargo bench --no-run

cargo-tests:
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Test debug
run: cargo test
- name: Test debug serialization
run: cargo test --features=serde
- name: Test debug no-std
run: cargo test --no-default-features

cargo-tests-nightly:
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
- name: Test debug nightly
run: cargo test --features=nightly
46 changes: 46 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Check formatting using rustfmt
# and lint with clippy
name: Rustfmt and Clippy check

on:
push:

jobs:
rustfmt:
name: rustfmt
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
components: rustfmt
override: true

- name: Run cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check

clippy:
name: clippy
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
components: clippy
override: true

- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-targets --features=serde -- --no-deps -D warnings
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/Cargo.lock
38 changes: 38 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "concrete-fft"
version = "0.1.0"
edition = "2021"
authors = ["sarah el kazdadi <[email protected]>"]
description = "Concrete-FFT is a pure Rust high performance fast Fourier transform library."
readme = "README.md"
repository = "https://github.com/zama-ai/concrete-fft"
license = "BSD-3-Clause-Clear"
homepage = "https://zama.ai/"
keywords = ["fft"]

[dependencies]
num-complex = "0.4"
dyn-stack = { version = "0.8", default-features = false }
aligned-vec = { version = "0.5", default-features = false }
serde = { version = "1.0", optional = true, default-features = false }

[features]
default = ["std"]
nightly = []
std = []
serde = ["dep:serde", "num-complex/serde"]

[dev-dependencies]
criterion = "0.3"
rustfft = "6.0"
fftw-sys = { version = "0.6", default-features = false, features = ["system"] }
rand = "0.8"
bincode = "1.3"

[[bench]]
name = "fft"
harness = false

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--html-in-header", "katex-header.html", "--cfg", "docsrs"]
33 changes: 33 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
BSD 3-Clause Clear License

Copyright © 2022 ZAMA.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

3. Neither the name of ZAMA nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.

NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE*.
THIS SOFTWARE IS PROVIDED BY THE ZAMA AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
ZAMA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*In addition to the rights carried by this license, ZAMA grants to the user a non-exclusive,
free and non-commercial license on all patents filed in its name relating to the open-source
code (the "Patents") for the sole purpose of evaluation, development, research, prototyping
and experimentation.
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
Concrete-FFT is a pure Rust high performance fast Fourier transform library
that processes vectors of sizes that are powers of two. It was made to be used
as a backend in Zama's `concrete` library.

This library provides two FFT modules:
- The ordered module FFT applies a forward/inverse FFT that takes its input in standard
order, and outputs the result in standard order. For more detail on what the FFT
computes, check the ordered module-level documentation.
- The unordered module FFT applies a forward FFT that takes its input in standard order,
and outputs the result in a certain permuted order that may depend on the FFT plan. On the
other hand, the inverse FFT takes its input in that same permuted order and outputs its result
in standard order. This is useful for cases where the order of the coefficients in the
Fourier domain is not important. An example is using the Fourier transform for vector
convolution. The only operations that are performed in the Fourier domain are elementwise, and
so the order of the coefficients does not affect the results.

## Features

- `std` (default): This enables runtime arch detection for accelerated SIMD
instructions, and an FFT plan that measures the various implementations to
choose the fastest one at runtime.
- `nightly`: This enables unstable Rust features to further speed up the FFT,
by enabling AVX512F instructions on CPUs that support them. This feature
requires a nightly Rust
toolchain.
- `serde`: This enables serialization and deserialization functions for the
unordered plan. These allow for data in the Fourier domain to be serialized
from the permuted order to the standard order, and deserialized from the
standard order to the permuted order. This is needed since the inverse
transform must be used with the same plan that computed/deserialized the
forward transform (or more specifically, a plan with the same internal base
FFT size).

## Example

```rust
use concrete_fft::c64;
use concrete_fft::ordered::{Plan, Method};
use dyn_stack::{DynStack, GlobalMemBuffer, ReborrowMut};
use num_complex::ComplexFloat;
use std::time::Duration;

const N: usize = 4;
let plan = Plan::new(4, Method::Measure(Duration::from_millis(10)));
let mut scratch_memory = GlobalMemBuffer::new(plan.fft_scratch().unwrap());
let mut stack = DynStack::new(&mut scratch_memory);

let data = [
c64::new(1.0, 0.0),
c64::new(2.0, 0.0),
c64::new(3.0, 0.0),
c64::new(4.0, 0.0),
];

let mut transformed_fwd = data;
plan.fwd(&mut transformed_fwd, stack.rb_mut());

let mut transformed_inv = transformed_fwd;
plan.inv(&mut transformed_inv, stack.rb_mut());

for (actual, expected) in transformed_inv.iter().map(|z| z / N as f64).zip(data) {
assert!((expected - actual).abs() < 1e-9);
}
```

## Links

- [Zama](https://www.zama.ai/)
- [Concrete](https://github.com/zama-ai/concrete)

## License

This software is distributed under the BSD-3-Clause-Clear license with an
exemption that gives rights to use our patents for research, evaluation and
prototyping purposes, as well as for your personal projects.

If you want to use Concrete in a commercial product however, you will need to
purchase a separate commercial licence.

If you have any questions, please contact us at `[email protected].`
Loading

0 comments on commit d110fa0

Please sign in to comment.