patch-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Patch-gnuradio] Element-wise vector addition as gr_add_vXX


From: Johnathan Corgan
Subject: [Patch-gnuradio] Element-wise vector addition as gr_add_vXX
Date: Sun, 11 Jun 2006 17:45:44 -0700
User-agent: Thunderbird 1.5.0.2 (X11/20060522)

Attached is a patch and new files that implement element-wise vector
addition.

The following new blocks are created:

gr_add_vii
gr_add_vss
gr_add_vff
gr_add_vcc

They must be created with a single argument that specifies the number of
items per block:

# Create an adder that accepts 1024 item vectors of floats:
adder = gr_add_vff(1024)

The attached patch file modifies gnuradio-core/src/lib/general.

The template files drop into this same directory:

gr_add_vXX.cc.t
gr_add_vXX.h.t
gr_add_vXX.i.t

The QA test script drops into gnuradio-core/src/python/gnuradio/gr:

qa_add_v_and_friends.py

I will also be working on vector analogs for the remainder of the
gr_func_xx blocks (for element-wise multiplication, etc.)

Finally, the dialtone_v.py script uses vector addition instead of stream
addition to sum the two constituent sine waves.  This somewhat of an
artificial way of using the new blocks but does show how they are
different from the corresponding stream blocks.

-Johnathan, AE6HO
Index: .cvsignore
===================================================================
RCS file: /sources/gnuradio/gnuradio-core/src/lib/general/.cvsignore,v
retrieving revision 1.10
diff -u -r1.10 .cvsignore
--- .cvsignore  24 Apr 2006 20:47:42 -0000      1.10
+++ .cvsignore  11 Jun 2006 19:50:05 -0000
@@ -120,6 +120,18 @@
 gr_add_ss.cc
 gr_add_ss.h
 gr_add_ss.i
+gr_add_vcc.cc
+gr_add_vcc.h
+gr_add_vcc.i
+gr_add_vff.cc
+gr_add_vff.h
+gr_add_vff.i
+gr_add_vii.cc
+gr_add_vii.h
+gr_add_vii.i
+gr_add_vss.cc
+gr_add_vss.h
+gr_add_vss.i
 gr_divide_cc.cc
 gr_divide_cc.h
 gr_divide_cc.i
Index: Makefile.gen
===================================================================
RCS file: /sources/gnuradio/gnuradio-core/src/lib/general/Makefile.gen,v
retrieving revision 1.8
diff -u -r1.8 Makefile.gen
--- Makefile.gen        24 Apr 2006 20:47:42 -0000      1.8
+++ Makefile.gen        11 Jun 2006 19:50:05 -0000
@@ -11,6 +11,10 @@
        gr_add_ff.h \
        gr_add_ii.h \
        gr_add_ss.h \
+       gr_add_vcc.h \
+       gr_add_vff.h \
+       gr_add_vii.h \
+       gr_add_vss.h \
        gr_chunks_to_symbols_bc.h \
        gr_chunks_to_symbols_bf.h \
        gr_chunks_to_symbols_ic.h \
@@ -72,6 +76,10 @@
        gr_add_ff.i \
        gr_add_ii.i \
        gr_add_ss.i \
+       gr_add_vcc.i \
+       gr_add_vff.i \
+       gr_add_vii.i \
+       gr_add_vss.i \
        gr_chunks_to_symbols_bc.i \
        gr_chunks_to_symbols_bf.i \
        gr_chunks_to_symbols_ic.i \
@@ -133,6 +141,10 @@
        gr_add_ff.cc \
        gr_add_ii.cc \
        gr_add_ss.cc \
+       gr_add_vcc.cc \
+       gr_add_vff.cc \
+       gr_add_vii.cc \
+       gr_add_vss.cc \
        gr_chunks_to_symbols_bc.cc \
        gr_chunks_to_symbols_bf.cc \
        gr_chunks_to_symbols_ic.cc \
Index: general_generated.i
===================================================================
RCS file: /sources/gnuradio/gnuradio-core/src/lib/general/general_generated.i,v
retrieving revision 1.8
diff -u -r1.8 general_generated.i
--- general_generated.i 24 Apr 2006 20:47:42 -0000      1.8
+++ general_generated.i 11 Jun 2006 19:50:05 -0000
@@ -11,6 +11,10 @@
 #include <gr_add_ff.h>
 #include <gr_add_ii.h>
 #include <gr_add_ss.h>
+#include <gr_add_vcc.h>
+#include <gr_add_vff.h>
+#include <gr_add_vii.h>
+#include <gr_add_vss.h>
 #include <gr_chunks_to_symbols_bc.h>
 #include <gr_chunks_to_symbols_bf.h>
 #include <gr_chunks_to_symbols_ic.h>
@@ -72,6 +76,10 @@
 %include <gr_add_ff.i>
 %include <gr_add_ii.i>
 %include <gr_add_ss.i>
+%include <gr_add_vcc.i>
+%include <gr_add_vff.i>
+%include <gr_add_vii.i>
+%include <gr_add_vss.i>
 %include <gr_chunks_to_symbols_bc.i>
 %include <gr_chunks_to_symbols_bf.i>
 %include <gr_chunks_to_symbols_ic.i>
Index: generate_common.py
===================================================================
RCS file: /sources/gnuradio/gnuradio-core/src/lib/general/generate_common.py,v
retrieving revision 1.9
diff -u -r1.9 generate_common.py
--- generate_common.py  24 Apr 2006 20:47:42 -0000      1.9
+++ generate_common.py  11 Jun 2006 19:50:05 -0000
@@ -46,7 +46,8 @@
     'gr_sub_XX',
     'gr_multiply_XX',
     'gr_divide_XX',
-    'gr_mute_XX'
+    'gr_mute_XX',
+    'gr_add_vXX'
     ]
 
 # other blocks
/* -*- c++ -*- */
/*
 * Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

// @WARNING@

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <@address@hidden>
#include <gr_io_signature.h>

@SPTR_NAME@
address@hidden@ (size_t nitems_per_block)
{
  return @SPTR_NAME@ (new @NAME@ (nitems_per_block));
}

@NAME@::@NAME@ (size_t nitems_per_block)
  : gr_sync_block ("@BASE_NAME@",
                   gr_make_io_signature (1, -1, sizeof 
(@I_TYPE@)*nitems_per_block),
                   gr_make_io_signature (1,  1, sizeof 
(@O_TYPE@)*nitems_per_block))
{
}

int
@NAME@::work (int noutput_items,
                   gr_vector_const_void_star &input_items,
                   gr_vector_void_star &output_items)
{
  @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0];

  int ninputs = input_items.size ();
  int nitems_per_block = 
output_signature()->sizeof_stream_item(0)/sizeof(@I_TYPE@);

  for (int i = 0; i < noutput_items; i++){
    for (int j = 0; j < nitems_per_block; j++){
      @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i*nitems_per_block+j];
      for (int k = 1; k < ninputs; k++)
        acc += ((@I_TYPE@ *) input_items[k])[i*nitems_per_block+j];

      *optr++ = (@O_TYPE@) acc;
    }
  }
  return noutput_items;
}
/* -*- c++ -*- */
/*
 * Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

// @WARNING@

#ifndef @GUARD_NAME@
#define @GUARD_NAME@

#include <gr_sync_block.h>

class @NAME@;
typedef boost::shared_ptr<@NAME@> @SPTR_NAME@;

@SPTR_NAME@ address@hidden@ (size_t nitems_per_block);

/*!
 * \brief output = sum (input_0, input_1, ...)
 * \ingroup block
 *
 * Add across all input vectors.
 */
class @NAME@ : public gr_sync_block
{
  friend @SPTR_NAME@ address@hidden@ (size_t nitems_per_block);

  @NAME@ (size_t nitems_per_block);

 public:

  int work (int noutput_items,
            gr_vector_const_void_star &input_items,
            gr_vector_void_star &output_items);
};

#endif
/* -*- c++ -*- */
/*
 * Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

// @WARNING@

GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@)

@SPTR_NAME@ address@hidden@ (size_t nitems_per_block);

class @NAME@ : public gr_sync_block
{
 private:
  @NAME@ (size_t nitems_per_block);
};
#!/usr/bin/env python
#
# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# 

from gnuradio import gr, gr_unittest

class test_head (gr_unittest.TestCase):

    def setUp(self):
        self.fg = gr.flow_graph()

    def tearDown(self):
        self.fg = None

    def help_ss(self, size, src_data, exp_data, op):
        for s in zip(range (len (src_data)), src_data):
            src = gr.vector_source_s(s[1])
            srcv = gr.stream_to_vector(gr.sizeof_short, size)
            self.fg.connect(src, srcv)
            self.fg.connect(srcv, (op, s[0]))
        rhs = gr.vector_to_stream(gr.sizeof_short, size)
        dst = gr.vector_sink_s()
        self.fg.connect(op, rhs, dst)
        self.fg.run()
        result_data = dst.data()
        self.assertEqual(exp_data, result_data)

    def help_ii(self, size, src_data, exp_data, op):
        for s in zip(range (len (src_data)), src_data):
            src = gr.vector_source_i(s[1])
            srcv = gr.stream_to_vector(gr.sizeof_int, size)
            self.fg.connect(src, srcv)
            self.fg.connect(srcv, (op, s[0]))
        rhs = gr.vector_to_stream(gr.sizeof_int, size)
        dst = gr.vector_sink_i()
        self.fg.connect(op, rhs, dst)
        self.fg.run()
        result_data = dst.data()
        self.assertEqual(exp_data, result_data)

    def help_ff(self, size, src_data, exp_data, op):
        for s in zip(range (len (src_data)), src_data):
            src = gr.vector_source_f(s[1])
            srcv = gr.stream_to_vector(gr.sizeof_float, size)
            self.fg.connect(src, srcv)
            self.fg.connect(srcv, (op, s[0]))
        rhs = gr.vector_to_stream(gr.sizeof_float, size)
        dst = gr.vector_sink_f()
        self.fg.connect(op, rhs, dst)
        self.fg.run()
        result_data = dst.data()
        self.assertEqual(exp_data, result_data)

    def help_cc(self, size, src_data, exp_data, op):
        for s in zip(range (len (src_data)), src_data):
            src = gr.vector_source_c(s[1])
            srcv = gr.stream_to_vector(gr.sizeof_gr_complex, size)
            self.fg.connect(src, srcv)
            self.fg.connect(srcv, (op, s[0]))
        rhs = gr.vector_to_stream(gr.sizeof_gr_complex, size)
        dst = gr.vector_sink_c()
        self.fg.connect(op, rhs, dst)
        self.fg.run()
        result_data = dst.data()
        self.assertEqual(exp_data, result_data)

    def test_add_vss_one(self):
        src1_data = (1,)
        src2_data = (2,)
        src3_data = (3,)
        expected_result = (6,)
        op = gr.add_vss(1)
        self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op)
        
    def test_add_vss_five(self):
        src1_data = (1, 2, 3, 4, 5)
        src2_data = (6, 7, 8, 9, 10)
        src3_data = (11, 12, 13, 14, 15)
        expected_result = (18, 21, 24, 27, 30)
        op = gr.add_vss(5)
        self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op)

    def test_add_vii_one(self):
        src1_data = (1,)
        src2_data = (2,)
        src3_data = (3,)
        expected_result = (6,)
        op = gr.add_vii(1)
        self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op)
        
    def test_add_vii_five(self):
        src1_data = (1, 2, 3, 4, 5)
        src2_data = (6, 7, 8, 9, 10)
        src3_data = (11, 12, 13, 14, 15)
        expected_result = (18, 21, 24, 27, 30)
        op = gr.add_vii(5)
        self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op)

    def test_add_vff_one(self):
        src1_data = (1.0,)
        src2_data = (2.0,)
        src3_data = (3.0,)
        expected_result = (6.0,)
        op = gr.add_vff(1)
        self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op)
        
    def test_add_vff_five(self):
        src1_data = (1.0, 2.0, 3.0, 4.0, 5.0)
        src2_data = (6.0, 7.0, 8.0, 9.0, 10.0)
        src3_data = (11.0, 12.0, 13.0, 14.0, 15.0)
        expected_result = (18.0, 21.0, 24.0, 27.0, 30.0)
        op = gr.add_vff(5)
        self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op)

    def test_add_vcc_one(self):
        src1_data = (1.0+2.0j,)
        src2_data = (3.0+4.0j,)
        src3_data = (5.0+6.0j,)
        expected_result = (9.0+12j,)
        op = gr.add_vcc(1)
        self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op)
        
    def test_add_vcc_five(self):
        src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j)
        src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)
        src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j)
        expected_result = (33.0+36.0j, 39.0+42.0j, 45.0+48.0j, 51.0+54.0j, 
57.0+60.0j)
        op = gr.add_vcc(5)
        self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op)

if __name__ == '__main__':
    gr_unittest.main ()
#!/usr/bin/env python

from gnuradio import gr, audio

# For testing different buffer sizes
size = 1024
rate = 48000

fg = gr.flow_graph()

# Two streams of floats
a = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 350, 0.5, 0.0);
b = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 440, 0.5, 0.0);

# Turn them into vectors of length 'size'
av = gr.stream_to_vector(gr.sizeof_float, size)
bv = gr.stream_to_vector(gr.sizeof_float, size)

# Make a vector adder for float vectors
adder = gr.add_vff(size)

# Turn the vector sum back into a stream of floats
sum = gr.vector_to_stream(gr.sizeof_float, size)

# Play it
sink = audio.sink(rate)

fg.connect(a, av)
fg.connect(b, bv)
fg.connect(av, (adder, 0))
fg.connect(bv, (adder, 1))
fg.connect(adder, sum)
fg.connect(sum, sink)

try:
    fg.run()
except KeyboardInterrupt:
    pass

reply via email to

[Prev in Thread] Current Thread [Next in Thread]