From 06f92ca4200bbebd2ecb77f88b4524711f9292c4 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 27 Apr 2010 22:05:15 -0400 Subject: Adding the synthesis filterbank (the opposite of the channelizer). It's ugly right now and uses a lot of memory to handle the buffers for each filter/input stream. --- gnuradio-core/src/lib/filter/Makefile.am | 3 + gnuradio-core/src/lib/filter/filter.i | 2 + .../lib/filter/gr_pfb_synthesis_filterbank_ccf.cc | 164 +++++++++++++++++++++ .../lib/filter/gr_pfb_synthesis_filterbank_ccf.h | 93 ++++++++++++ .../lib/filter/gr_pfb_synthesis_filterbank_ccf.i | 38 +++++ 5 files changed, 300 insertions(+) create mode 100644 gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc create mode 100644 gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h create mode 100644 gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 23c1dadc3..6a6532eb0 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -205,6 +205,7 @@ libfilter_la_common_SOURCES = \ float_dotprod_generic.c \ short_dotprod_generic.c \ gr_pfb_channelizer_ccf.cc \ + gr_pfb_synthesis_filterbank_ccf.cc\ gr_pfb_decimator_ccf.cc \ gr_pfb_interpolator_ccf.cc \ gr_pfb_arb_resampler_ccf.cc \ @@ -288,6 +289,7 @@ grinclude_HEADERS = \ short_dotprod_x86.h \ sse_debug.h \ gr_pfb_channelizer_ccf.h \ + gr_pfb_synthesis_filterbank_ccf.h\ gr_pfb_decimator_ccf.h \ gr_pfb_interpolator_ccf.h \ gr_pfb_arb_resampler_ccf.h \ @@ -344,6 +346,7 @@ swiginclude_HEADERS = \ gr_single_pole_iir_filter_ff.i \ gr_single_pole_iir_filter_cc.i \ gr_pfb_channelizer_ccf.i \ + gr_pfb_synthesis_filterbank_ccf.i\ gr_pfb_decimator_ccf.i \ gr_pfb_interpolator_ccf.i \ gr_pfb_arb_resampler_ccf.i \ diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i index bdfb8fa8d..645607cba 100644 --- a/gnuradio-core/src/lib/filter/filter.i +++ b/gnuradio-core/src/lib/filter/filter.i @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ %include "gr_goertzel_fc.i" %include "gr_cma_equalizer_cc.i" %include "gr_pfb_channelizer_ccf.i" +%include "gr_pfb_synthesis_filterbank_ccf.i" %include "gr_pfb_decimator_ccf.i" %include "gr_pfb_interpolator_ccf.i" %include "gr_pfb_arb_resampler_ccf.i" diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc new file mode 100644 index 000000000..f8b0eae26 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc @@ -0,0 +1,164 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps) +{ + return gr_pfb_synthesis_filterbank_ccf_sptr + (new gr_pfb_synthesis_filterbank_ccf (numchans, taps)); +} + + +gr_pfb_synthesis_filterbank_ccf::gr_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps) + : gr_sync_interpolator ("pfb_synthesis_filterbank_ccf", + gr_make_io_signature (numchans, numchans, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + numchans), + d_updated (false), d_numchans(numchans) +{ + d_filters = std::vector(d_numchans); + + d_buffer = new gr_complex*[d_numchans]; + + // Create an FIR filter for each channel and zero out the taps + std::vector vtaps(0, d_numchans); + for(unsigned int i = 0; i < d_numchans; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_buffer[i] = new gr_complex[65535]; + memset(d_buffer[i], 0, 65535*sizeof(gr_complex)); + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the IFFT to handle the input channel rotations + d_fft = new gri_fft_complex (d_numchans, true); +} + +gr_pfb_synthesis_filterbank_ccf::~gr_pfb_synthesis_filterbank_ccf () +{ + for(unsigned int i = 0; i < d_numchans; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_synthesis_filterbank_ccf::set_taps (const std::vector &taps) +{ + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_numchans); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_numchans; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_numchans]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter+1); + + d_updated = true; +} + +void +gr_pfb_synthesis_filterbank_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_numchans; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } +} + + +int +gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex*) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + unsigned int n, i; + for(n = 0; n < noutput_items/d_numchans; n++) { + for(i = 0; i < d_numchans; i++) { + in = (gr_complex*)input_items[i]; + d_fft->get_inbuf()[i] = (in+i)[n]; + } + + // spin through IFFT + d_fft->execute(); + + for(i = 0; i < d_numchans; i++) { + d_buffer[i][n+d_taps_per_filter-1] = d_fft->get_outbuf()[i]; + out[i] = d_filters[i]->filter(&d_buffer[i][n]); + } + out += d_numchans; + } + + for(i = 0; i < d_numchans; i++) { + memcpy(d_buffer[i], &d_buffer[i][n], + (d_taps_per_filter)*sizeof(gr_complex)); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h new file mode 100644 index 000000000..4b6235a8b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_GR_PFB_SYNTHESIS_FILTERBANK_CCF_H +#define INCLUDED_GR_PFB_SYNTHESIS_FILTERBANK_CCF_H + +#include + +class gr_pfb_synthesis_filterbank_ccf; +typedef boost::shared_ptr gr_pfb_synthesis_filterbank_ccf_sptr; +gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps); + +class gr_fir_ccf; +class gri_fft_complex; + + +/*! + * \class gr_pfb_synthesis_filterbank_ccf + * + * \brief Polyphase synthesis filterbank with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + */ + +class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator +{ + private: + /*! + * Build the polyphase synthesis filterbank. + * \param numchans (unsigned integer) Specifies the number of channels M + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + friend gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps); + + bool d_updated; + unsigned int d_numchans; + std::vector d_filters; + std::vector< std::vector > d_taps; + unsigned int d_taps_per_filter; + gri_fft_complex *d_fft; + gr_complex **d_buffer; + + /*! + * Build the polyphase synthesis filterbank. + * \param numchans (unsigned integer) Specifies the number of channels M + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + gr_pfb_synthesis_filterbank_ccf (unsigned int numchans, + const std::vector &taps); + +public: + ~gr_pfb_synthesis_filterbank_ccf (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + void set_taps (const std::vector &taps); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i new file mode 100644 index 000000000..02a9f0255 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pfb_synthesis_filterbank_ccf); + +gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps); + +class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator +{ + private: + gr_pfb_synthesis_filterbank_ccf (unsigned int numchans, + const std::vector &taps); + + public: + ~gr_pfb_synthesis_filterbank_ccf (); + + void set_taps (const std::vector &taps); +}; -- cgit From 0c6abf713755e4c7f705bad2e9f982d431b4286d Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 27 Apr 2010 22:17:44 -0400 Subject: Fixing ordering so that the input channels line up in the output signal properly. --- gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc index f8b0eae26..15ba1ae2e 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc @@ -150,11 +150,13 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, for(i = 0; i < d_numchans; i++) { d_buffer[i][n+d_taps_per_filter-1] = d_fft->get_outbuf()[i]; - out[i] = d_filters[i]->filter(&d_buffer[i][n]); + out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(&d_buffer[i][n]); } out += d_numchans; } + // Move the last chunk of memory to the front for the next entry + // this make sure that the first taps_per_filter values are correct for(i = 0; i < d_numchans; i++) { memcpy(d_buffer[i], &d_buffer[i][n], (d_taps_per_filter)*sizeof(gr_complex)); -- cgit From 2ee1a94ff42a3d1858805bcce50b6aadb1773f47 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 16 May 2010 14:39:53 -0400 Subject: Can now set more channels than input signals. Empty channels are established as the outtermost channels (around fs/2 and -fs/2). --- .../lib/filter/gr_pfb_synthesis_filterbank_ccf.cc | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc index 15ba1ae2e..b1365bcf9 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc @@ -43,7 +43,7 @@ gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf gr_pfb_synthesis_filterbank_ccf::gr_pfb_synthesis_filterbank_ccf (unsigned int numchans, const std::vector &taps) : gr_sync_interpolator ("pfb_synthesis_filterbank_ccf", - gr_make_io_signature (numchans, numchans, sizeof(gr_complex)), + gr_make_io_signature (1, numchans, sizeof(gr_complex)), gr_make_io_signature (1, 1, sizeof(gr_complex)), numchans), d_updated (false), d_numchans(numchans) @@ -132,6 +132,9 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, { gr_complex *in = (gr_complex*) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; + int numsigs = input_items.size(); + int ndiff = d_numchans - numsigs; + int nhalf = (int)ceil((float)numsigs/2.0f); if (d_updated) { d_updated = false; @@ -140,11 +143,24 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, unsigned int n, i; for(n = 0; n < noutput_items/d_numchans; n++) { - for(i = 0; i < d_numchans; i++) { + // fill up the populated channels based on the + // number of real input streams + for(i = 0; i < nhalf; i++) { in = (gr_complex*)input_items[i]; d_fft->get_inbuf()[i] = (in+i)[n]; } + // Make the ndiff channels around N/2 0 + for(; i < nhalf+ndiff; i++) { + d_fft->get_inbuf()[i] = gr_complex(0,0); + } + + // Finish off channels with data + for(; i < d_numchans; i++) { + in = (gr_complex*)input_items[i-ndiff]; + d_fft->get_inbuf()[i] = (in+i)[n]; + } + // spin through IFFT d_fft->execute(); -- cgit From cb2fa9a58c9a52f3501881964ee4f59992c5d84d Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Sat, 9 Oct 2010 16:11:03 -0400 Subject: rearrange includes to always be: internal GR, external, with GR. --- gnuradio-core/src/lib/runtime/Makefile.am | 4 ++-- gnuradio-core/src/lib/swig/Makefile.am | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am index abd789a1d..f67e8843d 100644 --- a/gnuradio-core/src/lib/runtime/Makefile.am +++ b/gnuradio-core/src/lib/runtime/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2003,2004,2007,2008,2009 Free Software Foundation, Inc. +# Copyright 2003,2004,2007,2008,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,7 +21,7 @@ include $(top_srcdir)/Makefile.common -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(GRUEL_INCLUDES) $(WITH_INCLUDES) +AM_CPPFLAGS = $(GRUEL_INCLUDES) $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(WITH_INCLUDES) noinst_LTLIBRARIES = libruntime.la libruntime-qa.la diff --git a/gnuradio-core/src/lib/swig/Makefile.am b/gnuradio-core/src/lib/swig/Makefile.am index 242f27d9c..1a50b8c8e 100644 --- a/gnuradio-core/src/lib/swig/Makefile.am +++ b/gnuradio-core/src/lib/swig/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2001,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright 2001,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -22,7 +22,7 @@ include $(top_srcdir)/Makefile.common if PYTHON -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) -I$(srcdir) \ +AM_CPPFLAGS = -I$(srcdir) $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \ $(WITH_INCLUDES) EXTRA_DIST = gen-swig-bug-fix -- cgit From 2e633fc33dcbc3e1b5c35323ebe24373d57ea459 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 16 Oct 2010 11:13:53 -0400 Subject: Adding a FIR filter implemented with its own internal buffer. This one keeps its own delay line and just takes in input samples instead of a pointer to an external buffer. The synthesis filter is being updated to use the new FIR implementation. --- gnuradio-core/src/lib/filter/Makefile.am | 4 +- .../lib/filter/gr_pfb_synthesis_filterbank_ccf.cc | 22 ++-- .../lib/filter/gr_pfb_synthesis_filterbank_ccf.h | 23 ++-- .../lib/filter/gri_fir_filter_with_buffer_ccf.cc | 81 +++++++++++++ .../lib/filter/gri_fir_filter_with_buffer_ccf.h | 130 +++++++++++++++++++++ 5 files changed, 243 insertions(+), 17 deletions(-) create mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc create mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 6a6532eb0..5c7473d06 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2001,2002,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright 2001,2002,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -190,6 +190,7 @@ libfilter_la_common_SOURCES = \ gr_fft_filter_fff.cc \ gr_goertzel_fc.cc \ gr_filter_delay_fc.cc \ + gri_fir_filter_with_buffer_ccf.cc \ gr_fractional_interpolator_ff.cc \ gr_fractional_interpolator_cc.cc \ gr_hilbert_fc.cc \ @@ -267,6 +268,7 @@ grinclude_HEADERS = \ gr_fft_filter_ccc.h \ gr_fft_filter_fff.h \ gr_filter_delay_fc.h \ + gri_fir_filter_with_buffer_ccf.h \ gr_fir_sysconfig_x86.h \ gr_fir_sysconfig_powerpc.h \ gr_fractional_interpolator_ff.h \ diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc index b1365bcf9..0b31bcf72 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc @@ -48,16 +48,18 @@ gr_pfb_synthesis_filterbank_ccf::gr_pfb_synthesis_filterbank_ccf numchans), d_updated (false), d_numchans(numchans) { - d_filters = std::vector(d_numchans); + //d_filters = std::vector(d_numchans); + d_filters = std::vector(d_numchans); - d_buffer = new gr_complex*[d_numchans]; + //d_buffer = new gr_complex*[d_numchans]; // Create an FIR filter for each channel and zero out the taps std::vector vtaps(0, d_numchans); for(unsigned int i = 0; i < d_numchans; i++) { - d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); - d_buffer[i] = new gr_complex[65535]; - memset(d_buffer[i], 0, 65535*sizeof(gr_complex)); + d_filters[i] = new gri_fir_filter_with_buffer_ccf(vtaps); + //d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + //d_buffer[i] = new gr_complex[65535]; + //memset(d_buffer[i], 0, 65535*sizeof(gr_complex)); } // Now, actually set the filters' taps @@ -134,7 +136,7 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, gr_complex *out = (gr_complex *) output_items[0]; int numsigs = input_items.size(); int ndiff = d_numchans - numsigs; - int nhalf = (int)ceil((float)numsigs/2.0f); + unsigned int nhalf = (unsigned int)ceil((float)numsigs/2.0f); if (d_updated) { d_updated = false; @@ -165,18 +167,22 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, d_fft->execute(); for(i = 0; i < d_numchans; i++) { - d_buffer[i][n+d_taps_per_filter-1] = d_fft->get_outbuf()[i]; - out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(&d_buffer[i][n]); + //d_buffer[i][n+d_taps_per_filter-1] = d_fft->get_outbuf()[i]; + //out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(&d_buffer[i][n]); + out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(d_fft->get_outbuf()[i]); } out += d_numchans; } // Move the last chunk of memory to the front for the next entry // this make sure that the first taps_per_filter values are correct + + /* for(i = 0; i < d_numchans; i++) { memcpy(d_buffer[i], &d_buffer[i][n], (d_taps_per_filter)*sizeof(gr_complex)); } + */ return noutput_items; } diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h index 4b6235a8b..27c8c2c50 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h @@ -25,6 +25,7 @@ #define INCLUDED_GR_PFB_SYNTHESIS_FILTERBANK_CCF_H #include +#include class gr_pfb_synthesis_filterbank_ccf; typedef boost::shared_ptr gr_pfb_synthesis_filterbank_ccf_sptr; @@ -49,24 +50,29 @@ class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator private: /*! * Build the polyphase synthesis filterbank. - * \param numchans (unsigned integer) Specifies the number of channels M - * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param numchans (unsigned integer) Specifies the number of + channels M + * \param taps (vector/list of floats) The prototype filter to + populate the filterbank. */ friend gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf (unsigned int numchans, const std::vector &taps); bool d_updated; unsigned int d_numchans; - std::vector d_filters; - std::vector< std::vector > d_taps; unsigned int d_taps_per_filter; gri_fft_complex *d_fft; - gr_complex **d_buffer; + //gr_complex **d_buffer; + std::vector< gri_fir_filter_with_buffer_ccf*> d_filters; + std::vector< std::vector > d_taps; + /*! * Build the polyphase synthesis filterbank. - * \param numchans (unsigned integer) Specifies the number of channels M - * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param numchans (unsigned integer) Specifies the number of + channels M + * \param taps (vector/list of floats) The prototype filter + to populate the filterbank. */ gr_pfb_synthesis_filterbank_ccf (unsigned int numchans, const std::vector &taps); @@ -76,7 +82,8 @@ public: /*! * Resets the filterbank's filter taps with the new prototype filter - * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param taps (vector/list of floats) The prototype filter to + populate the filterbank. */ void set_taps (const std::vector &taps); diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc new file mode 100644 index 000000000..e9545549f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +gri_fir_filter_with_buffer_ccf::gri_fir_filter_with_buffer_ccf(const std::vector &taps) +{ + d_buffer = NULL; + set_taps(taps); +} + +gri_fir_filter_with_buffer_ccf::~gri_fir_filter_with_buffer_ccf() +{ + free(d_buffer); +} + +gr_complex +gri_fir_filter_with_buffer_ccf::filter (gr_complex input) +{ +#if 0 + unsigned int i; + + for(i = ntaps()-1; i > 0; i--) { + d_buffer[i] = d_buffer[i-1]; + } + d_buffer[0] = input; + + gr_complex out = d_buffer[0]*d_taps[0]; + for(i = 1; i < ntaps(); i++) { + out += d_buffer[i]*d_taps[i]; + } + return out; + +#else + unsigned int i; + + d_buffer[d_idx] = input; + d_buffer[d_idx+ntaps()] = input; + //d_idx = (d_idx + 1) % ntaps(); + d_idx++; + if(d_idx == ntaps()) + d_idx = 0; + + gr_complex out = d_buffer[d_idx]*d_taps[0]; + for(i = 1; i < ntaps(); i++) { + out += d_buffer[d_idx + i]*d_taps[i]; + } + return out; +#endif +} + +void +gri_fir_filter_with_buffer_ccf::filterN (gr_complex output[], + const gr_complex input[], + unsigned long n) +{ + +} diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h new file mode 100644 index 000000000..5adc3e231 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gr_fir_XXX.py + * Any changes made to this file will be overwritten. + */ + + +#ifndef INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_H +#define INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_H + +#include +#include +#include +#include + +/*! + * \brief FIR with internal buffer for gr_complex input, + gr_complex output and float taps + * \ingroup filter + * + */ + +class gri_fir_filter_with_buffer_ccf { + +protected: + std::vector d_taps; // reversed taps + gr_complex *d_buffer; + unsigned int d_idx; + +public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + gri_fir_filter_with_buffer_ccf (const std::vector &taps); + + ~gri_fir_filter_with_buffer_ccf (); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \returns the filtered input value. + */ + gr_complex filter (gr_complex input); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + void filterN (gr_complex output[], const gr_complex input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + void filterNdec (gr_complex output[], const gr_complex input[], + unsigned long n, unsigned decimate); + + /*! + * \brief install \p new_taps as the current taps. + */ + void set_taps (const std::vector &taps) + { + d_taps = gr_reverse(taps); + //d_taps = (taps); + + if(d_buffer != NULL) + free(d_buffer); + + // FIXME: memalign this to 16-byte boundaries for SIMD later + d_buffer = (gr_complex*)malloc(sizeof(gr_complex) * 2 * d_taps.size()); + memset(d_buffer, 0x00, sizeof(gr_complex) * 2 * d_taps.size()); + d_idx = 0; + } + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned ntaps () const { return d_taps.size (); } + + /*! + * \return current taps + */ + const std::vector get_taps () const + { + return gr_reverse(d_taps); + } +}; + +#endif /* INCLUDED_GR_GR_FIR_FILTER_WITH_BUFFER_CCF_H */ -- cgit From e037d329ed2b80c655f7d5c0fcdcef8353b6c52f Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 16 Oct 2010 14:35:03 -0400 Subject: Cleaning up the new FIR filter implementation. Protects against some corner cases and adds filterN. --- .../lib/filter/gri_fir_filter_with_buffer_ccf.cc | 34 ++++++++-------------- .../lib/filter/gri_fir_filter_with_buffer_ccf.h | 11 ++++--- 2 files changed, 19 insertions(+), 26 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc index e9545549f..55e316d02 100644 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc @@ -23,8 +23,8 @@ #ifdef HAVE_CONFIG_H #include #endif + #include -#include gri_fir_filter_with_buffer_ccf::gri_fir_filter_with_buffer_ccf(const std::vector &taps) { @@ -34,42 +34,30 @@ gri_fir_filter_with_buffer_ccf::gri_fir_filter_with_buffer_ccf(const std::vector gri_fir_filter_with_buffer_ccf::~gri_fir_filter_with_buffer_ccf() { - free(d_buffer); + if(d_buffer != NULL) + free(d_buffer); } gr_complex gri_fir_filter_with_buffer_ccf::filter (gr_complex input) { -#if 0 - unsigned int i; - - for(i = ntaps()-1; i > 0; i--) { - d_buffer[i] = d_buffer[i-1]; - } - d_buffer[0] = input; - - gr_complex out = d_buffer[0]*d_taps[0]; - for(i = 1; i < ntaps(); i++) { - out += d_buffer[i]*d_taps[i]; - } - return out; - -#else unsigned int i; d_buffer[d_idx] = input; d_buffer[d_idx+ntaps()] = input; + + // using the later for the case when ntaps=0; + // profiling shows this doesn't make a difference //d_idx = (d_idx + 1) % ntaps(); d_idx++; - if(d_idx == ntaps()) + if(d_idx >= ntaps()) d_idx = 0; - gr_complex out = d_buffer[d_idx]*d_taps[0]; - for(i = 1; i < ntaps(); i++) { + gr_complex out = gr_complex(0,0); + for(i = 0; i < ntaps(); i++) { out += d_buffer[d_idx + i]*d_taps[i]; } return out; -#endif } void @@ -77,5 +65,7 @@ gri_fir_filter_with_buffer_ccf::filterN (gr_complex output[], const gr_complex input[], unsigned long n) { - + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(input[i]); + } } diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h index 5adc3e231..c91d70534 100644 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h @@ -33,6 +33,7 @@ #include #include #include +#include /*! * \brief FIR with internal buffer for gr_complex input, @@ -100,14 +101,16 @@ public: void set_taps (const std::vector &taps) { d_taps = gr_reverse(taps); - //d_taps = (taps); - if(d_buffer != NULL) + if(d_buffer != NULL) { free(d_buffer); + d_buffer = NULL; + } // FIXME: memalign this to 16-byte boundaries for SIMD later - d_buffer = (gr_complex*)malloc(sizeof(gr_complex) * 2 * d_taps.size()); - memset(d_buffer, 0x00, sizeof(gr_complex) * 2 * d_taps.size()); + size_t t = sizeof(gr_complex) * 2 * d_taps.size(); + d_buffer = (gr_complex*)malloc(t); + memset(d_buffer, 0x00, t); d_idx = 0; } -- cgit From 72c9a5a158b0b18964c8f2f8f914f16060868146 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 16 Oct 2010 14:36:38 -0400 Subject: Cleaning up synthesis filter and using new FIR filter with buffer. --- .../lib/filter/gr_pfb_synthesis_filterbank_ccf.cc | 21 +-------------------- .../lib/filter/gr_pfb_synthesis_filterbank_ccf.h | 2 -- 2 files changed, 1 insertion(+), 22 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc index 0b31bcf72..9fad1bd0d 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc @@ -25,8 +25,6 @@ #endif #include -#include -#include #include #include #include @@ -48,18 +46,12 @@ gr_pfb_synthesis_filterbank_ccf::gr_pfb_synthesis_filterbank_ccf numchans), d_updated (false), d_numchans(numchans) { - //d_filters = std::vector(d_numchans); d_filters = std::vector(d_numchans); - //d_buffer = new gr_complex*[d_numchans]; - // Create an FIR filter for each channel and zero out the taps std::vector vtaps(0, d_numchans); for(unsigned int i = 0; i < d_numchans; i++) { d_filters[i] = new gri_fir_filter_with_buffer_ccf(vtaps); - //d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); - //d_buffer[i] = new gr_complex[65535]; - //memset(d_buffer[i], 0, 65535*sizeof(gr_complex)); } // Now, actually set the filters' taps @@ -167,22 +159,11 @@ gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, d_fft->execute(); for(i = 0; i < d_numchans; i++) { - //d_buffer[i][n+d_taps_per_filter-1] = d_fft->get_outbuf()[i]; - //out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(&d_buffer[i][n]); out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(d_fft->get_outbuf()[i]); } + out += d_numchans; } - // Move the last chunk of memory to the front for the next entry - // this make sure that the first taps_per_filter values are correct - - /* - for(i = 0; i < d_numchans; i++) { - memcpy(d_buffer[i], &d_buffer[i][n], - (d_taps_per_filter)*sizeof(gr_complex)); - } - */ - return noutput_items; } diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h index 27c8c2c50..f5b1cbb94 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h @@ -32,7 +32,6 @@ typedef boost::shared_ptr gr_pfb_synthesis_filt gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf (unsigned int numchans, const std::vector &taps); -class gr_fir_ccf; class gri_fft_complex; @@ -62,7 +61,6 @@ class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator unsigned int d_numchans; unsigned int d_taps_per_filter; gri_fft_complex *d_fft; - //gr_complex **d_buffer; std::vector< gri_fir_filter_with_buffer_ccf*> d_filters; std::vector< std::vector > d_taps; -- cgit From 62042813aeeffeeb6091e229761c5068b5ed5cde Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 16 Oct 2010 14:37:55 -0400 Subject: Adding QA code for fir filter with buffer. --- gnuradio-core/src/lib/filter/Makefile.am | 6 +- gnuradio-core/src/lib/filter/qa_filter.cc | 2 + .../filter/qa_gri_fir_filter_with_buffer_ccf.cc | 148 +++++++++++++++++++++ .../lib/filter/qa_gri_fir_filter_with_buffer_ccf.h | 43 ++++++ 4 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 5c7473d06..ff6c546fd 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -222,7 +222,8 @@ libfilter_qa_la_common_SOURCES = \ qa_gr_fir_scc.cc \ qa_gr_rotator.cc \ qa_gri_mmse_fir_interpolator.cc \ - qa_gri_mmse_fir_interpolator_cc.cc + qa_gri_mmse_fir_interpolator_cc.cc \ + qa_gri_fir_filter_with_buffer_ccf.cc if MD_CPU_generic libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(generic_CODE) @@ -328,7 +329,8 @@ noinst_HEADERS = \ qa_gr_fir_scc.h \ qa_gr_rotator.h \ qa_gri_mmse_fir_interpolator.h \ - qa_gri_mmse_fir_interpolator_cc.h + qa_gri_mmse_fir_interpolator_cc.h \ + qa_gri_fir_filter_with_buffer_ccf.h if PYTHON diff --git a/gnuradio-core/src/lib/filter/qa_filter.cc b/gnuradio-core/src/lib/filter/qa_filter.cc index 878d48023..b9a30ba42 100644 --- a/gnuradio-core/src/lib/filter/qa_filter.cc +++ b/gnuradio-core/src/lib/filter/qa_filter.cc @@ -36,6 +36,7 @@ #include #include #include +#include CppUnit::TestSuite * qa_filter::suite () @@ -51,6 +52,7 @@ qa_filter::suite () s->addTest (qa_gri_mmse_fir_interpolator::suite ()); s->addTest (qa_gri_mmse_fir_interpolator_cc::suite ()); s->addTest (qa_gr_rotator::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_ccf::suite ()); return s; } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc new file mode 100644 index 000000000..f2e09db1c --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef float tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +void +qa_gri_fir_filter_with_buffer_ccf::t1 () +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_complex (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < ol; o++){ + // use an actual delay line for this test + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[o]; + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_ccf *f1 = new gri_fir_filter_with_buffer_ccf(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h new file mode 100644 index 000000000..b80be70a7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _QA_GRI_FIR_FILTER_WITH_BUFFER_CCF_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_CCF_H_ + +#include +#include + +class qa_gri_fir_filter_with_buffer_ccf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccf); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_CCF_H_ */ -- cgit From eb7316ea486ab774c24cba1142a785080559e579 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 16 Oct 2010 18:28:53 -0400 Subject: Using generators to make gri_fir_filter_with_buffer_XXX into all possible in/out/tap types we support. --- gnuradio-core/src/lib/filter/.gitignore | 10 ++ gnuradio-core/src/lib/filter/Makefile.am | 7 +- gnuradio-core/src/lib/filter/Makefile.gen | 17 ++- gnuradio-core/src/lib/filter/generate_all.py | 2 + .../generate_gri_fir_filter_with_buffer_XXX.py | 53 ++++++++ .../lib/filter/gri_fir_filter_with_buffer_XXX.cc.t | 88 ++++++++++++++ .../lib/filter/gri_fir_filter_with_buffer_XXX.h.t | 119 ++++++++++++++++++ .../lib/filter/gri_fir_filter_with_buffer_ccf.cc | 71 ----------- .../lib/filter/gri_fir_filter_with_buffer_ccf.h | 133 --------------------- 9 files changed, 293 insertions(+), 207 deletions(-) create mode 100755 gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py create mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t create mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t delete mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc delete mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/.gitignore b/gnuradio-core/src/lib/filter/.gitignore index 2d009f154..4797b6b3a 100644 --- a/gnuradio-core/src/lib/filter/.gitignore +++ b/gnuradio-core/src/lib/filter/.gitignore @@ -211,4 +211,14 @@ /gr_rational_resampler_base_scc.cc /gr_rational_resampler_base_scc.h /gr_rational_resampler_base_scc.i +/gri_fir_filter_with_buffer_ccc.cc +/gri_fir_filter_with_buffer_ccc.h +/gri_fir_filter_with_buffer_fcc.cc +/gri_fir_filter_with_buffer_fcc.h +/gri_fir_filter_with_buffer_fff.cc +/gri_fir_filter_with_buffer_fff.h +/gri_fir_filter_with_buffer_fsf.cc +/gri_fir_filter_with_buffer_fsf.h +/gri_fir_filter_with_buffer_scc.cc +/gri_fir_filter_with_buffer_scc.h /stamp-* diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index ff6c546fd..31f919ba7 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -44,6 +44,7 @@ code_generator = \ generate_gr_fir_sysconfig_generic.py \ generate_gr_fir_util.py \ generate_gr_freq_xlating_fir_filter_XXX.py \ + generate_gri_fir_filter_with_buffer_XXX.py \ generate_utils.py \ gr_fir_XXX.cc.t \ gr_fir_XXX.h.t \ @@ -60,7 +61,11 @@ code_generator = \ gr_rational_resampler_base_XXX.i.t \ gr_freq_xlating_fir_filter_XXX.cc.t \ gr_freq_xlating_fir_filter_XXX.h.t \ - gr_freq_xlating_fir_filter_XXX.i.t + gr_freq_xlating_fir_filter_XXX.i.t \ + gri_fir_filter_with_buffer_XXX.cc.t \ + gri_fir_filter_with_buffer_XXX.h.t \ + gri_fir_filter_with_buffer_XXX.i.t + # Source built by Python into $(builddir) BUILT_SOURCES = \ diff --git a/gnuradio-core/src/lib/filter/Makefile.gen b/gnuradio-core/src/lib/filter/Makefile.gen index 6809274fa..909899c05 100644 --- a/gnuradio-core/src/lib/filter/Makefile.gen +++ b/gnuradio-core/src/lib/filter/Makefile.gen @@ -40,7 +40,14 @@ GENERATED_H = \ gr_rational_resampler_base_fcc.h \ gr_rational_resampler_base_fff.h \ gr_rational_resampler_base_fsf.h \ - gr_rational_resampler_base_scc.h + gr_rational_resampler_base_scc.h \ + gri_fir_filter_with_buffer_ccc.h \ + gri_fir_filter_with_buffer_ccf.h \ + gri_fir_filter_with_buffer_fcc.h \ + gri_fir_filter_with_buffer_fff.h \ + gri_fir_filter_with_buffer_fsf.h \ + gri_fir_filter_with_buffer_scc.h + GENERATED_I = \ gr_fir_filter_ccc.i \ @@ -107,5 +114,11 @@ GENERATED_CC = \ gr_rational_resampler_base_fcc.cc \ gr_rational_resampler_base_fff.cc \ gr_rational_resampler_base_fsf.cc \ - gr_rational_resampler_base_scc.cc + gr_rational_resampler_base_scc.cc \ + gri_fir_filter_with_buffer_ccc.cc \ + gri_fir_filter_with_buffer_ccf.cc \ + gri_fir_filter_with_buffer_fcc.cc \ + gri_fir_filter_with_buffer_fff.cc \ + gri_fir_filter_with_buffer_fsf.cc \ + gri_fir_filter_with_buffer_scc.cc diff --git a/gnuradio-core/src/lib/filter/generate_all.py b/gnuradio-core/src/lib/filter/generate_all.py index b34e13c73..ceed2b851 100755 --- a/gnuradio-core/src/lib/filter/generate_all.py +++ b/gnuradio-core/src/lib/filter/generate_all.py @@ -30,6 +30,7 @@ import generate_gr_fir_sysconfig_generic import generate_gr_fir_sysconfig import generate_gr_fir_util import generate_gr_fir_XXX +import generate_gri_fir_filter_with_buffer_XXX def generate_all(): generate_gr_fir_XXX.generate() @@ -40,6 +41,7 @@ def generate_all(): generate_gr_fir_sysconfig_generic.generate() generate_gr_fir_sysconfig.generate() generate_gr_fir_util.generate() + generate_gri_fir_filter_with_buffer_XXX.generate() output_glue('filter') if __name__ == '__main__': diff --git a/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py new file mode 100755 index 000000000..7252e26f7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- python -*- +# +# Copyright 2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import re +from generate_utils import * + +roots = ['gri_fir_filter_with_buffer_XXX',] + +def code3_to_input_cast (code3): + if i_code (code3) == 's' and o_code (code3) == 'c': + return '(float)' + return '' + +def expand_h_cc (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['INPUT_CAST'] = code3_to_input_cast (code3) + return d + + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc (r, s) + + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t new file mode 100644 index 000000000..dd71a55fa --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include <@NAME@.h> + +@NAME@::@NAME@(const std::vector<@TAP_TYPE@> &taps) +{ + d_buffer = NULL; + set_taps(taps); +} + +@NAME@::~@NAME@() +{ + if(d_buffer != NULL) + free(d_buffer); +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_taps = gr_reverse(taps); + + if(d_buffer != NULL) { + free(d_buffer); + d_buffer = NULL; + } + + // FIXME: memalign this to 16-byte boundaries for SIMD later + size_t t = sizeof(@I_TYPE@) * 2 * d_taps.size(); + d_buffer = (@I_TYPE@*)malloc(t); + memset(d_buffer, 0x00, t); + d_idx = 0; +} + +@O_TYPE@ +@NAME@::filter (@I_TYPE@ input) +{ + unsigned int i; + + d_buffer[d_idx] = input; + d_buffer[d_idx+ntaps()] = input; + + // using the later for the case when ntaps=0; + // profiling shows this doesn't make a difference + //d_idx = (d_idx + 1) % ntaps(); + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + + @O_TYPE@ out = 0; + for(i = 0; i < ntaps(); i++) { + out += @INPUT_CAST@ d_buffer[d_idx + i] * d_taps[i]; + } + return out; +} + +void +@NAME@::filterN (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n) +{ + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(input[i]); + } +} diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t new file mode 100644 index 000000000..d566b3674 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t @@ -0,0 +1,119 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gri_fir_XXX.py + * Any changes made to this file will be overwritten. + */ + + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include +#include +#include +#include +#include + +/*! + * \brief FIR with internal buffer for @I_TYPE@ input, + @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter + * + */ + +class @NAME@ { + +protected: + std::vector<@TAP_TYPE@> d_taps; // reversed taps + @I_TYPE@ *d_buffer; + unsigned int d_idx; + +public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + @NAME@ (const std::vector<@TAP_TYPE@> &taps); + + ~@NAME@ (); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \returns the filtered input value. + */ + @O_TYPE@ filter (@I_TYPE@ input); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + void filterN (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n, unsigned decimate); + + /*! + * \brief install \p new_taps as the current taps. + */ + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned ntaps () const { return d_taps.size (); } + + /*! + * \return current taps + */ + const std::vector<@TAP_TYPE@> get_taps () const + { + return gr_reverse(d_taps); + } +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc deleted file mode 100644 index 55e316d02..000000000 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -gri_fir_filter_with_buffer_ccf::gri_fir_filter_with_buffer_ccf(const std::vector &taps) -{ - d_buffer = NULL; - set_taps(taps); -} - -gri_fir_filter_with_buffer_ccf::~gri_fir_filter_with_buffer_ccf() -{ - if(d_buffer != NULL) - free(d_buffer); -} - -gr_complex -gri_fir_filter_with_buffer_ccf::filter (gr_complex input) -{ - unsigned int i; - - d_buffer[d_idx] = input; - d_buffer[d_idx+ntaps()] = input; - - // using the later for the case when ntaps=0; - // profiling shows this doesn't make a difference - //d_idx = (d_idx + 1) % ntaps(); - d_idx++; - if(d_idx >= ntaps()) - d_idx = 0; - - gr_complex out = gr_complex(0,0); - for(i = 0; i < ntaps(); i++) { - out += d_buffer[d_idx + i]*d_taps[i]; - } - return out; -} - -void -gri_fir_filter_with_buffer_ccf::filterN (gr_complex output[], - const gr_complex input[], - unsigned long n) -{ - for(unsigned long i = 0; i < n; i++) { - output[i] = filter(input[i]); - } -} diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h deleted file mode 100644 index c91d70534..000000000 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * WARNING: This file is automatically generated by generate_gr_fir_XXX.py - * Any changes made to this file will be overwritten. - */ - - -#ifndef INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_H -#define INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_H - -#include -#include -#include -#include -#include - -/*! - * \brief FIR with internal buffer for gr_complex input, - gr_complex output and float taps - * \ingroup filter - * - */ - -class gri_fir_filter_with_buffer_ccf { - -protected: - std::vector d_taps; // reversed taps - gr_complex *d_buffer; - unsigned int d_idx; - -public: - - // CONSTRUCTORS - - /*! - * \brief construct new FIR with given taps. - * - * Note that taps must be in forward order, e.g., coefficient 0 is - * stored in new_taps[0], coefficient 1 is stored in - * new_taps[1], etc. - */ - gri_fir_filter_with_buffer_ccf (const std::vector &taps); - - ~gri_fir_filter_with_buffer_ccf (); - - // MANIPULATORS - - /*! - * \brief compute a single output value. - * - * \p input must have ntaps() valid entries. - * input[0] .. input[ntaps() - 1] are referenced to compute the output value. - * - * \returns the filtered input value. - */ - gr_complex filter (gr_complex input); - - /*! - * \brief compute an array of N output values. - * - * \p input must have (n - 1 + ntaps()) valid entries. - * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. - */ - void filterN (gr_complex output[], const gr_complex input[], - unsigned long n); - - /*! - * \brief compute an array of N output values, decimating the input - * - * \p input must have (decimate * (n - 1) + ntaps()) valid entries. - * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to - * compute the output values. - */ - void filterNdec (gr_complex output[], const gr_complex input[], - unsigned long n, unsigned decimate); - - /*! - * \brief install \p new_taps as the current taps. - */ - void set_taps (const std::vector &taps) - { - d_taps = gr_reverse(taps); - - if(d_buffer != NULL) { - free(d_buffer); - d_buffer = NULL; - } - - // FIXME: memalign this to 16-byte boundaries for SIMD later - size_t t = sizeof(gr_complex) * 2 * d_taps.size(); - d_buffer = (gr_complex*)malloc(t); - memset(d_buffer, 0x00, t); - d_idx = 0; - } - - // ACCESSORS - - /*! - * \return number of taps in filter. - */ - unsigned ntaps () const { return d_taps.size (); } - - /*! - * \return current taps - */ - const std::vector get_taps () const - { - return gr_reverse(d_taps); - } -}; - -#endif /* INCLUDED_GR_GR_FIR_FILTER_WITH_BUFFER_CCF_H */ -- cgit From 4a3fb7eb7481177ae35bb98307a1845a7304d97e Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sat, 16 Oct 2010 19:42:58 -0400 Subject: Fixes Makefile for fir filter generators. Adding new QA code for all other fir filters. fff and fsf versions currently failing. --- gnuradio-core/src/lib/filter/Makefile.am | 16 ++- .../lib/filter/gri_fir_filter_with_buffer_ccf.cc | 88 ++++++++++++ .../lib/filter/gri_fir_filter_with_buffer_ccf.h | 119 +++++++++++++++++ gnuradio-core/src/lib/filter/qa_filter.cc | 10 ++ .../filter/qa_gri_fir_filter_with_buffer_ccc.cc | 141 ++++++++++++++++++++ .../lib/filter/qa_gri_fir_filter_with_buffer_ccc.h | 43 ++++++ .../filter/qa_gri_fir_filter_with_buffer_fcc.cc | 148 +++++++++++++++++++++ .../lib/filter/qa_gri_fir_filter_with_buffer_fcc.h | 43 ++++++ .../filter/qa_gri_fir_filter_with_buffer_fff.cc | 138 +++++++++++++++++++ .../lib/filter/qa_gri_fir_filter_with_buffer_fff.h | 43 ++++++ .../filter/qa_gri_fir_filter_with_buffer_fsf.cc | 138 +++++++++++++++++++ .../lib/filter/qa_gri_fir_filter_with_buffer_fsf.h | 43 ++++++ .../filter/qa_gri_fir_filter_with_buffer_scc.cc | 148 +++++++++++++++++++++ .../lib/filter/qa_gri_fir_filter_with_buffer_scc.h | 43 ++++++ 14 files changed, 1157 insertions(+), 4 deletions(-) create mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc create mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 31f919ba7..cfd653581 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -195,7 +195,6 @@ libfilter_la_common_SOURCES = \ gr_fft_filter_fff.cc \ gr_goertzel_fc.cc \ gr_filter_delay_fc.cc \ - gri_fir_filter_with_buffer_ccf.cc \ gr_fractional_interpolator_ff.cc \ gr_fractional_interpolator_cc.cc \ gr_hilbert_fc.cc \ @@ -228,7 +227,12 @@ libfilter_qa_la_common_SOURCES = \ qa_gr_rotator.cc \ qa_gri_mmse_fir_interpolator.cc \ qa_gri_mmse_fir_interpolator_cc.cc \ - qa_gri_fir_filter_with_buffer_ccf.cc + qa_gri_fir_filter_with_buffer_ccf.cc \ + qa_gri_fir_filter_with_buffer_ccc.cc \ + qa_gri_fir_filter_with_buffer_fcc.cc \ + qa_gri_fir_filter_with_buffer_fff.cc \ + qa_gri_fir_filter_with_buffer_fsf.cc \ + qa_gri_fir_filter_with_buffer_scc.cc if MD_CPU_generic libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(generic_CODE) @@ -274,7 +278,6 @@ grinclude_HEADERS = \ gr_fft_filter_ccc.h \ gr_fft_filter_fff.h \ gr_filter_delay_fc.h \ - gri_fir_filter_with_buffer_ccf.h \ gr_fir_sysconfig_x86.h \ gr_fir_sysconfig_powerpc.h \ gr_fractional_interpolator_ff.h \ @@ -335,7 +338,12 @@ noinst_HEADERS = \ qa_gr_rotator.h \ qa_gri_mmse_fir_interpolator.h \ qa_gri_mmse_fir_interpolator_cc.h \ - qa_gri_fir_filter_with_buffer_ccf.h + qa_gri_fir_filter_with_buffer_ccf.h \ + qa_gri_fir_filter_with_buffer_ccc.h \ + qa_gri_fir_filter_with_buffer_fcc.h \ + qa_gri_fir_filter_with_buffer_fff.h \ + qa_gri_fir_filter_with_buffer_fsf.h \ + qa_gri_fir_filter_with_buffer_scc.h if PYTHON diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc new file mode 100644 index 000000000..35020bb78 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +gri_fir_filter_with_buffer_ccf::gri_fir_filter_with_buffer_ccf(const std::vector &taps) +{ + d_buffer = NULL; + set_taps(taps); +} + +gri_fir_filter_with_buffer_ccf::~gri_fir_filter_with_buffer_ccf() +{ + if(d_buffer != NULL) + free(d_buffer); +} + +void +gri_fir_filter_with_buffer_ccf::set_taps (const std::vector &taps) +{ + d_taps = gr_reverse(taps); + + if(d_buffer != NULL) { + free(d_buffer); + d_buffer = NULL; + } + + // FIXME: memalign this to 16-byte boundaries for SIMD later + size_t t = sizeof(gr_complex) * 2 * d_taps.size(); + d_buffer = (gr_complex*)malloc(t); + memset(d_buffer, 0x00, t); + d_idx = 0; +} + +gr_complex +gri_fir_filter_with_buffer_ccf::filter (gr_complex input) +{ + unsigned int i; + + d_buffer[d_idx] = input; + d_buffer[d_idx+ntaps()] = input; + + // using the later for the case when ntaps=0; + // profiling shows this doesn't make a difference + //d_idx = (d_idx + 1) % ntaps(); + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + + gr_complex out = 0; + for(i = 0; i < ntaps(); i++) { + out += d_buffer[d_idx + i] * d_taps[i]; + } + return out; +} + +void +gri_fir_filter_with_buffer_ccf::filterN (gr_complex output[], + const gr_complex input[], + unsigned long n) +{ + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(input[i]); + } +} diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h new file mode 100644 index 000000000..2b69f8b03 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h @@ -0,0 +1,119 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * WARNING: This file is automatically generated by generate_gri_fir_XXX.py + * Any changes made to this file will be overwritten. + */ + + +#ifndef INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_CCF_H +#define INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_CCF_H + +#include +#include +#include +#include +#include + +/*! + * \brief FIR with internal buffer for gr_complex input, + gr_complex output and float taps + * \ingroup filter + * + */ + +class gri_fir_filter_with_buffer_ccf { + +protected: + std::vector d_taps; // reversed taps + gr_complex *d_buffer; + unsigned int d_idx; + +public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + gri_fir_filter_with_buffer_ccf (const std::vector &taps); + + ~gri_fir_filter_with_buffer_ccf (); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \returns the filtered input value. + */ + gr_complex filter (gr_complex input); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + void filterN (gr_complex output[], const gr_complex input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + void filterNdec (gr_complex output[], const gr_complex input[], + unsigned long n, unsigned decimate); + + /*! + * \brief install \p new_taps as the current taps. + */ + void set_taps (const std::vector &taps); + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned ntaps () const { return d_taps.size (); } + + /*! + * \return current taps + */ + const std::vector get_taps () const + { + return gr_reverse(d_taps); + } +}; + +#endif /* INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_CCF_H */ diff --git a/gnuradio-core/src/lib/filter/qa_filter.cc b/gnuradio-core/src/lib/filter/qa_filter.cc index b9a30ba42..0d03cb0ee 100644 --- a/gnuradio-core/src/lib/filter/qa_filter.cc +++ b/gnuradio-core/src/lib/filter/qa_filter.cc @@ -37,6 +37,11 @@ #include #include #include +#include +#include +#include +#include +#include CppUnit::TestSuite * qa_filter::suite () @@ -53,6 +58,11 @@ qa_filter::suite () s->addTest (qa_gri_mmse_fir_interpolator_cc::suite ()); s->addTest (qa_gr_rotator::suite ()); s->addTest (qa_gri_fir_filter_with_buffer_ccf::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_ccc::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_fcc::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_fff::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_fsf::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_scc::suite ()); return s; } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc new file mode 100644 index 000000000..cff81ab13 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc @@ -0,0 +1,141 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +void +qa_gri_fir_filter_with_buffer_ccc::t1 () +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_complex (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < ol; o++){ + // use an actual delay line for this test + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[o]; + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_ccc *f1 = new gri_fir_filter_with_buffer_ccc(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h new file mode 100644 index 000000000..411a66a9a --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _QA_GRI_FIR_FILTER_WITH_BUFFER_CCC_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_CCC_H_ + +#include +#include + +class qa_gri_fir_filter_with_buffer_ccc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_CCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc new file mode 100644 index 000000000..de0da9f1c --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef float i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +void +qa_gri_fir_filter_with_buffer_fcc::t1 () +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < ol; o++){ + // use an actual delay line for this test + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[o]; + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_fcc *f1 = new gri_fir_filter_with_buffer_fcc(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h new file mode 100644 index 000000000..81b39f488 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _QA_GRI_FIR_FILTER_WITH_BUFFER_FCC_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FCC_H_ + +#include +#include + +class qa_gri_fir_filter_with_buffer_fcc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fcc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc new file mode 100644 index 000000000..518d98ab8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc @@ -0,0 +1,138 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef float i_type; +typedef float o_type; +typedef float tap_type; +typedef float acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +void +qa_gri_fir_filter_with_buffer_fff::t1 () +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < ol; o++){ + // use an actual delay line for this test + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[o]; + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_fff *f1 = new gri_fir_filter_with_buffer_fff(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h new file mode 100644 index 000000000..5bb6c3e93 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _QA_GRI_FIR_FILTER_WITH_BUFFER_FFF_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FFF_H_ + +#include +#include + +class qa_gri_fir_filter_with_buffer_fff : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fff); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FFF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc new file mode 100644 index 000000000..1dc869ef7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc @@ -0,0 +1,138 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef float i_type; +typedef short o_type; +typedef float tap_type; +typedef int acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +void +qa_gri_fir_filter_with_buffer_fsf::t1 () +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < ol; o++){ + // use an actual delay line for this test + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[o]; + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_fsf *f1 = new gri_fir_filter_with_buffer_fsf(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h new file mode 100644 index 000000000..38899b352 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _QA_GRI_FIR_FILTER_WITH_BUFFER_FSF_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FSF_H_ + +#include +#include + +class qa_gri_fir_filter_with_buffer_fsf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fsf); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FSF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc new file mode 100644 index 000000000..4ba433ebf --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef short i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_shorts (short *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (short) rint (uniform () * 16384); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += (float)input[i] * taps[i]; + } + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +void +qa_gri_fir_filter_with_buffer_scc::t1 () +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_shorts (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < ol; o++){ + // use an actual delay line for this test + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[o]; + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_scc *f1 = new gri_fir_filter_with_buffer_scc(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h new file mode 100644 index 000000000..fd9fe5b76 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _QA_GRI_FIR_FILTER_WITH_BUFFER_SCC_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_SCC_H_ + +#include +#include + +class qa_gri_fir_filter_with_buffer_scc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_scc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_SCC_H_ */ -- cgit From b9cbe9c9ca65b620cab9bf1b8e652637a885d3c2 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 17 Oct 2010 15:25:11 -0400 Subject: Fixing up filters a bit to pass QA tests for all versions. --- .../filter/generate_gri_fir_filter_with_buffer_XXX.py | 11 +++++++++++ .../src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t | 4 ++-- .../src/lib/filter/gri_fir_filter_with_buffer_ccf.cc | 2 +- .../lib/filter/qa_gri_fir_filter_with_buffer_fff.cc | 3 +-- .../lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc | 18 ++++-------------- 5 files changed, 19 insertions(+), 19 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py index 7252e26f7..f586b0c27 100755 --- a/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py +++ b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py @@ -26,6 +26,15 @@ from generate_utils import * roots = ['gri_fir_filter_with_buffer_XXX',] +def code3_to_acc_code (code3): + if i_code (code3) == 'c' or o_code (code3) == 'c' or tap_code (code3) == 'c': + return 'c' + if i_code (code3) == 'f' or o_code (code3) == 'f' or tap_code (code3) == 'f': + return 'f' + if i_code (code3) == 'i' or o_code (code3) == 'i' or tap_code (code3) == 'i': + return 'i' + return 'i' # even short short short needs int accumulator + def code3_to_input_cast (code3): if i_code (code3) == 's' and o_code (code3) == 'c': return '(float)' @@ -40,6 +49,8 @@ def init_dict (root, code3): name = re.sub ('X+', code3, root) d = standard_dict (name, code3) d['INPUT_CAST'] = code3_to_input_cast (code3) + acc_code = code3_to_acc_code (code3) + d['ACC_TYPE'] = char_to_type[acc_code] return d diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t index dd71a55fa..c0d061c81 100644 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t @@ -70,11 +70,11 @@ void if(d_idx >= ntaps()) d_idx = 0; - @O_TYPE@ out = 0; + @ACC_TYPE@ out = 0; for(i = 0; i < ntaps(); i++) { out += @INPUT_CAST@ d_buffer[d_idx + i] * d_taps[i]; } - return out; + return (@O_TYPE@)out; } void diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc index 35020bb78..b2db8ce0a 100644 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc @@ -74,7 +74,7 @@ gri_fir_filter_with_buffer_ccf::filter (gr_complex input) for(i = 0; i < ntaps(); i++) { out += d_buffer[d_idx + i] * d_taps[i]; } - return out; + return (gr_complex)out; } void diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc index 518d98ab8..ce689a54b 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc @@ -66,7 +66,6 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) for (int i = 0; i < ntaps; i++) { sum += input[i] * taps[i]; } - return sum; } @@ -129,7 +128,7 @@ qa_gri_fir_filter_with_buffer_fff::t1 () for (int o = 0; o < ol; o++){ CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o], - abs (expected_output[o]) * ERR_DELTA); + fabsf (expected_output[o]) * ERR_DELTA); } delete f1; } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc index 1dc869ef7..f09a1d7ac 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc @@ -38,12 +38,10 @@ typedef float i_type; typedef short o_type; typedef float tap_type; -typedef int acc_type; +typedef float acc_type; using std::vector; -#define ERR_DELTA (1e-5) - #define NELEM(x) (sizeof (x) / sizeof (x[0])) static float @@ -56,7 +54,7 @@ static void random_floats (float *buf, unsigned n) { for (unsigned i = 0; i < n; i++) - buf[i] = (float) rint (uniform () * 32767); + buf[i] = (float) rint (uniform () * 128); } static o_type @@ -66,8 +64,7 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) for (int i = 0; i < ntaps; i++) { sum += input[i] * taps[i]; } - - return sum; + return (o_type)sum; } // @@ -121,15 +118,8 @@ qa_gri_fir_filter_with_buffer_fsf::t1 () f1->filterN (actual_output, input, ol); // check results - // - // we use a sloppy error margin because on the x86 architecture, - // our reference implementation is using 80 bit floating point - // arithmetic, while the SSE version is using 32 bit float point - // arithmetic. - for (int o = 0; o < ol; o++){ - CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o], - abs (expected_output[o]) * ERR_DELTA); + CPPUNIT_ASSERT_EQUAL(expected_output[o], actual_output[o]); } delete f1; } -- cgit From 740d8974427d25f1bd4e4e045fc6f0a101cea9eb Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 17 Oct 2010 15:25:44 -0400 Subject: Removing ccf version of filter that is now autogenerated. --- .../lib/filter/gri_fir_filter_with_buffer_ccf.cc | 88 ---------------------- 1 file changed, 88 deletions(-) delete mode 100644 gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc deleted file mode 100644 index b2db8ce0a..000000000 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -gri_fir_filter_with_buffer_ccf::gri_fir_filter_with_buffer_ccf(const std::vector &taps) -{ - d_buffer = NULL; - set_taps(taps); -} - -gri_fir_filter_with_buffer_ccf::~gri_fir_filter_with_buffer_ccf() -{ - if(d_buffer != NULL) - free(d_buffer); -} - -void -gri_fir_filter_with_buffer_ccf::set_taps (const std::vector &taps) -{ - d_taps = gr_reverse(taps); - - if(d_buffer != NULL) { - free(d_buffer); - d_buffer = NULL; - } - - // FIXME: memalign this to 16-byte boundaries for SIMD later - size_t t = sizeof(gr_complex) * 2 * d_taps.size(); - d_buffer = (gr_complex*)malloc(t); - memset(d_buffer, 0x00, t); - d_idx = 0; -} - -gr_complex -gri_fir_filter_with_buffer_ccf::filter (gr_complex input) -{ - unsigned int i; - - d_buffer[d_idx] = input; - d_buffer[d_idx+ntaps()] = input; - - // using the later for the case when ntaps=0; - // profiling shows this doesn't make a difference - //d_idx = (d_idx + 1) % ntaps(); - d_idx++; - if(d_idx >= ntaps()) - d_idx = 0; - - gr_complex out = 0; - for(i = 0; i < ntaps(); i++) { - out += d_buffer[d_idx + i] * d_taps[i]; - } - return (gr_complex)out; -} - -void -gri_fir_filter_with_buffer_ccf::filterN (gr_complex output[], - const gr_complex input[], - unsigned long n) -{ - for(unsigned long i = 0; i < n; i++) { - output[i] = filter(input[i]); - } -} -- cgit From 9810ae784492ca23cce40cdd0cc3ca83eb5f5aef Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 17 Oct 2010 15:51:06 -0400 Subject: Removing nonexistent gri .i file from Makefile. Got a bit carried away with the copy/paste. --- gnuradio-core/src/lib/filter/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index cfd653581..6d2ec1c7e 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -63,8 +63,7 @@ code_generator = \ gr_freq_xlating_fir_filter_XXX.h.t \ gr_freq_xlating_fir_filter_XXX.i.t \ gri_fir_filter_with_buffer_XXX.cc.t \ - gri_fir_filter_with_buffer_XXX.h.t \ - gri_fir_filter_with_buffer_XXX.i.t + gri_fir_filter_with_buffer_XXX.h.t # Source built by Python into $(builddir) -- cgit From b03f921273423dddc5c8b76d6ab0cfcfe80123a3 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 17 Oct 2010 16:14:09 -0400 Subject: Adding ccf version of fir filter to gitignore. --- gnuradio-core/src/lib/filter/.gitignore | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/.gitignore b/gnuradio-core/src/lib/filter/.gitignore index 4797b6b3a..faaf02cb8 100644 --- a/gnuradio-core/src/lib/filter/.gitignore +++ b/gnuradio-core/src/lib/filter/.gitignore @@ -213,6 +213,8 @@ /gr_rational_resampler_base_scc.i /gri_fir_filter_with_buffer_ccc.cc /gri_fir_filter_with_buffer_ccc.h +/gri_fir_filter_with_buffer_ccf.cc +/gri_fir_filter_with_buffer_ccf.h /gri_fir_filter_with_buffer_fcc.cc /gri_fir_filter_with_buffer_fcc.h /gri_fir_filter_with_buffer_fff.cc -- cgit From 1d63a52520ebdac7242784eafa79093b7fc2710d Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 2 Nov 2010 12:47:46 -0400 Subject: Adding ability for FIR filter with internal buffer to decimate. Also adds QA code to test decimate by 2 and 5. Removes lib/filter/gri_fir_filter_with_buffer_ccf.h that is autogenerated. --- .../lib/filter/gri_fir_filter_with_buffer_XXX.cc.t | 33 ++++++++++++++++++++ .../lib/filter/gri_fir_filter_with_buffer_XXX.h.t | 18 +++++++++-- .../lib/filter/gri_fir_filter_with_buffer_ccf.h | 18 +++++++++-- .../filter/qa_gri_fir_filter_with_buffer_ccc.cc | 35 ++++++++++++++++----- .../lib/filter/qa_gri_fir_filter_with_buffer_ccc.h | 7 +++-- .../filter/qa_gri_fir_filter_with_buffer_ccf.cc | 35 ++++++++++++++++----- .../lib/filter/qa_gri_fir_filter_with_buffer_ccf.h | 7 +++-- .../filter/qa_gri_fir_filter_with_buffer_fcc.cc | 36 +++++++++++++++++----- .../lib/filter/qa_gri_fir_filter_with_buffer_fcc.h | 7 +++-- .../filter/qa_gri_fir_filter_with_buffer_fff.cc | 35 ++++++++++++++++----- .../lib/filter/qa_gri_fir_filter_with_buffer_fff.h | 7 +++-- .../filter/qa_gri_fir_filter_with_buffer_fsf.cc | 35 ++++++++++++++++----- .../lib/filter/qa_gri_fir_filter_with_buffer_fsf.h | 9 ++++-- .../filter/qa_gri_fir_filter_with_buffer_scc.cc | 35 ++++++++++++++++----- .../lib/filter/qa_gri_fir_filter_with_buffer_scc.h | 7 +++-- 15 files changed, 257 insertions(+), 67 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t index c0d061c81..154068840 100644 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t @@ -77,6 +77,26 @@ void return (@O_TYPE@)out; } +@O_TYPE@ +@NAME@::filter (const @I_TYPE@ input[], unsigned long dec) +{ + unsigned int i; + + for(i = 0; i < dec; i++) { + d_buffer[d_idx] = input[i]; + d_buffer[d_idx+ntaps()] = input[i]; + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + } + + @ACC_TYPE@ out = 0; + for(i = 0; i < ntaps(); i++) { + out += @INPUT_CAST@ d_buffer[d_idx + i] * d_taps[i]; + } + return (@O_TYPE@)out; +} + void @NAME@::filterN (@O_TYPE@ output[], const @I_TYPE@ input[], @@ -86,3 +106,16 @@ void output[i] = filter(input[i]); } } + +void +@NAME@::filterNdec (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n, + unsigned long decimate) +{ + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(&input[j], decimate); + j += decimate; + } +} diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t index d566b3674..23d64b65d 100644 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t @@ -69,13 +69,25 @@ public: /*! * \brief compute a single output value. * - * \p input must have ntaps() valid entries. - * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * \p input is a single input value of the filter type * * \returns the filtered input value. */ @O_TYPE@ filter (@I_TYPE@ input); + + /*! + * \brief compute a single output value; designed for decimating filters. + * + * \p input is a single input value of the filter type. The value of dec is the + * decimating value of the filter, so input[] must have dec valid values. + * The filter pushes dec number of items onto the circ. buffer before computing + * a single output. + * + * \returns the filtered input value. + */ + @O_TYPE@ filter (const @I_TYPE@ input[], unsigned long dec); + /*! * \brief compute an array of N output values. * @@ -93,7 +105,7 @@ public: * compute the output values. */ void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[], - unsigned long n, unsigned decimate); + unsigned long n, unsigned long decimate); /*! * \brief install \p new_taps as the current taps. diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h index 2b69f8b03..bd7fa33cf 100644 --- a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h @@ -69,13 +69,25 @@ public: /*! * \brief compute a single output value. * - * \p input must have ntaps() valid entries. - * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * \p input is a single input value of the filter type * * \returns the filtered input value. */ gr_complex filter (gr_complex input); + + /*! + * \brief compute a single output value; designed for decimating filters. + * + * \p input is a single input value of the filter type. The value of dec is the + * decimating value of the filter, so input[] must have dec valid values. + * The filter pushes dec number of items onto the circ. buffer before computing + * a single output. + * + * \returns the filtered input value. + */ + gr_complex filter (const gr_complex input[], unsigned long dec); + /*! * \brief compute an array of N output values. * @@ -93,7 +105,7 @@ public: * compute the output values. */ void filterNdec (gr_complex output[], const gr_complex input[], - unsigned long n, unsigned decimate); + unsigned long n, unsigned long decimate); /*! * \brief install \p new_taps as the current taps. diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc index cff81ab13..e87d93ebf 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc @@ -73,14 +73,31 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) return sum; } +void +qa_gri_fir_filter_with_buffer_ccc::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_ccc::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_ccc::t3 () +{ + test_decimate(5); +} + // // Test for ntaps in [0,9], and input lengths in [0,17]. // This ensures that we are building the shifted taps correctly, // and exercises all corner cases on input alignment and length. // - void -qa_gri_fir_filter_with_buffer_ccc::t1 () +qa_gri_fir_filter_with_buffer_ccc::test_decimate(unsigned int decimate) { const int MAX_TAPS = 9; const int OUTPUT_LEN = 17; @@ -107,11 +124,13 @@ qa_gri_fir_filter_with_buffer_ccc::t1 () // compute expected output values memset(dline, 0, INPUT_LEN*sizeof(i_type)); - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ // use an actual delay line for this test - for(int oo = INPUT_LEN-1; oo > 0; oo--) - dline[oo] = dline[oo-1]; - dline[0] = input[o]; + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } expected_output[o] = ref_dotprod (dline, taps, n); } @@ -121,7 +140,7 @@ qa_gri_fir_filter_with_buffer_ccc::t1 () // zero the output, then do the filtering memset (actual_output, 0, sizeof (actual_output)); - f1->filterN (actual_output, input, ol); + f1->filterNdec (actual_output, input, ol/decimate, decimate); // check results // @@ -130,7 +149,7 @@ qa_gri_fir_filter_with_buffer_ccc::t1 () // arithmetic, while the SSE version is using 32 bit float point // arithmetic. - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], abs (expected_output[o]) * ERR_DELTA); } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h index 411a66a9a..f9f206f66 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h @@ -29,13 +29,16 @@ class qa_gri_fir_filter_with_buffer_ccc : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccc); CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); CPPUNIT_TEST_SUITE_END (); private: + void test_decimate(unsigned int decimate); void t1 (); - // void t2 (); - // void t3 (); + void t2 (); + void t3 (); }; diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc index f2e09db1c..c25853b1e 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc @@ -80,14 +80,31 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) return sum; } +void +qa_gri_fir_filter_with_buffer_ccf::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_ccf::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_ccf::t3 () +{ + test_decimate(5); +} + // // Test for ntaps in [0,9], and input lengths in [0,17]. // This ensures that we are building the shifted taps correctly, // and exercises all corner cases on input alignment and length. // - void -qa_gri_fir_filter_with_buffer_ccf::t1 () +qa_gri_fir_filter_with_buffer_ccf::test_decimate (unsigned int decimate) { const int MAX_TAPS = 9; const int OUTPUT_LEN = 17; @@ -114,11 +131,13 @@ qa_gri_fir_filter_with_buffer_ccf::t1 () // compute expected output values memset(dline, 0, INPUT_LEN*sizeof(i_type)); - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ // use an actual delay line for this test - for(int oo = INPUT_LEN-1; oo > 0; oo--) - dline[oo] = dline[oo-1]; - dline[0] = input[o]; + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } expected_output[o] = ref_dotprod (dline, taps, n); } @@ -128,7 +147,7 @@ qa_gri_fir_filter_with_buffer_ccf::t1 () // zero the output, then do the filtering memset (actual_output, 0, sizeof (actual_output)); - f1->filterN (actual_output, input, ol); + f1->filterNdec (actual_output, input, ol/decimate, decimate); // check results // @@ -137,7 +156,7 @@ qa_gri_fir_filter_with_buffer_ccf::t1 () // arithmetic, while the SSE version is using 32 bit float point // arithmetic. - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], abs (expected_output[o]) * ERR_DELTA); } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h index b80be70a7..924b4bc2e 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h @@ -29,13 +29,16 @@ class qa_gri_fir_filter_with_buffer_ccf : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccf); CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); CPPUNIT_TEST_SUITE_END (); private: + void test_decimate(unsigned int decimate); void t1 (); - // void t2 (); - // void t3 (); + void t2 (); + void t3 (); }; diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc index de0da9f1c..19f270200 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc @@ -80,14 +80,32 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) return sum; } +void +qa_gri_fir_filter_with_buffer_fcc::t1() +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_fcc::t2() +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_fcc::t3() +{ + test_decimate(5); +} + + // // Test for ntaps in [0,9], and input lengths in [0,17]. // This ensures that we are building the shifted taps correctly, // and exercises all corner cases on input alignment and length. // - void -qa_gri_fir_filter_with_buffer_fcc::t1 () +qa_gri_fir_filter_with_buffer_fcc::test_decimate(unsigned int decimate) { const int MAX_TAPS = 9; const int OUTPUT_LEN = 17; @@ -114,11 +132,13 @@ qa_gri_fir_filter_with_buffer_fcc::t1 () // compute expected output values memset(dline, 0, INPUT_LEN*sizeof(i_type)); - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ // use an actual delay line for this test - for(int oo = INPUT_LEN-1; oo > 0; oo--) - dline[oo] = dline[oo-1]; - dline[0] = input[o]; + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } expected_output[o] = ref_dotprod (dline, taps, n); } @@ -128,7 +148,7 @@ qa_gri_fir_filter_with_buffer_fcc::t1 () // zero the output, then do the filtering memset (actual_output, 0, sizeof (actual_output)); - f1->filterN (actual_output, input, ol); + f1->filterNdec (actual_output, input, ol/decimate, decimate); // check results // @@ -137,7 +157,7 @@ qa_gri_fir_filter_with_buffer_fcc::t1 () // arithmetic, while the SSE version is using 32 bit float point // arithmetic. - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], abs (expected_output[o]) * ERR_DELTA); } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h index 81b39f488..6201800f9 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h @@ -29,13 +29,16 @@ class qa_gri_fir_filter_with_buffer_fcc : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fcc); CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); CPPUNIT_TEST_SUITE_END (); private: + void test_decimate(unsigned int decimate); void t1 (); - // void t2 (); - // void t3 (); + void t2 (); + void t3 (); }; diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc index ce689a54b..8401e484b 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc @@ -69,14 +69,31 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) return sum; } +void +qa_gri_fir_filter_with_buffer_fff::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_fff::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_fff::t3 () +{ + test_decimate(5); +} + // // Test for ntaps in [0,9], and input lengths in [0,17]. // This ensures that we are building the shifted taps correctly, // and exercises all corner cases on input alignment and length. // - void -qa_gri_fir_filter_with_buffer_fff::t1 () +qa_gri_fir_filter_with_buffer_fff::test_decimate(unsigned int decimate) { const int MAX_TAPS = 9; const int OUTPUT_LEN = 17; @@ -103,11 +120,13 @@ qa_gri_fir_filter_with_buffer_fff::t1 () // compute expected output values memset(dline, 0, INPUT_LEN*sizeof(i_type)); - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ // use an actual delay line for this test - for(int oo = INPUT_LEN-1; oo > 0; oo--) - dline[oo] = dline[oo-1]; - dline[0] = input[o]; + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } expected_output[o] = ref_dotprod (dline, taps, n); } @@ -117,7 +136,7 @@ qa_gri_fir_filter_with_buffer_fff::t1 () // zero the output, then do the filtering memset (actual_output, 0, sizeof (actual_output)); - f1->filterN (actual_output, input, ol); + f1->filterNdec (actual_output, input, ol/decimate, decimate); // check results // @@ -126,7 +145,7 @@ qa_gri_fir_filter_with_buffer_fff::t1 () // arithmetic, while the SSE version is using 32 bit float point // arithmetic. - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o], fabsf (expected_output[o]) * ERR_DELTA); } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h index 5bb6c3e93..54a9cdc53 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h @@ -29,13 +29,16 @@ class qa_gri_fir_filter_with_buffer_fff : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fff); CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); CPPUNIT_TEST_SUITE_END (); private: + void test_decimate(unsigned int decimate); void t1 (); - // void t2 (); - // void t3 (); + void t2 (); + void t3 (); }; diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc index f09a1d7ac..091505380 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc @@ -67,14 +67,31 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) return (o_type)sum; } +void +qa_gri_fir_filter_with_buffer_fsf::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_fsf::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_fsf::t3 () +{ + test_decimate(5); +} + // // Test for ntaps in [0,9], and input lengths in [0,17]. // This ensures that we are building the shifted taps correctly, // and exercises all corner cases on input alignment and length. // - void -qa_gri_fir_filter_with_buffer_fsf::t1 () +qa_gri_fir_filter_with_buffer_fsf::test_decimate (unsigned int decimate) { const int MAX_TAPS = 9; const int OUTPUT_LEN = 17; @@ -101,11 +118,13 @@ qa_gri_fir_filter_with_buffer_fsf::t1 () // compute expected output values memset(dline, 0, INPUT_LEN*sizeof(i_type)); - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ // use an actual delay line for this test - for(int oo = INPUT_LEN-1; oo > 0; oo--) - dline[oo] = dline[oo-1]; - dline[0] = input[o]; + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } expected_output[o] = ref_dotprod (dline, taps, n); } @@ -115,10 +134,10 @@ qa_gri_fir_filter_with_buffer_fsf::t1 () // zero the output, then do the filtering memset (actual_output, 0, sizeof (actual_output)); - f1->filterN (actual_output, input, ol); + f1->filterNdec (actual_output, input, ol/decimate, decimate); // check results - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ CPPUNIT_ASSERT_EQUAL(expected_output[o], actual_output[o]); } delete f1; diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h index 38899b352..9c901464e 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h @@ -29,13 +29,16 @@ class qa_gri_fir_filter_with_buffer_fsf : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fsf); CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); CPPUNIT_TEST_SUITE_END (); private: - + void test_decimate(unsigned int decimate); + void t1 (); - // void t2 (); - // void t3 (); + void t2 (); + void t3 (); }; diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc index 4ba433ebf..03cd71022 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc @@ -80,14 +80,31 @@ ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) return sum; } +void +qa_gri_fir_filter_with_buffer_scc::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_scc::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_scc::t3 () +{ + test_decimate(5); +} + // // Test for ntaps in [0,9], and input lengths in [0,17]. // This ensures that we are building the shifted taps correctly, // and exercises all corner cases on input alignment and length. // - void -qa_gri_fir_filter_with_buffer_scc::t1 () +qa_gri_fir_filter_with_buffer_scc::test_decimate (unsigned int decimate) { const int MAX_TAPS = 9; const int OUTPUT_LEN = 17; @@ -114,11 +131,13 @@ qa_gri_fir_filter_with_buffer_scc::t1 () // compute expected output values memset(dline, 0, INPUT_LEN*sizeof(i_type)); - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ // use an actual delay line for this test - for(int oo = INPUT_LEN-1; oo > 0; oo--) - dline[oo] = dline[oo-1]; - dline[0] = input[o]; + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } expected_output[o] = ref_dotprod (dline, taps, n); } @@ -128,7 +147,7 @@ qa_gri_fir_filter_with_buffer_scc::t1 () // zero the output, then do the filtering memset (actual_output, 0, sizeof (actual_output)); - f1->filterN (actual_output, input, ol); + f1->filterNdec (actual_output, input, ol/decimate, decimate); // check results // @@ -137,7 +156,7 @@ qa_gri_fir_filter_with_buffer_scc::t1 () // arithmetic, while the SSE version is using 32 bit float point // arithmetic. - for (int o = 0; o < ol; o++){ + for (int o = 0; o < (int)(ol/decimate); o++){ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], abs (expected_output[o]) * ERR_DELTA); } diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h index fd9fe5b76..970ca3749 100644 --- a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h @@ -29,13 +29,16 @@ class qa_gri_fir_filter_with_buffer_scc : public CppUnit::TestCase { CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_scc); CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); CPPUNIT_TEST_SUITE_END (); private: + void test_decimate(unsigned int decimate); void t1 (); - // void t2 (); - // void t3 (); + void t2 (); + void t3 (); }; -- cgit From 1fa9a8ea31115b878bff48d2259fc72d1a37b52c Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Tue, 2 Nov 2010 12:53:15 -0400 Subject: Sneaking in a few warning fixes to this branch. --- gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc | 1 - gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc index cb67b8104..db16a634b 100644 --- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc @@ -55,7 +55,6 @@ gr_pfb_channelizer_ccf::gr_pfb_channelizer_ccf (unsigned int numchans, // This tests the specified input sample rate to see if it conforms to this // requirement within a few significant figures. double intp = 0; - double x = (10000.0*rint(numchans / oversample_rate)) / 10000.0; double fltp = modf(numchans / oversample_rate, &intp); if(fltp != 0.0) throw std::invalid_argument("gr_pfb_channelizer: oversample rate must be N/i for i in [1, N]"); diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc index ff997e7a9..c32398e6d 100644 --- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc +++ b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc @@ -161,8 +161,9 @@ gr_fll_band_edge_cc::work (int noutput_items, const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - float *frq, *phs; - gr_complex *err; + float *frq = NULL; + float *phs = NULL; + gr_complex *err = NULL; if(output_items.size() > 2) { frq = (float *) output_items[1]; phs = (float *) output_items[2]; -- cgit