fourier_algorithms/
fft.rs

1use num_complex::Complex;
2
3/// Specifies a type of transform to perform.
4#[derive(Copy, Clone, PartialEq, Eq)]
5pub enum Transform {
6    /// Fast Fourier transform
7    Fft,
8    /// Inverse fast Fourier transform
9    Ifft,
10    /// Unscaled IFFT (conventionally the IFFT is scaled by `1 / N`)
11    UnscaledIfft,
12    /// Square-root scaled FFT (a unitary transform)
13    SqrtScaledFft,
14    /// Square-root scaled IFFT (a unitary transform)
15    SqrtScaledIfft,
16}
17
18impl Transform {
19    /// Returns true if the transform is a forward transform.
20    pub fn is_forward(&self) -> bool {
21        match self {
22            Self::Fft | Self::SqrtScaledFft => true,
23            Self::Ifft | Self::UnscaledIfft | Self::SqrtScaledIfft => false,
24        }
25    }
26
27    /// Returns the inverse transform, or `None` for `UnscaledIfft`.
28    pub fn inverse(&self) -> Option<Self> {
29        match self {
30            Self::Fft => Some(Self::Ifft),
31            Self::Ifft => Some(Self::Fft),
32            Self::SqrtScaledFft => Some(Self::SqrtScaledIfft),
33            Self::SqrtScaledIfft => Some(Self::SqrtScaledFft),
34            Self::UnscaledIfft => None,
35        }
36    }
37}
38
39/// The interface for performing FFTs.
40pub trait Fft {
41    /// The real type used by the FFT.
42    type Real: Copy;
43
44    /// The size of the FFT.
45    fn size(&self) -> usize;
46
47    /// Apply an FFT or IFFT in-place.
48    fn transform_in_place(&self, input: &mut [Complex<Self::Real>], transform: Transform);
49
50    /// Apply an FFT or IFFT out-of-place.
51    fn transform(
52        &self,
53        input: &[Complex<Self::Real>],
54        output: &mut [Complex<Self::Real>],
55        transform: Transform,
56    ) {
57        assert_eq!(input.len(), self.size());
58        assert_eq!(output.len(), self.size());
59        output.copy_from_slice(input);
60        self.transform_in_place(output, transform);
61    }
62
63    /// Apply an FFT in-place.
64    fn fft_in_place(&self, input: &mut [Complex<Self::Real>]) {
65        self.transform_in_place(input, Transform::Fft);
66    }
67
68    /// Apply an IFFT in-place.
69    fn ifft_in_place(&self, input: &mut [Complex<Self::Real>]) {
70        self.transform_in_place(input, Transform::Ifft);
71    }
72
73    /// Apply an FFT out-of-place.
74    fn fft(&self, input: &[Complex<Self::Real>], output: &mut [Complex<Self::Real>]) {
75        self.transform(input, output, Transform::Fft);
76    }
77
78    /// Apply an IFFT out-of-place.
79    fn ifft(&self, input: &[Complex<Self::Real>], output: &mut [Complex<Self::Real>]) {
80        self.transform(input, output, Transform::Ifft);
81    }
82}