diff options
-rw-r--r-- | gr-blocks/grc/blocks_block_tree.xml | 1 | ||||
-rw-r--r-- | gr-blocks/grc/blocks_transcendental.xml | 41 | ||||
-rw-r--r-- | gr-blocks/include/blocks/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-blocks/include/blocks/transcendental.h | 56 | ||||
-rw-r--r-- | gr-blocks/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-blocks/lib/transcendental_impl.cc | 150 | ||||
-rw-r--r-- | gr-blocks/lib/transcendental_impl.h | 51 | ||||
-rw-r--r-- | gr-blocks/python/qa_transcendental.py | 90 | ||||
-rw-r--r-- | gr-blocks/swig/blocks_swig.i | 3 |
9 files changed, 394 insertions, 0 deletions
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml index 6ab84c94e..5e304d3c3 100644 --- a/gr-blocks/grc/blocks_block_tree.xml +++ b/gr-blocks/grc/blocks_block_tree.xml @@ -50,6 +50,7 @@ <block>blocks_integrate_xx</block> <block>blocks_nlog10_ff</block> <block>blocks_rms_xx</block> + <block>blocks_transcendental</block> </cat> <cat> <name>Boolean Operations (New) </name> diff --git a/gr-blocks/grc/blocks_transcendental.xml b/gr-blocks/grc/blocks_transcendental.xml new file mode 100644 index 000000000..a883a2eef --- /dev/null +++ b/gr-blocks/grc/blocks_transcendental.xml @@ -0,0 +1,41 @@ +<?xml version="1.0"?> +<!-- +################################################### +##transcendental functions +################################################### + --> +<block> + <name>Transcendental</name> + <key>blocks_transcendental</key> + <import>from gnuradio import blocks</import> + <make>blocks.transcendental($name, "$type")</make> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex_double</key> + <opt>type:complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>type:float</opt> + </option> + </param> + <param> + <name>Function Name</name> + <key>name</key> + <value>cos</value> + <type>string</type> + </param> + <sink> + <name>in</name> + <type>$type.type</type> + </sink> + <source> + <name>out</name> + <type>$type.type</type> + </source> +</block> diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt index 8d5fe9b13..d3c08f6e6 100644 --- a/gr-blocks/include/blocks/CMakeLists.txt +++ b/gr-blocks/include/blocks/CMakeLists.txt @@ -141,6 +141,7 @@ install(FILES stretch_ff.h threshold_ff.h throttle.h + transcendental.h uchar_to_float.h vector_to_stream.h vector_to_streams.h diff --git a/gr-blocks/include/blocks/transcendental.h b/gr-blocks/include/blocks/transcendental.h new file mode 100644 index 000000000..f8a0d5d80 --- /dev/null +++ b/gr-blocks/include/blocks/transcendental.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2013 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_TRANSCENDENTAL_H +#define INCLUDED_GR_TRANSCENDENTAL_H + +#include <blocks/api.h> +#include <gr_sync_block.h> +#include <string> + +namespace gr { + namespace blocks { + + /*! + * \brief A block that performs various transcendental math operations. + * + * Possible function names can be found in the cmath library. IO + * may be either complex or real, double or single precision. + * + * Possible type strings: float, double, complex_float, complex_double + * + * output[i] = trans_fcn(input[i]) + */ + class BLOCKS_API transcendental : virtual public gr_sync_block + { + public: + // gr::blocks::transcendental::sptr + typedef boost::shared_ptr<transcendental> sptr; + + static sptr make(const std::string &name, + const std::string &type="float"); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_TRANSCENDENTAL_H */ diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index e1b9b4f00..20e3ae4aa 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -180,6 +180,7 @@ list(APPEND gr_blocks_sources stretch_ff_impl.cc threshold_ff_impl.cc throttle_impl.cc + transcendental_impl.cc uchar_array_to_float.cc uchar_to_float_impl.cc vector_to_stream_impl.cc diff --git a/gr-blocks/lib/transcendental_impl.cc b/gr-blocks/lib/transcendental_impl.cc new file mode 100644 index 000000000..725899ca8 --- /dev/null +++ b/gr-blocks/lib/transcendental_impl.cc @@ -0,0 +1,150 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2013 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. + */ + +#include "transcendental_impl.h" +#include <gr_io_signature.h> +#include <stdexcept> +#include <complex> //complex math +#include <cmath> //real math +#include <map> + +namespace gr { + namespace blocks { + + /*********************************************************************** + * work function creation and registration + **********************************************************************/ + struct map_val_type + { + work_fcn_type work_fcn; + size_t io_size; + }; + typedef std::map<std::string, map_val_type> map_type; + + //construct map on first use idiom + static map_type & + get_map(void) + { + static map_type map; + return map; + } + + //static initialization of this object registers a function + struct transcendental_registrant + { + transcendental_registrant(const std::string &key, + const work_fcn_type &work_fcn, + const size_t io_size) + { + map_val_type val; + val.work_fcn = work_fcn; + val.io_size = io_size; + get_map()[key] = val; + } + }; + + //macro to create a work function and register it +#define REGISTER_FUNCTION(__fcn__, __type__, __key__) \ + static int __key__ ## _work( \ + int noutput_items, \ + gr_vector_const_void_star &input_items, \ + gr_vector_void_star &output_items) \ + { \ + const __type__ *in = (const __type__ *) input_items[0]; \ + __type__ *out = (__type__ *) output_items[0]; \ + for (size_t i = 0; i < size_t(noutput_items); i++){ \ + out[i] = std::__fcn__(in[i]); \ + } \ + return noutput_items; \ + } \ + transcendental_registrant __key__ ## _registrant(#__key__, &__key__ ## _work, sizeof(__type__)); + + //register work functions for real types +#define REGISTER_REAL_FUNCTIONS(__fcn__) \ + REGISTER_FUNCTION(__fcn__, float, __fcn__ ## _float) \ + REGISTER_FUNCTION(__fcn__, double, __fcn__ ## _double) + + //register work functions for complex types +#define REGISTER_COMPLEX_FUNCTIONS(__fcn__) \ + REGISTER_FUNCTION(__fcn__, std::complex<float>, __fcn__ ## _complex_float) \ + REGISTER_FUNCTION(__fcn__, std::complex<double>, __fcn__ ## _complex_double) + + //register both complex and real +#define REGISTER_FUNCTIONS(__fcn__) \ + REGISTER_REAL_FUNCTIONS(__fcn__) \ + REGISTER_COMPLEX_FUNCTIONS(__fcn__) + + //create and register transcendental work functions + REGISTER_FUNCTIONS(cos) + REGISTER_FUNCTIONS(sin) + REGISTER_FUNCTIONS(tan) + REGISTER_REAL_FUNCTIONS(acos) + REGISTER_REAL_FUNCTIONS(asin) + REGISTER_REAL_FUNCTIONS(atan) + REGISTER_FUNCTIONS(cosh) + REGISTER_FUNCTIONS(sinh) + REGISTER_FUNCTIONS(tanh) + REGISTER_FUNCTIONS(exp) + REGISTER_FUNCTIONS(log) + REGISTER_FUNCTIONS(log10) + REGISTER_FUNCTIONS(sqrt) + + + transcendental::sptr + transcendental::make(const std::string &name, + const std::string &type) + { + //search for an entry in the map + const std::string key = name + "_" + type; + const bool has_key = get_map().count(key) != 0; + if(!has_key) + throw std::runtime_error("could not find transcendental function for " + key); + + //make a new block with found work function + return gnuradio::get_initial_sptr + (new transcendental_impl(get_map()[key].work_fcn, get_map()[key].io_size)); + } + + transcendental_impl::transcendental_impl(const work_fcn_type &work_fcn, + const size_t io_size) + : gr_sync_block("transcendental", + gr_make_io_signature(1, 1, io_size), + gr_make_io_signature(1, 1, io_size)), + _work_fcn(work_fcn) + { + // NOP + } + + transcendental_impl::~transcendental_impl() + { + } + + int + transcendental_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + return _work_fcn(noutput_items, input_items, output_items); + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/transcendental_impl.h b/gr-blocks/lib/transcendental_impl.h new file mode 100644 index 000000000..47055551e --- /dev/null +++ b/gr-blocks/lib/transcendental_impl.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2013 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_TRANSCENDENTAL_IMPL_H +#define INCLUDED_GR_TRANSCENDENTAL_IMPL_H + +#include <blocks/transcendental.h> + +namespace gr { + namespace blocks { + + typedef int(*work_fcn_type)(int, gr_vector_const_void_star &, gr_vector_void_star &); + + class transcendental_impl : public transcendental + { + private: + const work_fcn_type &_work_fcn; + + public: + transcendental_impl(const work_fcn_type &work_fcn, + const size_t io_size); + ~transcendental_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_TRANSCENDENTAL_IMPL_H */ diff --git a/gr-blocks/python/qa_transcendental.py b/gr-blocks/python/qa_transcendental.py new file mode 100644 index 000000000..8174f7963 --- /dev/null +++ b/gr-blocks/python/qa_transcendental.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# +# Copyright 2013 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. +# + +from gnuradio import gr, gr_unittest +import blocks_swig as blocks +import math + +class test_transcendental(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_01(self): + tb = self.tb + + data = 100*[0,] + expected_result = 100*[1,] + + src = gr.vector_source_f(data, False) + op = blocks.transcendental("cos", "float") + dst = gr.vector_sink_f() + + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + + dst_data = dst.data() + + self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 5) + + def test_02(self): + tb = self.tb + + data = 100*[3,] + expected_result = 100*[math.log10(3),] + + src = gr.vector_source_f(data, False) + op = blocks.transcendental("log10", "float") + dst = gr.vector_sink_f() + + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + + dst_data = dst.data() + + self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 5) + + def test_03(self): + tb = self.tb + + data = 100*[3,] + expected_result = 100*[math.tanh(3),] + + src = gr.vector_source_f(data, False) + op = blocks.transcendental("tanh", "float") + dst = gr.vector_sink_f() + + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + + dst_data = dst.data() + + self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_transcendental, "test_transcendental.xml") diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i index 6407421b1..db8af3436 100644 --- a/gr-blocks/swig/blocks_swig.i +++ b/gr-blocks/swig/blocks_swig.i @@ -124,6 +124,7 @@ #include "blocks/sub_cc.h" #include "blocks/threshold_ff.h" #include "blocks/throttle.h" +#include "blocks/transcendental.h" #include "blocks/uchar_to_float.h" #include "blocks/unpacked_to_packed_bb.h" #include "blocks/unpacked_to_packed_ss.h" @@ -229,6 +230,7 @@ %include "blocks/sub_cc.h" %include "blocks/threshold_ff.h" %include "blocks/throttle.h" +%include "blocks/transcendental.h" %include "blocks/uchar_to_float.h" %include "blocks/unpacked_to_packed_bb.h" %include "blocks/unpacked_to_packed_ss.h" @@ -333,6 +335,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, sub_ii); GR_SWIG_BLOCK_MAGIC2(blocks, sub_cc); GR_SWIG_BLOCK_MAGIC2(blocks, threshold_ff); GR_SWIG_BLOCK_MAGIC2(blocks, throttle); +GR_SWIG_BLOCK_MAGIC2(blocks, transcendental); GR_SWIG_BLOCK_MAGIC2(blocks, uchar_to_float); GR_SWIG_BLOCK_MAGIC2(blocks, unpacked_to_packed_bb); GR_SWIG_BLOCK_MAGIC2(blocks, unpacked_to_packed_ss); |