Skip to content
This repository
Browse code

templates even better with member specialization

  • Loading branch information...
commit 0ead95c4b081ef83be7343e982ac0d09ecf9f050 1 parent bb6f58c
Josh Blum authored

Showing 3 changed files with 225 additions and 213 deletions. Show diff stats Hide diff stats

  1. +60 60 lib/add.cc
  2. +85 83 lib/multiply.cc
  3. +80 70 lib/multiply_const_v.cc
120 lib/add.cc
@@ -28,60 +28,6 @@
28 28 using namespace gnuradio::extras;
29 29
30 30 /***********************************************************************
31   - * Generic adder implementation
32   - **********************************************************************/
33   -template <typename type>
34   -struct add_work
35   -{
36   - size_t multiple(void){return 1;}
37   - size_t operator()(
38   - const size_t vlen,
39   - const gnuradio::block::InputItems &input_items,
40   - const gnuradio::block::OutputItems &output_items
41   - ){
42   - const size_t n_nums = output_items[0].size() * vlen;
43   - type *out = output_items[0].cast<type *>();
44   - const type *in0 = input_items[0].cast<const type *>();
45   -
46   - for (size_t n = 1; n < input_items.size(); n++){
47   - const type *in = input_items[n].cast<const type *>();
48   - for (size_t i = 0; i < n_nums; i++){
49   - out[i] = in0[i] + in[i];
50   - }
51   - in0 = out; //for next input, we do output += input
52   - }
53   -
54   - return output_items[0].size();
55   - }
56   -};
57   -
58   -/***********************************************************************
59   - * Adder implementation with float32 - calls volk
60   - **********************************************************************/
61   -template <>
62   -struct add_work <float>
63   -{
64   - size_t multiple(void){return volk_get_alignment();}
65   - size_t operator()(
66   - const size_t vlen,
67   - const gnuradio::block::InputItems &input_items,
68   - const gnuradio::block::OutputItems &output_items
69   - ){
70   - const size_t n_nums = output_items[0].size() * vlen;
71   - float *out = output_items[0].cast<float *>();
72   - const float *in0 = input_items[0].cast<const float *>();
73   -
74   - for (size_t n = 1; n < input_items.size(); n++){
75   - const float *in = input_items[n].cast<const float *>();
76   - volk_32f_x2_add_32f_a(out, in0, in, n_nums);
77   - in0 = out; //for next input, we do output += input
78   - }
79   -
80   - return output_items[0].size();
81   - }
82   -};
83   -
84   -/***********************************************************************
85 31 * Templated adder class
86 32 **********************************************************************/
87 33 template <typename type>
@@ -95,24 +41,78 @@ class add_generic : public add{
95 41 ),
96 42 _vlen(vlen)
97 43 {
98   - const int alignment_multiple = _work.multiple() / (sizeof(type)*vlen);
  44 + const int alignment_multiple = get_work_multiple() / (sizeof(type)*vlen);
99 45 set_output_multiple(std::max(1, alignment_multiple));
100 46 }
101 47
  48 + size_t get_work_multiple(void);
  49 +
102 50 int work(
103 51 const InputItems &input_items,
104 52 const OutputItems &output_items
105   - ){
106   - const size_t noutput_items = output_items[0].size();
107   - return _work(_vlen, input_items, output_items);
108   - }
  53 + );
109 54
110 55 private:
111 56 const size_t _vlen;
112   - add_work<type> _work;
113 57 };
114 58
115 59 /***********************************************************************
  60 + * Generic adder implementation
  61 + **********************************************************************/
  62 +template <typename type>
  63 +size_t add_generic<type>::get_work_multiple(void)
  64 +{
  65 + return 1;
  66 +}
  67 +
  68 +template <typename type>
  69 +int add_generic<type>::work(
  70 + const InputItems &input_items,
  71 + const OutputItems &output_items
  72 +){
  73 + const size_t n_nums = output_items[0].size() * _vlen;
  74 + type *out = output_items[0].cast<type *>();
  75 + const type *in0 = input_items[0].cast<const type *>();
  76 +
  77 + for (size_t n = 1; n < input_items.size(); n++){
  78 + const type *in = input_items[n].cast<const type *>();
  79 + for (size_t i = 0; i < n_nums; i++){
  80 + out[i] = in0[i] + in[i];
  81 + }
  82 + in0 = out; //for next input, we do output += input
  83 + }
  84 +
  85 + return output_items[0].size();
  86 +}
  87 +
  88 +/***********************************************************************
  89 + * Adder implementation with float32 - calls volk
  90 + **********************************************************************/
  91 +template <>
  92 +size_t add_generic<float>::get_work_multiple(void)
  93 +{
  94 + return volk_get_alignment();
  95 +}
  96 +
  97 +template <>
  98 +int add_generic<float>::work(
  99 + const InputItems &input_items,
  100 + const OutputItems &output_items
  101 +){
  102 + const size_t n_nums = output_items[0].size() * _vlen;
  103 + float *out = output_items[0].cast<float *>();
  104 + const float *in0 = input_items[0].cast<const float *>();
  105 +
  106 + for (size_t n = 1; n < input_items.size(); n++){
  107 + const float *in = input_items[n].cast<const float *>();
  108 + volk_32f_x2_add_32f_a(out, in0, in, n_nums);
  109 + in0 = out; //for next input, we do output += input
  110 + }
  111 +
  112 + return output_items[0].size();
  113 +}
  114 +
  115 +/***********************************************************************
116 116 * factory function
117 117 **********************************************************************/
118 118 add::sptr add::make_fc32_fc32(const size_t num_inputs, const size_t vlen){
168 lib/multiply.cc
@@ -28,83 +28,6 @@
28 28 using namespace gnuradio::extras;
29 29
30 30 /***********************************************************************
31   - * Generic multiplier implementation
32   - **********************************************************************/
33   -template <typename type>
34   -struct multiply_work{
35   - size_t multiple(void){return 1;}
36   - size_t operator()(
37   - const size_t vlen,
38   - const gnuradio::block::InputItems &input_items,
39   - const gnuradio::block::OutputItems &output_items
40   - ){
41   - const size_t n_nums = output_items[0].size() * vlen;
42   - type *out = output_items[0].cast<type *>();
43   - const type *in0 = input_items[0].cast<const type *>();
44   -
45   - for (size_t n = 1; n < input_items.size(); n++){
46   - const type *in = input_items[n].cast<const type *>();
47   - for (size_t i = 0; i < n_nums; i++){
48   - out[i] = in0[i] * in[i];
49   - }
50   - in0 = out; //for next input, we do output *= input
51   - }
52   -
53   - return output_items[0].size();
54   - }
55   -};
56   -
57   -/***********************************************************************
58   - * Multiplier implementation with complex float32 - calls volk
59   - **********************************************************************/
60   -template <>
61   -struct multiply_work <std::complex<float> >
62   -{
63   - size_t multiple(void){return volk_get_alignment();}
64   - size_t operator()(
65   - const size_t vlen,
66   - const gnuradio::block::InputItems &input_items,
67   - const gnuradio::block::OutputItems &output_items
68   - ){
69   - const size_t n_nums = output_items[0].size() * vlen;
70   - std::complex<float> *out = output_items[0].cast<std::complex<float> *>();
71   - const std::complex<float> *in0 = input_items[0].cast<const std::complex<float> *>();
72   -
73   - for (size_t n = 1; n < input_items.size(); n++){
74   - const std::complex<float> *in = input_items[n].cast<const std::complex<float> *>();
75   - volk_32fc_x2_multiply_32fc_a(out, in0, in, n_nums);
76   - in0 = out; //for next input, we do output += input
77   - }
78   - return output_items[0].size();
79   - }
80   -};
81   -
82   -/***********************************************************************
83   - * Multiplier implementation with float32 - calls volk
84   - **********************************************************************/
85   -template <>
86   -struct multiply_work <float>
87   -{
88   - size_t multiple(void){return volk_get_alignment();}
89   - size_t operator()(
90   - const size_t vlen,
91   - const gnuradio::block::InputItems &input_items,
92   - const gnuradio::block::OutputItems &output_items
93   - ){
94   - const size_t n_nums = output_items[0].size() * vlen;
95   - float *out = output_items[0].cast<float *>();
96   - const float *in0 = input_items[0].cast<const float *>();
97   -
98   - for (size_t n = 1; n < input_items.size(); n++){
99   - const float *in = input_items[n].cast<const float *>();
100   - volk_32f_x2_multiply_32f_a(out, in0, in, n_nums);
101   - in0 = out; //for next input, we do output += input
102   - }
103   - return output_items[0].size();
104   - }
105   -};
106   -
107   -/***********************************************************************
108 31 * Templated multipler class
109 32 **********************************************************************/
110 33 template <typename type>
@@ -118,24 +41,103 @@ class multiply_generic : public multiply{
118 41 ),
119 42 _vlen(vlen)
120 43 {
121   - const int alignment_multiple = _work.multiple() / (sizeof(type)*vlen);
  44 + const int alignment_multiple = get_work_multiple() / (sizeof(type)*vlen);
122 45 set_output_multiple(std::max(1, alignment_multiple));
123 46 }
124 47
  48 + size_t get_work_multiple(void);
  49 +
125 50 int work(
126 51 const InputItems &input_items,
127 52 const OutputItems &output_items
128   - ){
129   - const size_t noutput_items = output_items[0].size();
130   - return _work(_vlen, input_items, output_items);
131   - }
  53 + );
132 54
133 55 private:
134 56 const size_t _vlen;
135   - multiply_work<type> _work;
136 57 };
137 58
138 59 /***********************************************************************
  60 + * Generic multiplier implementation
  61 + **********************************************************************/
  62 +template <typename type>
  63 +size_t multiply_generic<type>::get_work_multiple(void)
  64 +{
  65 + return 1;
  66 +}
  67 +
  68 +template <typename type>
  69 +int multiply_generic<type>::work(
  70 + const InputItems &input_items,
  71 + const OutputItems &output_items
  72 +){
  73 + const size_t n_nums = output_items[0].size() * _vlen;
  74 + type *out = output_items[0].cast<type *>();
  75 + const type *in0 = input_items[0].cast<const type *>();
  76 +
  77 + for (size_t n = 1; n < input_items.size(); n++){
  78 + const type *in = input_items[n].cast<const type *>();
  79 + for (size_t i = 0; i < n_nums; i++){
  80 + out[i] = in0[i] * in[i];
  81 + }
  82 + in0 = out; //for next input, we do output += input
  83 + }
  84 +
  85 + return output_items[0].size();
  86 +}
  87 +
  88 +/***********************************************************************
  89 + * Multiplier implementation with complex complex float32 - calls volk
  90 + **********************************************************************/
  91 +template <>
  92 +size_t multiply_generic<std::complex<float> >::get_work_multiple(void)
  93 +{
  94 + return volk_get_alignment();
  95 +}
  96 +
  97 +template <>
  98 +int multiply_generic<std::complex<float> >::work(
  99 + const InputItems &input_items,
  100 + const OutputItems &output_items
  101 +){
  102 + const size_t n_nums = output_items[0].size() * _vlen;
  103 + std::complex<float> *out = output_items[0].cast<std::complex<float> *>();
  104 + const std::complex<float> *in0 = input_items[0].cast<const std::complex<float> *>();
  105 +
  106 + for (size_t n = 1; n < input_items.size(); n++){
  107 + const std::complex<float> *in = input_items[n].cast<const std::complex<float> *>();
  108 + volk_32fc_x2_multiply_32fc_a(out, in0, in, n_nums);
  109 + in0 = out; //for next input, we do output += input
  110 + }
  111 + return output_items[0].size();
  112 +}
  113 +
  114 +/***********************************************************************
  115 + * Multiplier implementation with float32 - calls volk
  116 + **********************************************************************/
  117 +template <>
  118 +size_t multiply_generic<float>::get_work_multiple(void)
  119 +{
  120 + return volk_get_alignment();
  121 +}
  122 +
  123 +template <>
  124 +int multiply_generic<float>::work(
  125 + const InputItems &input_items,
  126 + const OutputItems &output_items
  127 +){
  128 + const size_t n_nums = output_items[0].size() * _vlen;
  129 + float *out = output_items[0].cast<float *>();
  130 + const float *in0 = input_items[0].cast<const float *>();
  131 +
  132 + for (size_t n = 1; n < input_items.size(); n++){
  133 + const float *in = input_items[n].cast<const float *>();
  134 + volk_32f_x2_multiply_32f_a(out, in0, in, n_nums);
  135 + in0 = out; //for next input, we do output += input
  136 + }
  137 + return output_items[0].size();
  138 +}
  139 +
  140 +/***********************************************************************
139 141 * factory function
140 142 **********************************************************************/
141 143 multiply::sptr multiply::make_fc32_fc32(const size_t num_inputs, const size_t vlen){
150 lib/multiply_const_v.cc
@@ -28,73 +28,6 @@
28 28 using namespace gnuradio::extras;
29 29
30 30 /***********************************************************************
31   - * Generic vlen == 1 multiplier implementation
32   - **********************************************************************/
33   -template <typename type>
34   -struct multiply_const_work{
35   - size_t multiple(void){return 1;}
36   - size_t operator()(
37   - const std::vector<type> &val,
38   - const gnuradio::block::InputItems &input_items,
39   - const gnuradio::block::OutputItems &output_items
40   - ){
41   - const size_t noutput_items = output_items[0].size();
42   - type *out = output_items[0].cast<type *>();
43   - const type *in = input_items[0].cast<const type *>();
44   -
45   - for (size_t i = 0; i < noutput_items; i++){
46   - out[i] = in[i] * val[0];
47   - }
48   -
49   - return noutput_items;
50   - }
51   -};
52   -
53   -/***********************************************************************
54   - * FC32 vlen == 1 multiplier implementation
55   - **********************************************************************/
56   -template <>
57   -struct multiply_const_work <std::complex<float> >
58   -{
59   - size_t multiple(void){return volk_get_alignment();}
60   - size_t operator()(
61   - const std::vector<std::complex<float> > &val,
62   - const gnuradio::block::InputItems &input_items,
63   - const gnuradio::block::OutputItems &output_items
64   - ){
65   - const size_t num_items = output_items[0].size();
66   - typedef std::complex<float> type;
67   - const type scalar = reinterpret_cast<const type *>(&val[0])[0];
68   - type *out = output_items[0].cast<type *>();
69   - const type *in = input_items[0].cast<const type *>();
70   - volk_32fc_s32fc_multiply_32fc_a(out, in, scalar, num_items);
71   - return num_items;
72   - }
73   -};
74   -
75   -/***********************************************************************
76   - * F32 vlen == 1 multiplier implementation
77   - **********************************************************************/
78   -template <>
79   -struct multiply_const_work <float>
80   -{
81   - size_t multiple(void){return volk_get_alignment();}
82   - size_t operator()(
83   - const std::vector<float> &val,
84   - const gnuradio::block::InputItems &input_items,
85   - const gnuradio::block::OutputItems &output_items
86   - ){
87   - const size_t num_items = output_items[0].size();
88   - typedef float type;
89   - const type scalar = reinterpret_cast<const type *>(&val[0])[0];
90   - type *out = output_items[0].cast<type *>();
91   - const type *in = input_items[0].cast<const type *>();
92   - volk_32f_s32f_multiply_32f_a(out, in, scalar, num_items);
93   - return num_items;
94   - }
95   -};
96   -
97   -/***********************************************************************
98 31 * Generic multiply const implementation
99 32 **********************************************************************/
100 33 template <typename type>
@@ -109,15 +42,22 @@ class multiply_const_generic : public multiply_const_v{
109 42 {
110 43 _val.resize(vec.size());
111 44 this->set_const(vec);
112   - const int alignment_multiple = _work.multiple() / (sizeof(type)*_val.size());
  45 + const int alignment_multiple = get_work_multiple() / (sizeof(type)*_val.size());
113 46 set_output_multiple(std::max(1, alignment_multiple));
114 47 }
115 48
  49 + size_t get_work_multiple(void);
  50 +
  51 + int work1(
  52 + const InputItems &input_items,
  53 + const OutputItems &output_items
  54 + );
  55 +
116 56 int work(
117 57 const InputItems &input_items,
118 58 const OutputItems &output_items
119 59 ){
120   - if (_val.size() == 1) return _work(_val, input_items, output_items);
  60 + if (_val.size() == 1) return work1(input_items, output_items);
121 61
122 62 const size_t noutput_items = output_items[0].size();
123 63 const size_t n_nums = noutput_items * _val.size();
@@ -149,10 +89,80 @@ class multiply_const_generic : public multiply_const_v{
149 89 private:
150 90 std::vector<std::complex<double> > _original_val;
151 91 std::vector<type> _val;
152   - multiply_const_work<type> _work;
153 92 };
154 93
155 94 /***********************************************************************
  95 + * Generic vlen == 1 multiplier implementation
  96 + **********************************************************************/
  97 +template <typename type>
  98 +size_t multiply_const_generic<type>::get_work_multiple(void)
  99 +{
  100 + return 1;
  101 +}
  102 +
  103 +template <typename type>
  104 +int multiply_const_generic<type>::work1(
  105 + const InputItems &input_items,
  106 + const OutputItems &output_items
  107 +){
  108 + const size_t noutput_items = output_items[0].size();
  109 + type *out = output_items[0].cast<type *>();
  110 + const type *in = input_items[0].cast<const type *>();
  111 +
  112 + for (size_t i = 0; i < noutput_items; i++){
  113 + out[i] = in[i] * _val[0];
  114 + }
  115 +
  116 + return noutput_items;
  117 +}
  118 +
  119 +/***********************************************************************
  120 + * FC32 vlen == 1 multiplier implementation
  121 + **********************************************************************/
  122 +template <>
  123 +size_t multiply_const_generic<std::complex<float> >::get_work_multiple(void)
  124 +{
  125 + return volk_get_alignment();
  126 +}
  127 +
  128 +template <>
  129 +int multiply_const_generic<std::complex<float> >::work1(
  130 + const InputItems &input_items,
  131 + const OutputItems &output_items
  132 +){
  133 + const size_t num_items = output_items[0].size();
  134 + typedef std::complex<float> type;
  135 + const type scalar = reinterpret_cast<const type *>(&_val[0])[0];
  136 + type *out = output_items[0].cast<type *>();
  137 + const type *in = input_items[0].cast<const type *>();
  138 + volk_32fc_s32fc_multiply_32fc_a(out, in, scalar, num_items);
  139 + return num_items;
  140 +}
  141 +
  142 +/***********************************************************************
  143 + * F32 vlen == 1 multiplier implementation
  144 + **********************************************************************/
  145 +template <>
  146 +size_t multiply_const_generic<float>::get_work_multiple(void)
  147 +{
  148 + return volk_get_alignment();
  149 +}
  150 +
  151 +template <>
  152 +int multiply_const_generic<float>::work1(
  153 + const InputItems &input_items,
  154 + const OutputItems &output_items
  155 +){
  156 + const size_t num_items = output_items[0].size();
  157 + typedef float type;
  158 + const type scalar = reinterpret_cast<const type *>(&_val[0])[0];
  159 + type *out = output_items[0].cast<type *>();
  160 + const type *in = input_items[0].cast<const type *>();
  161 + volk_32f_s32f_multiply_32f_a(out, in, scalar, num_items);
  162 + return num_items;
  163 +}
  164 +
  165 +/***********************************************************************
156 166 * factory function
157 167 **********************************************************************/
158 168 #define make_factory_function(suffix, type) \

0 comments on commit 0ead95c

Please sign in to comment.
Something went wrong with that request. Please try again.