Initial commit
This commit is contained in:
127
fft/recursive_fft_cplx.cpp
Normal file
127
fft/recursive_fft_cplx.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user