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 `hello@zama.ai.`
