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) {
23#if SIZE_MAX > UINT32_MAX
39void bit_reverse_permute(std::vector<cd> &a) {
40 const size_t N = a.size();
42 while ((1u << log_n) < N) ++log_n;
45 for (
size_t i = 0; i < N; ++i) {
50 for (
int b = 0; b < log_n; ++b) {
51 rev = (rev << 1) | (x & 1);
54 if (i < rev) std::swap(a[i], a[rev]);
58void pad_to_pow_two(std::vector<cd> &a,
size_t &N) {
59 if (is_power_of_two(N))
return;
61 size_t N2 = next_power_of_two(N);
62 a.resize(N2, cd{0.0, 0.0});
80void iterative_fft(std::vector<cd> &a,
bool inverse) {
87 bit_reverse_permute(a);
90 const double PI = std::acos(-1.0);
92 inverse ? +1.0 : -1.0;
97 for (
size_t len = 2; len <= N; len <<= 1) {
100 const double angle = sign * 2.0 * PI / double(len);
101 const cd wlen = std::polar(1.0, angle);
104 for (
size_t i = 0; i < N; i += len) {
106 const size_t half = len >> 1;
107 for (
size_t j = 0; j < half; ++j) {
112 cd v = a[i + j + half] * w;
114 a[i + j + half] = u - v;
122 for (
size_t i = 0; i < N; ++i) a[i] /=
static_cast<double>(N);
130std::vector<cd> fft_copy(
const std::vector<cd> &input,
bool inverse) {
131 std::vector<cd> a = input;
132 iterative_fft(a, inverse);
137void iterative_fft_2d(std::vector<cd> &data,
size_t width,
size_t height,
bool inverse) {
139 size_t W = fft::next_power_of_two(width);
140 size_t H = fft::next_power_of_two(height);
143 if (W != width || H != height) {
144 std::vector<cd> padded(W * H, {0.0, 0.0});
145 for (
size_t y = 0; y < height; y++)
146 for (
size_t x = 0; x < width; x++) padded[y * W + x] = data[y * width + x];
147 data = std::move(padded);
153 std::vector<cd> temp_row(width);
154 std::vector<cd> temp_col(height);
157 for (
size_t y = 0; y < height; y++) {
158 std::copy(data.begin() + y * width, data.begin() + (y + 1) * width, temp_row.begin());
159 fft::iterative_fft(temp_row, inverse);
160 std::copy(temp_row.begin(), temp_row.end(), data.begin() + y * width);
164 for (
size_t x = 0; x < width; x++) {
165 for (
size_t y = 0; y < height; y++) temp_col[y] = data[y * width + x];
166 fft::iterative_fft(temp_col, inverse);
167 for (
size_t y = 0; y < height; y++) data[y * width + x] = temp_col[y];
175std::vector<cd> iterative_fft_2d_copy(
const std::vector<cd> &input,
size_t width,
size_t height,
177 std::vector<cd> a = input;
178 iterative_fft_2d(a, width, height, inverse);