diff options
author | mormj <34754695+mormj@users.noreply.github.com> | 2020-11-03 16:51:44 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-03 16:51:44 -0500 |
commit | ed95e8d45cfc6cd3e026298dadf4d2e8f9f1c3b8 (patch) | |
tree | a15c82b2a2c2baa623434ad2c3a4c51416002082 /gr-fft/lib/fft.cc | |
parent | 0f780e26d6545338b6c4a1b34405822a9a6ec706 (diff) |
Move FFT functions and blocks to templates (#3903)
* fft: refactor fft classes as templates
In order to reduce code duplication construct fft objects and blocks
with template paramters.
Separate forward and reverse as a template
parameter
Maintain the real fft block forward as r2c and reverse as r2c as well
Co-authored-by: Andrej Rode <mail@andrejro.de>
Diffstat (limited to 'gr-fft/lib/fft.cc')
-rw-r--r-- | gr-fft/lib/fft.cc | 149 |
1 files changed, 40 insertions, 109 deletions
diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc index dca635265b..9fc0a22f46 100644 --- a/gr-fft/lib/fft.cc +++ b/gr-fft/lib/fft.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003,2008,2011,2012 Free Software Foundation, Inc. + * Copyright 2003,2008,2011,2012,2020 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -141,7 +141,9 @@ static void export_wisdom() // ---------------------------------------------------------------- -fft_complex::fft_complex(int fft_size, bool forward, int nthreads) + +template <class T, bool forward> +fft<T, forward>::fft(int fft_size, int nthreads) : d_nthreads(nthreads), d_inbuf(fft_size), d_outbuf(fft_size) { gr::configure_default_loggers(d_logger, d_debug_logger, "fft_complex"); @@ -159,137 +161,57 @@ fft_complex::fft_complex(int fft_size, bool forward, int nthreads) lock_wisdom(); import_wisdom(); // load prior wisdom from disk - d_plan = fftwf_plan_dft_1d(fft_size, - reinterpret_cast<fftwf_complex*>(d_inbuf.data()), - reinterpret_cast<fftwf_complex*>(d_outbuf.data()), - forward ? FFTW_FORWARD : FFTW_BACKWARD, - FFTW_MEASURE); - + initialize_plan(fft_size); if (d_plan == NULL) { GR_LOG_ERROR(d_logger, "creating plan failed"); - throw std::runtime_error("fftwf_plan_dft_1d failed"); + throw std::runtime_error("Creating fftw plan failed"); } export_wisdom(); // store new wisdom to disk unlock_wisdom(); } -fft_complex::~fft_complex() +template <> +void fft<gr_complex, true>::initialize_plan(int fft_size) { - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - fftwf_destroy_plan((fftwf_plan)d_plan); + d_plan = fftwf_plan_dft_1d(fft_size, + reinterpret_cast<fftwf_complex*>(d_inbuf.data()), + reinterpret_cast<fftwf_complex*>(d_outbuf.data()), + FFTW_FORWARD, + FFTW_MEASURE); } -void fft_complex::set_nthreads(int n) +template <> +void fft<gr_complex, false>::initialize_plan(int fft_size) { - if (n <= 0) { - throw std::out_of_range("gr::fft: invalid number of threads"); - } - d_nthreads = n; - -#ifdef FFTW3F_THREADS - fftwf_plan_with_nthreads(d_nthreads); -#endif + d_plan = fftwf_plan_dft_1d(fft_size, + reinterpret_cast<fftwf_complex*>(d_inbuf.data()), + reinterpret_cast<fftwf_complex*>(d_outbuf.data()), + FFTW_BACKWARD, + FFTW_MEASURE); } -void fft_complex::execute() { fftwf_execute((fftwf_plan)d_plan); } - -// ---------------------------------------------------------------- -fft_real_fwd::fft_real_fwd(int fft_size, int nthreads) - : d_nthreads(nthreads), d_inbuf(fft_size), d_outbuf(fft_size / 2 + 1) +template <> +void fft<float, true>::initialize_plan(int fft_size) { - gr::configure_default_loggers(d_logger, d_debug_logger, "fft_real_fwd"); - - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - static_assert(sizeof(fftwf_complex) == sizeof(gr_complex), - "The size of fftwf_complex is not equal to gr_complex"); - - if (fft_size <= 0) { - throw std::out_of_range("gr::fft: invalid fft_size"); - } - - config_threading(nthreads); - lock_wisdom(); - import_wisdom(); // load prior wisdom from disk - d_plan = fftwf_plan_dft_r2c_1d(fft_size, d_inbuf.data(), reinterpret_cast<fftwf_complex*>(d_outbuf.data()), FFTW_MEASURE); - - if (d_plan == NULL) { - GR_LOG_ERROR(d_logger, "creating plan failed"); - throw std::runtime_error("fftwf_plan_dft_r2c_1d failed"); - } - export_wisdom(); // store new wisdom to disk - unlock_wisdom(); -} - -fft_real_fwd::~fft_real_fwd() -{ - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - fftwf_destroy_plan((fftwf_plan)d_plan); } -void fft_real_fwd::set_nthreads(int n) +template <> +void fft<float, false>::initialize_plan(int fft_size) { - if (n <= 0) { - throw std::out_of_range( - "gr::fft::fft_real_fwd::set_nthreads: invalid number of threads"); - } - d_nthreads = n; - -#ifdef FFTW3F_THREADS - fftwf_plan_with_nthreads(d_nthreads); -#endif -} - -void fft_real_fwd::execute() { fftwf_execute((fftwf_plan)d_plan); } - -// ---------------------------------------------------------------- - -fft_real_rev::fft_real_rev(int fft_size, int nthreads) - : d_nthreads(nthreads), d_inbuf(fft_size / 2 + 1), d_outbuf(fft_size) -{ - gr::configure_default_loggers(d_logger, d_debug_logger, "fft_real_rev"); - - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - static_assert(sizeof(fftwf_complex) == sizeof(gr_complex), - "The size of fftwf_complex is not equal to gr_complex"); - - if (fft_size <= 0) { - throw std::out_of_range("gr::fft::fft_real_rev: invalid fft_size"); - } - - config_threading(nthreads); - lock_wisdom(); - import_wisdom(); // load prior wisdom from disk - - // FIXME If there's ever a chance that the planning functions - // will be called in multiple threads, we've got to ensure single - // threaded access. They are not thread-safe. d_plan = fftwf_plan_dft_c2r_1d(fft_size, reinterpret_cast<fftwf_complex*>(d_inbuf.data()), d_outbuf.data(), FFTW_MEASURE); - - if (d_plan == NULL) { - GR_LOG_ERROR(d_logger, "creating plan failed"); - throw std::runtime_error("fftwf_plan_dft_c2r_1d failed"); - } - export_wisdom(); // store new wisdom to disk - unlock_wisdom(); } -fft_real_rev::~fft_real_rev() + +template <class T, bool forward> +fft<T, forward>::~fft() { // Hold global mutex during plan construction and destruction. planner::scoped_lock lock(planner::mutex()); @@ -297,11 +219,11 @@ fft_real_rev::~fft_real_rev() fftwf_destroy_plan((fftwf_plan)d_plan); } -void fft_real_rev::set_nthreads(int n) +template <class T, bool forward> +void fft<T, forward>::set_nthreads(int n) { if (n <= 0) { - throw std::out_of_range( - "gr::fft::fft_real_rev::set_nthreads: invalid number of threads"); + throw std::out_of_range("gr::fft: invalid number of threads"); } d_nthreads = n; @@ -310,7 +232,16 @@ void fft_real_rev::set_nthreads(int n) #endif } -void fft_real_rev::execute() { fftwf_execute((fftwf_plan)d_plan); } +template <class T, bool forward> +void fft<T, forward>::execute() +{ + fftwf_execute((fftwf_plan)d_plan); +} + +template class fft<gr_complex, true>; +template class fft<gr_complex, false>; +template class fft<float, true>; +template class fft<float, false>; } /* namespace fft */ } /* namespace gr */ |