128 lines
2.5 KiB
C++
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;
|
|
}
|