#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(fftw_alloc_complex(pad*N)); â = reinterpret_cast(fftw_alloc_complex(pad*N)); fftw_import_wisdom_from_filename("fftw.wisdom"); a_to_â = fftw_plan_dft_1d(pad*N, reinterpret_cast(a), reinterpret_cast(â), FFTW_BACKWARD, 0); â_to_a = fftw_plan_dft_1d(pad*N, reinterpret_cast(â), reinterpret_cast(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 LogarithmicFourierTransform::fourier(const std::vector& c, bool symmetric) { std::vector ĉ(N); std::vector σ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 LogarithmicFourierTransform::inverse(const std::vector& ĉ) { std::vector c(N); std::vector σ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; }