numerics 0.1.0
Loading...
Searching...
No Matches
fft.hpp
Go to the documentation of this file.
1/// @file spectral/fft.hpp
2/// @brief FFT interface with backend dispatch.
3///
4/// Each module defines its own backend enum for the choices relevant to it.
5/// This enum covers spectral transforms; linalg uses num::Backend in
6/// core/policy.hpp.
7///
8/// Backends:
9/// FFTBackend::seq -- native Cooley-Tukey radix-2 DIT; always available.
10/// Input length must be a power of two.
11/// FFTBackend::fftw -- FFTW3 (AVX / NEON optimised); requires
12/// NUMERICS_HAS_FFTW.
13/// Falls back to FFTBackend::seq automatically if FFTW3
14/// is absent.
15///
16/// Conventions (both backends):
17/// Forward DFT: X[k] = sum_{j=0}^{n-1} x[j] * exp(-2*pi*i*j*k/n)
18/// Inverse DFT: unnormalised (FFTW convention). Divide by n to recover x.
19/// rfft output: n/2+1 complex bins (Hermitian symmetry of real input).
20#pragma once
21
22#include "core/types.hpp"
23#include "core/vector.hpp"
24
25namespace num {
26namespace spectral {
27
28/// @brief Selects which backend handles an FFT operation.
29enum class FFTBackend {
30 seq, ///< Native Cooley-Tukey radix-2 DIT -- always available (power-of-two
31 ///< only)
32 simd, ///< Handwritten AVX2 / NEON butterfly -- falls back to seq if
33 ///< unavailable
34 stdsimd, ///< std::experimental::simd butterfly -- requires
35 ///< NUMERICS_HAS_STD_SIMD
36 fftw, ///< FFTW3 (mixed-radix, AVX / NEON optimised) -- requires
37 ///< NUMERICS_HAS_FFTW
38};
39
40// Convenience constants -- use these at call sites:
41// fft(in, out, num::spectral::fftw);
42inline constexpr FFTBackend seq = FFTBackend::seq;
43inline constexpr FFTBackend fftw = FFTBackend::fftw;
46
47/// True when FFTW3 was found at configure time.
48inline constexpr bool has_fftw =
49#ifdef NUMERICS_HAS_FFTW
50 true;
51#else
52 false;
53#endif
54
55/// True when handwritten AVX2 or NEON backend is available.
56inline constexpr bool has_fft_simd =
57#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
58 true;
59#else
60 false;
61#endif
62
63/// True when std::experimental::simd is available.
64inline constexpr bool has_fft_stdsimd =
65#ifdef NUMERICS_HAS_STD_SIMD
66 true;
67#else
68 false;
69#endif
70
71/// Automatically selected at configure time: fftw > simd > seq.
73#ifdef NUMERICS_HAS_FFTW
75#elif defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
77#else
79#endif
80
81// One-shot transforms
82
83/// @brief Forward complex DFT. out must be pre-allocated to in.size().
84void fft(const CVector& in, CVector& out, FFTBackend b = default_fft_backend);
85
86/// @brief Inverse complex DFT (unnormalised: result = n * true_inverse).
87void ifft(const CVector& in, CVector& out, FFTBackend b = default_fft_backend);
88
89/// @brief Real-to-complex forward DFT. out must be pre-allocated to n/2+1.
90void rfft(const Vector& in, CVector& out, FFTBackend b = default_fft_backend);
91
92/// @brief Complex-to-real inverse DFT (unnormalised).
93/// @param n Length of the real output (must satisfy in.size() == n/2+1).
94void irfft(const CVector& in,
95 int n,
96 Vector& out,
98
99// Reusable plan
100
101/// @brief Precomputed plan for repeated complex transforms of a fixed size.
102///
103/// @code
104/// num::spectral::FFTPlan plan(1024); // forward, default backend
105/// for (auto& frame : frames)
106/// plan.execute(frame, spectrum); // O(n log n), no allocation
107/// @endcode
108class FFTPlan {
109 public:
110 /// @param n Transform size (must be power of two for
111 /// FFTBackend::seq)
112 /// @param forward true = forward DFT, false = inverse DFT
113 /// @param b Backend to use (default: default_fft_backend)
114 explicit FFTPlan(int n,
115 bool forward = true,
117 ~FFTPlan();
118
119 FFTPlan(const FFTPlan&) = delete;
120 FFTPlan& operator=(const FFTPlan&) = delete;
121
122 void execute(const CVector& in, CVector& out) const;
123
124 int size() const {
125 return n_;
126 }
128 return backend_;
129 }
130
131 private:
132 int n_;
133 FFTBackend backend_;
134 void* impl_; // backends::seq::FFTPlanImpl or backends::fftw::FFTPlanImpl
135};
136
137} // namespace spectral
138} // namespace num
Dense vector with optional GPU storage, templated over scalar type T.
Definition vector.hpp:24
Precomputed plan for repeated complex transforms of a fixed size.
Definition fft.hpp:108
FFTBackend backend() const
Definition fft.hpp:127
FFTPlan(const FFTPlan &)=delete
int size() const
Definition fft.hpp:124
void execute(const CVector &in, CVector &out) const
Definition fft.cpp:162
FFTPlan & operator=(const FFTPlan &)=delete
Core type definitions.
void ifft(const CVector &in, CVector &out, FFTBackend b=default_fft_backend)
Inverse complex DFT (unnormalised: result = n * true_inverse).
Definition fft.cpp:40
void fft(const CVector &in, CVector &out, FFTBackend b=default_fft_backend)
Forward complex DFT. out must be pre-allocated to in.size().
Definition fft.cpp:15
FFTBackend
Selects which backend handles an FFT operation.
Definition fft.hpp:29
void irfft(const CVector &in, int n, Vector &out, FFTBackend b=default_fft_backend)
Complex-to-real inverse DFT (unnormalised).
Definition fft.cpp:88
constexpr bool has_fft_simd
True when handwritten AVX2 or NEON backend is available.
Definition fft.hpp:56
constexpr FFTBackend fftw
Definition fft.hpp:43
constexpr FFTBackend fft_stdsimd
Definition fft.hpp:45
constexpr FFTBackend default_fft_backend
Automatically selected at configure time: fftw > simd > seq.
Definition fft.hpp:72
constexpr FFTBackend fft_simd
Definition fft.hpp:44
void rfft(const Vector &in, CVector &out, FFTBackend b=default_fft_backend)
Real-to-complex forward DFT. out must be pre-allocated to n/2+1.
Definition fft.cpp:64
constexpr bool has_fft_stdsimd
True when std::experimental::simd is available.
Definition fft.hpp:64
constexpr bool has_fftw
True when FFTW3 was found at configure time.
Definition fft.hpp:48
constexpr FFTBackend seq
Definition fft.hpp:42
Vector operations.