numerics
Loading...
Searching...
No Matches
impl.hpp
Go to the documentation of this file.
1/// @file spectral/backends/seq/impl.hpp
2/// @brief Native Cooley-Tukey radix-2 DIT FFT (sequential, power-of-two sizes).
3/// Only included by src/spectral/fft.cpp.
4#pragma once
5#include "spectral/fft.hpp"
6#include <cmath>
7#include <stdexcept>
8#include <vector>
9
10namespace backends {
11namespace seq {
12
13static constexpr double TWO_PI = 6.283185307179586476925286766559;
14
15inline void bit_reverse(num::CVector& a) {
16 num::idx n = a.size();
17 for (num::idx i = 1, j = 0; i < n; ++i) {
18 num::idx bit = n >> 1;
19 for (; j & bit; bit >>= 1) j ^= bit;
20 j ^= bit;
21 if (i < j) std::swap(a[i], a[j]);
22 }
23}
24
25inline void cooley_tukey(num::CVector& a, bool invert) {
26 num::idx n = a.size();
27 if (n == 0 || (n & (n - 1)))
28 throw std::invalid_argument("FFT: length must be a power of two");
29 bit_reverse(a);
30 for (num::idx len = 2; len <= n; len <<= 1) {
31 double ang = TWO_PI / static_cast<double>(len) * (invert ? 1.0 : -1.0);
32 num::cplx wlen{std::cos(ang), std::sin(ang)};
33 for (num::idx i = 0; i < n; i += len) {
34 num::cplx w{1.0, 0.0};
35 for (num::idx j = 0; j < len / 2; ++j) {
36 num::cplx u = a[i + j];
37 num::cplx v = a[i + j + len / 2] * w;
38 a[i + j] = u + v;
39 a[i + j + len / 2] = u - v;
40 w *= wlen;
41 }
42 }
43 }
44}
45
46inline void fft(const num::CVector& in, num::CVector& out) {
47 for (num::idx i = 0; i < in.size(); ++i) out[i] = in[i];
48 cooley_tukey(out, false);
49}
50
51inline void ifft(const num::CVector& in, num::CVector& out) {
52 for (num::idx i = 0; i < in.size(); ++i) out[i] = in[i];
53 cooley_tukey(out, true);
54}
55
56inline void rfft(const num::Vector& in, num::CVector& out) {
57 num::idx n = in.size();
58 num::CVector tmp(n, num::cplx{0, 0});
59 for (num::idx i = 0; i < n; ++i) tmp[i] = {in[i], 0.0};
60 cooley_tukey(tmp, false);
61 for (num::idx k = 0; k < n / 2 + 1; ++k) out[k] = tmp[k];
62}
63
64inline void irfft(const num::CVector& in, int n, num::Vector& out) {
65 num::CVector tmp(static_cast<num::idx>(n), num::cplx{0, 0});
66 for (num::idx k = 0; k < static_cast<num::idx>(n / 2 + 1); ++k)
67 tmp[k] = in[k];
68 for (num::idx k = 1; k < static_cast<num::idx>((n - 1) / 2 + 1); ++k)
69 tmp[static_cast<num::idx>(n) - k] = std::conj(in[k]);
70 cooley_tukey(tmp, true);
71 for (num::idx i = 0; i < static_cast<num::idx>(n); ++i) out[i] = tmp[i].real();
72}
73
74// Precomputed plan: twiddle factors per butterfly stage
76 int n;
77 bool invert;
78 std::vector<std::vector<num::cplx>> twiddles;
79
80 FFTPlanImpl(int n_, bool inv) : n(n_), invert(inv) {
81 if (n_ == 0 || (n_ & (n_ - 1)))
82 throw std::invalid_argument("FFTPlan: length must be a power of two");
83 for (int len = 2; len <= n_; len <<= 1) {
84 double ang = TWO_PI / static_cast<double>(len) * (inv ? 1.0 : -1.0);
85 num::cplx wlen{std::cos(ang), std::sin(ang)};
86 std::vector<num::cplx> tw(len / 2);
87 num::cplx w{1.0, 0.0};
88 for (int j = 0; j < len / 2; ++j) { tw[j] = w; w *= wlen; }
89 twiddles.push_back(std::move(tw));
90 }
91 }
92
93 void execute(num::CVector& a) const {
94 bit_reverse(a);
95 int stage = 0;
96 for (int len = 2; len <= n; len <<= 1, ++stage) {
97 const auto& tw = twiddles[stage];
98 for (int i = 0; i < n; i += len) {
99 for (int j = 0; j < len / 2; ++j) {
100 num::cplx u = a[i + j];
101 num::cplx v = a[i + j + len / 2] * tw[j];
102 a[i + j] = u + v;
103 a[i + j + len / 2] = u - v;
104 }
105 }
106 }
107 }
108};
109
110} // namespace seq
111} // namespace backends
Dense vector with optional GPU storage, templated over scalar type T.
Definition vector.hpp:23
constexpr idx size() const noexcept
Definition vector.hpp:77
FFT interface with backend dispatch.
void cooley_tukey(num::CVector &a, bool invert)
Definition impl.hpp:25
void bit_reverse(num::CVector &a)
Definition impl.hpp:15
void ifft(const num::CVector &in, num::CVector &out)
Definition impl.hpp:51
void rfft(const num::Vector &in, num::CVector &out)
Definition impl.hpp:56
void irfft(const num::CVector &in, int n, num::Vector &out)
Definition impl.hpp:64
void fft(const num::CVector &in, num::CVector &out)
Definition impl.hpp:46
std::size_t idx
Definition types.hpp:11
std::complex< real > cplx
Definition types.hpp:12
void execute(num::CVector &a) const
Definition impl.hpp:93
FFTPlanImpl(int n_, bool inv)
Definition impl.hpp:80
std::vector< std::vector< num::cplx > > twiddles
Definition impl.hpp:78