diff options
author | Jaron Kent-Dobias <jaron@kent-dobias.com> | 2025-04-18 23:02:43 -0300 |
---|---|---|
committer | Jaron Kent-Dobias <jaron@kent-dobias.com> | 2025-04-18 23:02:43 -0300 |
commit | e4ab12ce914b2471355a99943b58c5b274d8754c (patch) | |
tree | ce730c80936dba6ed4ac82e210cd5b7faddbc258 /log-fourier.cpp | |
parent | 92bd43e33e79a7d682267d3f6054e8b1dd9d00db (diff) | |
download | code-e4ab12ce914b2471355a99943b58c5b274d8754c.tar.gz code-e4ab12ce914b2471355a99943b58c5b274d8754c.tar.bz2 code-e4ab12ce914b2471355a99943b58c5b274d8754c.zip |
Refactor
Diffstat (limited to 'log-fourier.cpp')
-rw-r--r-- | log-fourier.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/log-fourier.cpp b/log-fourier.cpp new file mode 100644 index 0000000..1e2e7d9 --- /dev/null +++ b/log-fourier.cpp @@ -0,0 +1,102 @@ +#include "log-fourier.hpp" + +LogarithmicFourierTransform::LogarithmicFourierTransform(unsigned N, Real k, Real Δτ, unsigned pad) : N(N), pad(pad), k(k), Δτ(Δτ) { + τₛ = -0.5 * N; + ωₛ = -0.5 * N; + sₛ = -0.5 * pad * N; + a = reinterpret_cast<Complex*>(fftw_alloc_complex(pad*N)); + â = reinterpret_cast<Complex*>(fftw_alloc_complex(pad*N)); + fftw_import_wisdom_from_filename("fftw.wisdom"); + a_to_â = fftw_plan_dft_1d(pad*N, reinterpret_cast<fftw_complex*>(a), reinterpret_cast<fftw_complex*>(â), FFTW_BACKWARD, 0); + â_to_a = fftw_plan_dft_1d(pad*N, reinterpret_cast<fftw_complex*>(â), reinterpret_cast<fftw_complex*>(a), FFTW_BACKWARD, 0); + fftw_export_wisdom_to_filename("fftw.wisdom"); +} + +LogarithmicFourierTransform::~LogarithmicFourierTransform() { + fftw_destroy_plan(a_to_â); + fftw_destroy_plan(â_to_a); + fftw_free(a); + fftw_free(â); + fftw_cleanup(); +} + +Real LogarithmicFourierTransform::τ(unsigned n) const { + return Δτ * (n + τₛ); +} + +Real LogarithmicFourierTransform::ω(unsigned n) const { + return Δτ * (n + ωₛ); +} + +Real LogarithmicFourierTransform::s(unsigned n) const { + return (n + sₛ) * 2*M_PI / (pad * N * Δτ); +} + +Real LogarithmicFourierTransform::t(unsigned n) const { + return exp(τ(n)); +} + +Real LogarithmicFourierTransform::ν(unsigned n) const { + return exp(ω(n)); +} + +Complex gamma(Complex z) { + gsl_sf_result logΓ; + gsl_sf_result argΓ; + + gsl_sf_lngamma_complex_e(z.real(), z.imag(), &logΓ, &argΓ); + + return exp(logΓ.val + 1i * argΓ.val); +} + +std::vector<Complex> LogarithmicFourierTransform::fourier(const std::vector<Real>& c, bool symmetric) { + std::vector<Complex> ĉ(N); + std::vector<Real> σs = {1}; + if (symmetric){ + σs.push_back(-1); + } + for (Real σ : σs) { + for (unsigned n = 0; n < pad*N; n++) { + if (n < N) { + a[n] = c[n] * exp((1 - k) * τ(n)); + } else { + a[n] = 0; + } + } + fftw_execute(a_to_â); + for (unsigned n = 0; n < pad*N; n++) { + â[(pad*N / 2 + n) % (pad*N)] *= pow(1i * σ, 1i * s(n) - k) * gamma(k - 1i * s(n)); + } + fftw_execute(â_to_a); + for (unsigned n = 0; n < N; n++) { + ĉ[n] += exp(-k * ω(n)) * a[(pad - 1)*N+n] / (Real)(pad*N); + } + } + + return ĉ; +} + +std::vector<Real> LogarithmicFourierTransform::inverse(const std::vector<Complex>& ĉ) { + std::vector<Real> c(N); + std::vector<Real> σs = {1, -1}; + for (Real σ : σs) { + for (unsigned n = 0; n < pad * N; n++) { + if (n < N) { + a[n] = ĉ[n] * exp((1 - k) * ω(n)); + } else { + a[n] = 0; + } + } + fftw_execute(a_to_â); + for (unsigned n = 0; n < pad*N; n++) { + â[(pad*N / 2 + n) % (pad*N)] *= pow(-1i * σ, 1i * s(n) - k) * gamma(k - 1i * s(n)); + } + fftw_execute(â_to_a); + for (unsigned n = 0; n < N; n++) { + c[n] += exp(-k * τ(n)) * a[(pad - 1)*N+n].real() / (Real)(pad*N) / (2 * M_PI); + } + } + + return c; +} + |