1#include "internal/fft_iterative.h"
10bool is_power_of_two(
size_t n) {
11 return n && ((n & (n - 1)) == 0);
15size_t next_power_of_two(
size_t n) {
24#if SIZE_MAX > UINT32_MAX
40void bit_reverse_permute(std::vector<cd>& a) {
41 const size_t N = a.size();
43 while ((1u << log_n) < N)
47 for (
size_t i = 0; i < N; ++i) {
52 for (
int b = 0; b < log_n; ++b) {
53 rev = (rev << 1) | (x & 1);
57 std::swap(a[i], a[rev]);
61void pad_to_pow_two(std::vector<cd>& a,
size_t& N) {
62 if (is_power_of_two(N))
65 size_t N2 = next_power_of_two(N);
66 a.resize(N2, cd {0.0, 0.0});
84void iterative_fft(std::vector<cd>& a,
bool inverse) {
91 bit_reverse_permute(a);
94 const double PI = std::acos(-1.0);
96 inverse ? +1.0 : -1.0;
101 for (
size_t len = 2; len <= N; len <<= 1) {
104 const double angle = sign * 2.0 * PI / double(len);
105 const cd wlen = std::polar(1.0, angle);
108 for (
size_t i = 0; i < N; i += len) {
109 cd w = cd {1.0, 0.0};
110 const size_t half = len >> 1;
111 for (
size_t j = 0; j < half; ++j) {
116 cd v = a[i + j + half] * w;
118 a[i + j + half] = u - v;
126 for (
size_t i = 0; i < N; ++i)
127 a[i] /=
static_cast<double>(N);
135std::vector<cd> fft_copy(
const std::vector<cd>& input,
bool inverse) {
136 std::vector<cd> a = input;
137 iterative_fft(a, inverse);
142void iterative_fft_2d(std::vector<cd>& data,
size_t width,
size_t height,
bool inverse) {
144 size_t W = fft::next_power_of_two(width);
145 size_t H = fft::next_power_of_two(height);
148 if (W != width || H != height) {
149 std::vector<cd> padded(W * H, {0.0, 0.0});
150 for (
size_t y = 0; y < height; y++)
151 for (
size_t x = 0; x < width; x++)
152 padded[y * W + x] = data[y * width + x];
153 data = std::move(padded);
159 std::vector<cd> temp_row(width);
160 std::vector<cd> temp_col(height);
163 for (
size_t y = 0; y < height; y++) {
164 std::copy(data.begin() + y * width, data.begin() + (y + 1) * width, temp_row.begin());
165 fft::iterative_fft(temp_row, inverse);
166 std::copy(temp_row.begin(), temp_row.end(), data.begin() + y * width);
170 for (
size_t x = 0; x < width; x++) {
171 for (
size_t y = 0; y < height; y++)
172 temp_col[y] = data[y * width + x];
173 fft::iterative_fft(temp_col, inverse);
174 for (
size_t y = 0; y < height; y++)
175 data[y * width + x] = temp_col[y];
184iterative_fft_2d_copy(
const std::vector<cd>& input,
size_t width,
size_t height,
bool inverse) {
185 std::vector<cd> a = input;
186 iterative_fft_2d(a, width, height, inverse);