summaryrefslogtreecommitdiff
path: root/gr-fft/lib/fft.cc
diff options
context:
space:
mode:
authormormj <34754695+mormj@users.noreply.github.com>2020-11-03 16:51:44 -0500
committerGitHub <noreply@github.com>2020-11-03 16:51:44 -0500
commited95e8d45cfc6cd3e026298dadf4d2e8f9f1c3b8 (patch)
treea15c82b2a2c2baa623434ad2c3a4c51416002082 /gr-fft/lib/fft.cc
parent0f780e26d6545338b6c4a1b34405822a9a6ec706 (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.cc149
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 */