#include #include #include #include #include #include #include constexpr void print(auto& x_re, auto& x_im) { for (std::tuple elem : std::views::zip(x_re, x_im)) { const auto re = std::get<0>(elem); const auto im = std::get<1>(elem); std::cout << "\t" << re << "; " << im << std::endl; } } constexpr std::pair, std::vector> fft(const std::vector& x_re, const std::vector& x_im) { // TODO: Make sure this is ignored in release mode assert(x_re.size() == x_im.size()); const unsigned N = x_re.size(); if (N == 1) { return {x_re, x_im}; } else { const auto& even_x_re = x_re | std::views::stride(2); const auto& even_x_im = x_im | std::views::stride(2); const auto& odd_x_re = x_re | std::views::drop(1) | std::views::stride(2); const auto& odd_x_im = x_im | std::views::drop(1) | std::views::stride(2); const auto& [even_fft_re, even_fft_im] = fft(std::vector(even_x_re.begin(), even_x_re.end()), std::vector(even_x_im.begin(), even_x_im.end())); const auto& [odd_fft_re, odd_fft_im] = fft(std::vector(odd_x_re.begin(), odd_x_re.end()), std::vector(odd_x_im.begin(), odd_x_im.end())); /// Combine even and odd ffts std::vector factors_re(N); std::vector factors_im(N); for (int k = 0; k < N; ++k) { factors_re[k] = std::cos((2 * std::numbers::pi * k) / N); factors_im[k] = -std::sin((2 * std::numbers::pi * k) / N); } std::vector result_re(N); std::vector result_im(N); for (int k = 0; k < N / 2; ++k) { result_re[k] = even_fft_re[k] + factors_re[k] * odd_fft_re[k] - factors_im[k] * odd_fft_im[k]; result_im[k] = even_fft_im[k] + factors_im[k] * odd_fft_re[k] + factors_re[k] * odd_fft_im[k]; } for (int k = 0; k < N / 2; ++k) { result_re[N / 2 + k] = even_fft_re[k] + factors_re[N / 2 + k] * odd_fft_re[k] - factors_im[k] * odd_fft_im[k]; result_im[N / 2 + k] = even_fft_im[k] + factors_im[N / 2 + k] * odd_fft_re[k] + factors_re[k] * odd_fft_im[k]; } return {result_re, result_im}; } } int main() { std::vector x_re = {1, 2, 3, 4}; std::vector x_im = {0, 0, 0, 0}; const auto [X_re, X_im] = fft(x_re, x_im); return 0; }