numerics 0.1.0
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)
20 j ^= bit;
21 j ^= bit;
22 if (i < j)
23 std::swap(a[i], a[j]);
24 }
25}
26
27inline void cooley_tukey(num::CVector& a, bool invert) {
28 num::idx n = a.size();
29 if (n == 0 || (n & (n - 1)))
30 throw std::invalid_argument("FFT: length must be a power of two");
31 bit_reverse(a);
32 for (num::idx len = 2; len <= n; len <<= 1) {
33 double ang = TWO_PI / static_cast<double>(len) * (invert ? 1.0 : -1.0);
34 num::cplx wlen{std::cos(ang), std::sin(ang)};
35 for (num::idx i = 0; i < n; i += len) {
36 num::cplx w{1.0, 0.0};
37 for (num::idx j = 0; j < len / 2; ++j) {
38 num::cplx u = a[i + j];
39 num::cplx v = a[i + j + len / 2] * w;
40 a[i + j] = u + v;
41 a[i + j + len / 2] = u - v;
42 w *= wlen;
43 }
44 }
45 }
46}
47
48inline void fft(const num::CVector& in, num::CVector& out) {
49 for (num::idx i = 0; i < in.size(); ++i)
50 out[i] = in[i];
51 cooley_tukey(out, false);
52}
53
54inline void ifft(const num::CVector& in, num::CVector& out) {
55 for (num::idx i = 0; i < in.size(); ++i)
56 out[i] = in[i];
57 cooley_tukey(out, true);
58}
59
60inline void rfft(const num::Vector& in, num::CVector& out) {
61 num::idx n = in.size();
62 num::CVector tmp(n, num::cplx{0, 0});
63 for (num::idx i = 0; i < n; ++i)
64 tmp[i] = {in[i], 0.0};
65 cooley_tukey(tmp, false);
66 for (num::idx k = 0; k < n / 2 + 1; ++k)
67 out[k] = tmp[k];
68}
69
70inline void irfft(const num::CVector& in, int n, num::Vector& out) {
71 num::CVector tmp(static_cast<num::idx>(n), num::cplx{0, 0});
72 for (num::idx k = 0; k < static_cast<num::idx>(n / 2 + 1); ++k)
73 tmp[k] = in[k];
74 for (num::idx k = 1; k < static_cast<num::idx>((n - 1) / 2 + 1); ++k)
75 tmp[static_cast<num::idx>(n) - k] = std::conj(in[k]);
76 cooley_tukey(tmp, true);
77 for (num::idx i = 0; i < static_cast<num::idx>(n); ++i)
78 out[i] = tmp[i].real();
79}
80
81// Precomputed plan: twiddle factors per butterfly stage
83 int n;
84 bool invert;
85 std::vector<std::vector<num::cplx>> twiddles;
86
87 FFTPlanImpl(int n_, bool inv)
88 : n(n_)
89 , invert(inv) {
90 if (n_ == 0 || (n_ & (n_ - 1)))
91 throw std::invalid_argument(
92 "FFTPlan: length must be a power of two");
93 for (int len = 2; len <= n_; len <<= 1) {
94 double ang = TWO_PI / static_cast<double>(len) * (inv ? 1.0 : -1.0);
95 num::cplx wlen{std::cos(ang), std::sin(ang)};
96 std::vector<num::cplx> tw(len / 2);
97 num::cplx w{1.0, 0.0};
98 for (int j = 0; j < len / 2; ++j) {
99 tw[j] = w;
100 w *= wlen;
101 }
102 twiddles.push_back(std::move(tw));
103 }
104 }
105
106 void execute(num::CVector& a) const {
107 bit_reverse(a);
108 int stage = 0;
109 for (int len = 2; len <= n; len <<= 1, ++stage) {
110 const auto& tw = twiddles[stage];
111 for (int i = 0; i < n; i += len) {
112 for (int j = 0; j < len / 2; ++j) {
113 num::cplx u = a[i + j];
114 num::cplx v = a[i + j + len / 2] * tw[j];
115 a[i + j] = u + v;
116 a[i + j + len / 2] = u - v;
117 }
118 }
119 }
120 }
121};
122
123} // namespace seq
124} // namespace backends
Dense vector with optional GPU storage, templated over scalar type T.
Definition vector.hpp:24
constexpr idx size() const noexcept
Definition vector.hpp:80
FFT interface with backend dispatch.
void cooley_tukey(num::CVector &a, bool invert)
Definition impl.hpp:27
void bit_reverse(num::CVector &a)
Definition impl.hpp:15
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
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:106
FFTPlanImpl(int n_, bool inv)
Definition impl.hpp:87
std::vector< std::vector< num::cplx > > twiddles
Definition impl.hpp:85