86 lines
2.8 KiB
C++
86 lines
2.8 KiB
C++
#include <cassert>
|
|
#include <iostream>
|
|
#include <math.h>
|
|
#include <numbers>
|
|
#include <ranges>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
|
|
constexpr void print(auto& x_re, auto& x_im) {
|
|
for (std::tuple<const float&, const float&> 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<float>, std::vector<float>>
|
|
fft(const std::vector<float>& x_re, const std::vector<float>& 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<float>(even_x_re.begin(), even_x_re.end()),
|
|
std::vector<float>(even_x_im.begin(), even_x_im.end()));
|
|
const auto& [odd_fft_re, odd_fft_im] =
|
|
fft(std::vector<float>(odd_x_re.begin(), odd_x_re.end()),
|
|
std::vector<float>(odd_x_im.begin(), odd_x_im.end()));
|
|
|
|
/// Combine even and odd ffts
|
|
|
|
std::vector<float> factors_re(N);
|
|
std::vector<float> 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<float> result_re(N);
|
|
std::vector<float> 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<float> x_re = {1, 2, 3, 4};
|
|
std::vector<float> x_im = {0, 0, 0, 0};
|
|
const auto [X_re, X_im] = fft(x_re, x_im);
|
|
|
|
return 0;
|
|
}
|