numerics 0.1.0
Loading...
Searching...
No Matches
fft.cpp
Go to the documentation of this file.
1#include "spectral/fft.hpp"
4#include "backends/seq/impl.hpp"
5#ifdef NUMERICS_HAS_STD_SIMD
7#endif
8#include <stdexcept>
9
10namespace num {
11namespace spectral {
12
13// -- One-shot dispatch --------------------------------------------------------
14
15void fft(const CVector& in, CVector& out, FFTBackend b) {
16 if (out.size() != in.size())
17 throw std::invalid_argument("fft: in and out must have the same size");
18#ifdef NUMERICS_HAS_FFTW
19 if (b == FFTBackend::fftw) {
20 backends::fftw::fft(in, out);
21 return;
22 }
23#endif
24#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
25 if (b == FFTBackend::simd) {
26 backends::opt::fft(in, out);
27 return;
28 }
29#endif
30#ifdef NUMERICS_HAS_STD_SIMD
31 if (b == FFTBackend::stdsimd) {
32 backends::stdsimd::fft(in, out);
33 return;
34 }
35#endif
36 // seq is the fallback for simd/stdsimd on unsupported platforms
37 backends::seq::fft(in, out);
38}
39
40void ifft(const CVector& in, CVector& out, FFTBackend b) {
41 if (out.size() != in.size()) {
42 throw std::invalid_argument("ifft: in and out must have the same size");
43 }
44#ifdef NUMERICS_HAS_FFTW
45 if (b == FFTBackend::fftw) {
46 backends::fftw::ifft(in, out);
47 return;
48 }
49#endif
50#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
51 if (b == FFTBackend::simd) {
52 backends::opt::ifft(in, out);
53 return;
54 }
55#endif
56#ifdef NUMERICS_HAS_STD_SIMD
57 if (b == FFTBackend::stdsimd) {
58 backends::stdsimd::ifft(in, out);
59 return;
60 }
61#endif
62 backends::seq::ifft(in, out);
63}
64
65void rfft(const Vector& in, CVector& out, FFTBackend b) {
66 if (static_cast<int>(out.size()) != static_cast<int>(in.size()) / 2 + 1)
67 throw std::invalid_argument("rfft: out must have size n/2+1");
68#ifdef NUMERICS_HAS_FFTW
69 if (b == FFTBackend::fftw) {
70 backends::fftw::rfft(in, out);
71 return;
72 }
73#endif
74#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
75 if (b == FFTBackend::simd) {
76 backends::opt::rfft(in, out);
77 return;
78 }
79#endif
80#ifdef NUMERICS_HAS_STD_SIMD
81 if (b == FFTBackend::stdsimd) {
82 backends::stdsimd::rfft(in, out);
83 return;
84 }
85#endif
86 backends::seq::rfft(in, out);
87}
88
89void irfft(const CVector& in, int n, Vector& out, FFTBackend b) {
90 if (static_cast<int>(in.size()) != n / 2 + 1)
91 throw std::invalid_argument("irfft: in must have size n/2+1");
92 if (static_cast<int>(out.size()) != n)
93 throw std::invalid_argument("irfft: out must have size n");
94#ifdef NUMERICS_HAS_FFTW
95 if (b == FFTBackend::fftw) {
96 backends::fftw::irfft(in, n, out);
97 return;
98 }
99#endif
100#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
101 if (b == FFTBackend::simd) {
102 backends::opt::irfft(in, n, out);
103 return;
104 }
105#endif
106#ifdef NUMERICS_HAS_STD_SIMD
107 if (b == FFTBackend::stdsimd) {
108 backends::stdsimd::irfft(in, n, out);
109 return;
110 }
111#endif
112 backends::seq::irfft(in, n, out);
113}
114
115// -- FFTPlan ------------------------------------------------------------------
116
117FFTPlan::FFTPlan(int n, bool forward, FFTBackend b)
118 : n_(n),
119 backend_(b) {
120#ifdef NUMERICS_HAS_FFTW
121 if (b == FFTBackend::fftw) {
122 impl_ = new backends::fftw::FFTPlanImpl(n, forward);
123 return;
124 }
125#endif
126#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
127 if (b == FFTBackend::simd) {
128 impl_ = new backends::opt::FFTPlanImpl(n, !forward);
129 return;
130 }
131#endif
132#ifdef NUMERICS_HAS_STD_SIMD
133 if (b == FFTBackend::stdsimd) {
134 impl_ = new backends::stdsimd::FFTPlanImpl(n, !forward);
135 return;
136 }
137#endif
138 impl_ = new backends::seq::FFTPlanImpl(n, !forward);
139}
140
142#ifdef NUMERICS_HAS_FFTW
143 if (backend_ == FFTBackend::fftw) {
144 delete static_cast<backends::fftw::FFTPlanImpl*>(impl_);
145 return;
146 }
147#endif
148#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
149 if (backend_ == FFTBackend::simd) {
150 delete static_cast<backends::opt::FFTPlanImpl*>(impl_);
151 return;
152 }
153#endif
154#ifdef NUMERICS_HAS_STD_SIMD
155 if (backend_ == FFTBackend::stdsimd) {
156 delete static_cast<backends::stdsimd::FFTPlanImpl*>(impl_);
157 return;
158 }
159#endif
160 delete static_cast<backends::seq::FFTPlanImpl*>(impl_);
161}
162
163void FFTPlan::execute(const CVector& in, CVector& out) const {
164 if (static_cast<int>(in.size()) != n_ || static_cast<int>(out.size()) != n_)
165 throw std::invalid_argument("FFTPlan::execute: size mismatch");
166#ifdef NUMERICS_HAS_FFTW
167 if (backend_ == FFTBackend::fftw) {
168 static_cast<backends::fftw::FFTPlanImpl*>(impl_)->execute(in, out);
169 return;
170 }
171#endif
172#if defined(NUMERICS_HAS_AVX2) || defined(NUMERICS_HAS_NEON)
173 if (backend_ == FFTBackend::simd) {
174 for (idx i = 0; i < static_cast<idx>(n_); ++i)
175 out[i] = in[i];
176 static_cast<backends::opt::FFTPlanImpl*>(impl_)->execute(out);
177 return;
178 }
179#endif
180#ifdef NUMERICS_HAS_STD_SIMD
181 if (backend_ == FFTBackend::stdsimd) {
182 for (idx i = 0; i < static_cast<idx>(n_); ++i)
183 out[i] = in[i];
184 static_cast<backends::stdsimd::FFTPlanImpl*>(impl_)->execute(out);
185 return;
186 }
187#endif
188 for (idx i = 0; i < static_cast<idx>(n_); ++i)
189 out[i] = in[i];
190 static_cast<backends::seq::FFTPlanImpl*>(impl_)->execute(out);
191}
192
193} // namespace spectral
194} // namespace num
Dense owning vector.
Definition vector.hpp:16
constexpr idx size() const noexcept
Definition vector.hpp:83
FFTPlan(int n, bool forward=true, FFTBackend b=default_fft_backend)
Definition fft.cpp:117
void execute(const CVector &in, CVector &out) const
Definition fft.cpp:163
FFT interface with backend dispatch.
void irfft(const num::CVector &in, int n, num::Vector &out)
Definition impl.hpp:180
void ifft(const num::CVector &in, num::CVector &out)
Definition impl.hpp:161
void fft(const num::CVector &in, num::CVector &out)
Definition impl.hpp:153
void rfft(const num::Vector &in, num::CVector &out)
Definition impl.hpp:169
void ifft(const num::CVector &in, num::CVector &out)
Definition impl.hpp:54
void rfft(const num::Vector &in, num::CVector &out)
Definition impl.hpp:60
void irfft(const num::CVector &in, int n, num::Vector &out)
Definition impl.hpp:70
void fft(const num::CVector &in, num::CVector &out)
Definition impl.hpp:48
void ifft(const CVector &in, CVector &out, FFTBackend b=default_fft_backend)
Definition fft.cpp:40
void fft(const CVector &in, CVector &out, FFTBackend b=default_fft_backend)
Definition fft.cpp:15
void irfft(const CVector &in, int n, Vector &out, FFTBackend b=default_fft_backend)
Definition fft.cpp:89
void rfft(const Vector &in, CVector &out, FFTBackend b=default_fft_backend)
Definition fft.cpp:65
std::size_t idx
Definition types.hpp:11
FFTW3 backend wrappers. Only included by src/spectral/fft.cpp.
Handwritten AVX2 / NEON butterfly for the FFT.
std::experimental::simd butterfly for FFT.
Precomputed twiddle factors + SIMD butterfly execution.
Definition impl.hpp:117