4#include "debugtrace.hpp"
5#include "lasp_config.h"
7using rte = std::runtime_error;
9#if LASP_FFT_BACKEND == Armadillo
17 vc res = arma::fft(time);
18 return res.rows(0,
nfft / 2);
23 vc f_above_nyq = arma::conj(arma::reverse(f));
24 f_full.rows(0,
nfft / 2) = f;
25 f_full.rows(
nfft / 2,
nfft - 1) = f_above_nyq.rows(0,
nfft/2-1);
26 return arma::real(arma::ifft(f_full));
29#elif LASP_FFT_BACKEND == FFTW
38 fftw_plan forward_plan =
nullptr;
39 fftw_plan reverse_plan =
nullptr;
40 fftw_complex *frequencyDomain =
nullptr;
41 d *timeDomain =
nullptr;
45 timeDomain = (
d *)fftw_malloc(
sizeof(d) *
nfft);
48 (fftw_complex *)fftw_malloc(
sizeof(fftw_complex) * (
nfft / 2 + 1));
51 fftw_plan_dft_r2c_1d(
nfft, timeDomain, frequencyDomain, FFTW_MEASURE);
54 fftw_plan_dft_c2r_1d(
nfft, frequencyDomain, timeDomain, FFTW_MEASURE);
55 if (!forward_plan || !reverse_plan || !timeDomain || !frequencyDomain) {
56 throw rte(
"Error allocating FFT");
61 fftw_destroy_plan(forward_plan);
62 fftw_destroy_plan(reverse_plan);
63 fftw_free(frequencyDomain);
64 fftw_free(timeDomain);
68 if (time.n_rows !=
nfft) {
69 throw rte(
"Invalid size of input vector, should be equal to nfft");
73 memcpy(timeDomain, time.memptr(),
sizeof(d) *
nfft);
75 fftw_execute(forward_plan);
77 memcpy(
reinterpret_cast<void *
>(res.memptr()), frequencyDomain,
78 sizeof(
c) * (
nfft / 2 + 1));
84 if (f.n_rows !=
nfft / 2 + 1) {
85 throw rte(
"Invalid size of input vector, should be equal to nfft/2+1");
87 memcpy(frequencyDomain,
88 reinterpret_cast<void *
>(
const_cast<c *
>(f.memptr())),
89 (
nfft / 2 + 1) *
sizeof(
c));
91 fftw_execute(reverse_plan);
94 memcpy(res.memptr(), timeDomain,
nfft *
sizeof(d));
105 "Cannot compile lasp_ffc.c, no FFT backend specified. Should either be FFTPack, or FFTW"
111 throw rte(
"Invalid nfft: 0");
113 if (
nfft >= LASP_MAX_NFFT) {
114 throw rte(
"Invalid nfft, should be smaller than: " +
115 std::to_string(LASP_MAX_NFFT));
117 _impl = std::make_unique<Fft_impl>(
nfft);
128 return _impl->fft(timedata);
134 cmat res(_impl->nfft / 2 + 1, freqdata.n_cols);
139 for (
us colno = 0; colno < freqdata.n_cols; colno++) {
140 res.col(colno) = _impl->fft(freqdata.col(colno));
148 return _impl->ifft(freqdata);
151 dmat res(_impl->nfft, freqdata.n_cols);
157 for (
us colno = 0; colno < freqdata.n_cols; colno++) {
158 res.col(colno) = _impl->ifft(freqdata.col(colno));
164#if LASP_FFT_BACKEND == Armadillo
165#elif LASP_FFT_BACKEND == FFTW
166 if (wisdom.length() > 0) {
167 int rv = fftw_import_wisdom_from_string(wisdom.c_str());
169 throw rte(
"Error loading FFTW wisdom");
176#if LASP_FFT_BACKEND == Armadillo
178#elif LASP_FFT_BACKEND == FFTW
183 char *wis = fftw_export_wisdom_to_string();
184 std::string res{wis};
vd ifft(const vc &freqdata)
static std::string store_fft_wisdom()
Return a string containing FFT wisdom storage. String is empty for backend != FFTW.
vc fft(const vd &timedata)
us nfft() const
Return nfft.
static void load_fft_wisdom(const std::string &wisdom)
Load FFT wisdom from a wisdom string. Function does nothing if FFT backend is not FFTW.
Fft(const us nfft)
Initialize FFT.
size_t us
We often use boolean values.