-
Notifications
You must be signed in to change notification settings - Fork 12
/
add.cpp
133 lines (112 loc) · 3.56 KB
/
add.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
#include <grextras/add.hpp>
#include <boost/make_shared.hpp>
#include <stdexcept>
#include <complex>
#ifdef HAVE_VOLK
#include <volk/volk.h>
#endif
using namespace grextras;
/***********************************************************************
* Templated Adder class
**********************************************************************/
template <typename type>
struct AddImpl : Add
{
AddImpl(const size_t vlen):
gras::Block("GrExtras Add"),
_vlen(vlen)
{
this->set_input_signature(gras::IOSignature(sizeof(type)*_vlen));
this->set_output_signature(gras::IOSignature(sizeof(type)*_vlen));
}
void notify_topology(const size_t num_inputs, const size_t num_outputs)
{
for (size_t i = 0; i < num_inputs; i++)
{
gras::InputPortConfig config = this->get_input_config(i);
config.inline_buffer = (i == 0);
this->set_input_config(i, config);
}
}
void work(const InputItems &, const OutputItems &);
const size_t _vlen;
};
/***********************************************************************
* Generic Adder implementation
**********************************************************************/
template <typename type>
void AddImpl<type>::work(
const InputItems &ins, const OutputItems &outs
){
const size_t n_nums = std::min(ins.min(), outs.min());
type *out = outs[0].cast<type *>();
const type *in0 = ins[0].cast<const type *>();
for (size_t n = 1; n < ins.size(); n++)
{
const type *in = ins[n].cast<const type *>();
for (size_t i = 0; i < n_nums * _vlen; i++)
{
out[i] = in0[i] + in[i];
}
in0 = out; //for next input, we do output += input
}
this->consume(n_nums);
this->produce(n_nums);
}
#ifdef HAVE_VOLK
/***********************************************************************
* Adder implementation with float32 - calls volk
**********************************************************************/
template <>
void AddImpl<float>::work(
const InputItems &ins, const OutputItems &outs
){
const size_t n_nums = std::min(ins.min(), outs.min());
float *out = outs[0].cast<float *>();
const float *in0 = ins[0].cast<const float *>();
for (size_t n = 1; n < ins.size(); n++)
{
const float *in = ins[n].cast<const float *>();
volk_32f_x2_add_32f(out, in0, in, n_nums * _vlen);
in0 = out; //for next input, we do output += input
}
this->consume(n_nums);
this->produce(n_nums);
}
#endif
/***********************************************************************
* factory function
**********************************************************************/
Add::sptr Add::make_fc32_fc32(const size_t vlen)
{
return sptr(new AddImpl<float>(2*vlen));
}
Add::sptr Add::make_sc32_sc32(const size_t vlen)
{
return sptr(new AddImpl<boost::int32_t>(2*vlen));
}
Add::sptr Add::make_sc16_sc16(const size_t vlen)
{
return sptr(new AddImpl<boost::int16_t>(2*vlen));
}
Add::sptr Add::make_sc8_sc8(const size_t vlen)
{
return sptr(new AddImpl<boost::int8_t>(2*vlen));
}
Add::sptr Add::make_f32_f32(const size_t vlen)
{
return sptr(new AddImpl<float>(vlen));
}
Add::sptr Add::make_s32_s32(const size_t vlen)
{
return sptr(new AddImpl<boost::int32_t>(vlen));
}
Add::sptr Add::make_s16_s16(const size_t vlen)
{
return sptr(new AddImpl<boost::int16_t>(vlen));
}
Add::sptr Add::make_s8_s8(const size_t vlen)
{
return sptr(new AddImpl<boost::int8_t>(vlen));
}