Files
rohde-engineering-competition/fft/recursive_fft_cplx.cpp
2026-02-18 21:32:22 +01:00

128 lines
2.5 KiB
C++

#include <iostream>
#include <math.h>
#include <numbers>
#include <ranges>
#include <vector>
/*
*
* Helper classes and functions
*
*/
template <typename value_t>
class Complex {
public:
constexpr Complex() noexcept : mRe(), mIm() {
}
constexpr Complex(const value_t& re, const value_t& im) noexcept
: mRe(re), mIm(im) {
}
constexpr Complex operator-() const {
return {-mRe, -mIm};
}
constexpr Complex operator+(const Complex& other) const {
return {mRe + other.mRe, mIm + other.mIm};
}
constexpr Complex operator-(const Complex& other) const {
return *this + (-other);
}
constexpr Complex operator*(const Complex& other) const {
return {mRe * other.mRe - mIm * other.mIm,
mIm * other.mRe + mRe * other.mIm};
}
constexpr value_t& real() {
return mRe;
}
constexpr value_t& imag() {
return mIm;
}
private:
value_t mRe;
value_t mIm;
};
using ComplexFloat = Complex<float>;
template <typename value_t>
constexpr void print(std::vector<Complex<value_t>> vec) {
for (auto& elem : vec) {
std::cout << "\t" << elem.real() << "; " << elem.imag() << std::endl;
}
}
/*
*
* FFT implementation
*
*/
constexpr std::vector<ComplexFloat> fft(const std::vector<ComplexFloat>& x) {
const unsigned N = x.size();
if (N == 1) {
return x;
} else {
/// Compute even and odd ffts
const auto& even_x = x | std::views::stride(2);
const auto& odd_x = x | std::views::drop(1) | std::views::stride(2);
const auto& even_fft =
fft(std::vector<ComplexFloat>(even_x.begin(), even_x.end()));
const auto& odd_fft =
fft(std::vector<ComplexFloat>(odd_x.begin(), odd_x.end()));
/// Combine even and odd ffts
std::vector<ComplexFloat> factors(N);
for (int k = 0; k < N; ++k) {
factors[k].real() = std::cos((2 * std::numbers::pi * k) / N);
factors[k].imag() = -std::sin((2 * std::numbers::pi * k) / N);
}
std::vector<ComplexFloat> result(N);
for (int k = 0; k < N; ++k) {
result[k] =
even_fft[k % (N / 2)] + factors[k] * odd_fft[k % (N / 2)];
}
return result;
}
}
/*
*
* Usage
*
*/
int main() {
std::vector<ComplexFloat> x = {{1, 0}, {2, 0}, {3, 0}, {4, 0}};
const auto& X = fft(x);
std::cout << "================" << std::endl;
std::cout << "result: " << std::endl;
print(X);
return 0;
}