1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,2009,2010,2012,2018 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "add_blk_impl.h"
29 #include <gnuradio/io_signature.h>
30 #include <volk/volk.h>
31 
32 namespace gr {
33 namespace blocks {
34 
35 template <class T>
make(size_t vlen)36 typename add_blk<T>::sptr add_blk<T>::make(size_t vlen)
37 {
38     return gnuradio::get_initial_sptr(new add_blk_impl<T>(vlen));
39 }
40 
41 
42 template <>
add_blk_impl(size_t vlen)43 add_blk_impl<float>::add_blk_impl(size_t vlen)
44     : sync_block("add_ff",
45                  io_signature::make(1, -1, sizeof(float) * vlen),
46                  io_signature::make(1, 1, sizeof(float) * vlen)),
47       d_vlen(vlen)
48 {
49     const int alignment_multiple = volk_get_alignment() / sizeof(float);
50     set_alignment(std::max(1, alignment_multiple));
51 }
52 
53 template <>
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)54 int add_blk_impl<float>::work(int noutput_items,
55                               gr_vector_const_void_star& input_items,
56                               gr_vector_void_star& output_items)
57 {
58     float* out = (float*)output_items[0];
59     int noi = d_vlen * noutput_items;
60 
61     memcpy(out, input_items[0], noi * sizeof(float));
62     for (size_t i = 1; i < input_items.size(); i++)
63         volk_32f_x2_add_32f(out, out, (const float*)input_items[i], noi);
64     return noutput_items;
65 }
66 
67 
68 template <class T>
add_blk_impl(size_t vlen)69 add_blk_impl<T>::add_blk_impl(size_t vlen)
70     : sync_block("add_blk",
71                  io_signature::make(1, -1, sizeof(T) * vlen),
72                  io_signature::make(1, 1, sizeof(T) * vlen)),
73       d_vlen(vlen)
74 {
75 }
76 
77 template <class T>
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)78 int add_blk_impl<T>::work(int noutput_items,
79                           gr_vector_const_void_star& input_items,
80                           gr_vector_void_star& output_items)
81 {
82     T* optr = (T*)output_items[0];
83 
84     int ninputs = input_items.size();
85 
86     for (size_t i = 0; i < noutput_items * d_vlen; i++) {
87         T acc = ((T*)input_items[0])[i];
88         for (int j = 1; j < ninputs; j++)
89             acc += ((T*)input_items[j])[i];
90 
91         *optr++ = (T)acc;
92     }
93 
94     return noutput_items;
95 }
96 
97 template class add_blk<std::int16_t>;
98 template class add_blk<std::int32_t>;
99 template class add_blk<gr_complex>;
100 template class add_blk<float>;
101 } /* namespace blocks */
102 } /* namespace gr */
103