diff options
Diffstat (limited to 'gr-trellis/lib')
34 files changed, 4713 insertions, 4105 deletions
diff --git a/gr-trellis/lib/base.cc b/gr-trellis/lib/base.cc index c5022dac83..15ccc80f75 100644 --- a/gr-trellis/lib/base.cc +++ b/gr-trellis/lib/base.cc @@ -26,61 +26,55 @@ #include <gnuradio/trellis/base.h> namespace gr { - namespace trellis { +namespace trellis { - bool - dec2base(unsigned int num, int base, std::vector<int> &s) - { - int l = s.size(); - unsigned int n=num; - for(int i=0;i<l;i++) { - s[l-i-1] = n % base; //MSB first - n /= base; - } - if(n!=0) { - printf("Number %d requires more than %d digits.",num,l); - return false; - } - else - return true; +bool dec2base(unsigned int num, int base, std::vector<int>& s) +{ + int l = s.size(); + unsigned int n = num; + for (int i = 0; i < l; i++) { + s[l - i - 1] = n % base; // MSB first + n /= base; } + if (n != 0) { + printf("Number %d requires more than %d digits.", num, l); + return false; + } else + return true; +} - unsigned int - base2dec(const std::vector<int> &s, int base) - { - int l = s.size(); - unsigned int num=0; - for(int i=0;i<l;i++) - num=num*base+s[i]; - return num; - } +unsigned int base2dec(const std::vector<int>& s, int base) +{ + int l = s.size(); + unsigned int num = 0; + for (int i = 0; i < l; i++) + num = num * base + s[i]; + return num; +} - bool - dec2bases(unsigned int num, const std::vector<int> &bases, std::vector<int> &s) - { - int l = s.size(); - unsigned int n=num; - for(int i=0;i<l;i++) { - s[l-i-1] = n % bases[l-i-1]; - n /= bases[l-i-1]; - } - if(n!=0) { - printf("Number %d requires more than %d digits.",num,l); - return false; - } - else - return true; +bool dec2bases(unsigned int num, const std::vector<int>& bases, std::vector<int>& s) +{ + int l = s.size(); + unsigned int n = num; + for (int i = 0; i < l; i++) { + s[l - i - 1] = n % bases[l - i - 1]; + n /= bases[l - i - 1]; } + if (n != 0) { + printf("Number %d requires more than %d digits.", num, l); + return false; + } else + return true; +} - unsigned int - bases2dec(const std::vector<int> &s, const std::vector<int> &bases) - { - int l = s.size(); - unsigned int num=0; - for(int i=0;i<l;i++) - num = num * bases[i] + s[i]; - return num; - } +unsigned int bases2dec(const std::vector<int>& s, const std::vector<int>& bases) +{ + int l = s.size(); + unsigned int num = 0; + for (int i = 0; i < l; i++) + num = num * bases[i] + s[i]; + return num; +} - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/calc_metric.cc b/gr-trellis/lib/calc_metric.cc index bdbb13ea08..587edd437e 100644 --- a/gr-trellis/lib/calc_metric.cc +++ b/gr-trellis/lib/calc_metric.cc @@ -25,224 +25,252 @@ #include <gnuradio/trellis/calc_metric.h> namespace gr { - namespace trellis { - - template <class T> - void calc_metric(int O, int D, const std::vector<T> &TABLE, const T *input, - float *metric, digital::trellis_metric_type_t type) - { - float minm = FLT_MAX; - int minmi = 0; - - switch(type) { - case digital::TRELLIS_EUCLIDEAN: - for(int o = 0; o < O; o++) { - metric[o] = 0.0; - for(int m = 0; m < D; m++) { - T s = input[m]-TABLE[o*D+m]; - //gr_complex sc(1.0*s,0); - //metric[o] += (sc*conj(sc)).real(); - metric[o] += s * s; - } - } - break; - case digital::TRELLIS_HARD_SYMBOL: - for(int o = 0; o < O; o++) { - metric[o] = 0.0; - for(int m = 0; m < D; m++) { - T s = input[m]-TABLE[o*D+m]; - //gr_complex sc(1.0*s,0); - //metric[o] + =(sc*conj(sc)).real(); - metric[o] += s * s; - } - if(metric[o] < minm) { - minm = metric[o]; - minmi = o; - } - } - for(int o = 0; o < O; o++) { - metric[o] = (o == minmi ? 0.0 : 1.0); - } - break; - case digital::TRELLIS_HARD_BIT: - throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); - break; - default: - throw std::runtime_error("calc_metric: Invalid metric type."); - } +namespace trellis { + +template <class T> +void calc_metric(int O, + int D, + const std::vector<T>& TABLE, + const T* input, + float* metric, + digital::trellis_metric_type_t type) +{ + float minm = FLT_MAX; + int minmi = 0; + + switch (type) { + case digital::TRELLIS_EUCLIDEAN: + for (int o = 0; o < O; o++) { + metric[o] = 0.0; + for (int m = 0; m < D; m++) { + T s = input[m] - TABLE[o * D + m]; + // gr_complex sc(1.0*s,0); + // metric[o] += (sc*conj(sc)).real(); + metric[o] += s * s; + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for (int o = 0; o < O; o++) { + metric[o] = 0.0; + for (int m = 0; m < D; m++) { + T s = input[m] - TABLE[o * D + m]; + // gr_complex sc(1.0*s,0); + // metric[o] + =(sc*conj(sc)).real(); + metric[o] += s * s; + } + if (metric[o] < minm) { + minm = metric[o]; + minmi = o; + } + } + for (int o = 0; o < O; o++) { + metric[o] = (o == minmi ? 0.0 : 1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error( + "calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); } +} + +template void calc_metric<char>(int O, + int D, + const std::vector<char>& TABLE, + const char* input, + float* metric, + digital::trellis_metric_type_t type); + +template void calc_metric<short>(int O, + int D, + const std::vector<short>& TABLE, + const short* input, + float* metric, + digital::trellis_metric_type_t type); + +template void calc_metric<int>(int O, + int D, + const std::vector<int>& TABLE, + const int* input, + float* metric, + digital::trellis_metric_type_t type); + +template void calc_metric<float>(int O, + int D, + const std::vector<float>& TABLE, + const float* input, + float* metric, + digital::trellis_metric_type_t type); - template - void calc_metric<char>(int O, int D, const std::vector<char> &TABLE, const char *input, float *metric, digital::trellis_metric_type_t type); - - template - void calc_metric<short>(int O, int D, const std::vector<short> &TABLE, const short *input, float *metric, digital::trellis_metric_type_t type); - - template void calc_metric<int>(int O, int D, const std::vector<int> &TABLE, const int *input, float *metric, digital::trellis_metric_type_t type); - - template void calc_metric<float>(int O, int D, const std::vector<float> &TABLE, const float *input, float *metric, digital::trellis_metric_type_t type); - - /* - void calc_metric(int O, int D, const std::vector<short> &TABLE, const short *input, float *metric, digital::trellis_metric_type_t type) - { - float minm = FLT_MAX; - int minmi = 0; - - switch(type) { - case digital::TRELLIS_EUCLIDEAN: - for(int o = 0; o < O; o++) { - metric[o] = 0.0; - for(int m = 0; m < D; m++) { - float s = input[m]-TABLE[o*D+m]; - metric[o] += s*s; - } - } - break; - case digital::TRELLIS_HARD_SYMBOL: - for(int o = 0; o < O; o++) { - metric[o] = 0.0; - for(int m = 0; m < D; m++) { - float s = input[m]-TABLE[o*D+m]; - metric[o] += s*s; - } - if(metric[o] < minm) { - minm = metric[o]; - minmi = o; - } - } - for(int o = 0; o < O; o++) { - metric[o] = (o == minmi ? 0.0 : 1.0); - } - break; - case digital::TRELLIS_HARD_BIT: - throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); - break; - default: - throw std::runtime_error("calc_metric: Invalid metric type."); +/* +void calc_metric(int O, int D, const std::vector<short> &TABLE, const short *input, float +*metric, digital::trellis_metric_type_t type) +{ + float minm = FLT_MAX; + int minmi = 0; + + switch(type) { + case digital::TRELLIS_EUCLIDEAN: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + float s = input[m]-TABLE[o*D+m]; + metric[o] += s*s; + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + float s = input[m]-TABLE[o*D+m]; + metric[o] += s*s; + } + if(metric[o] < minm) { + minm = metric[o]; + minmi = o; } } + for(int o = 0; o < O; o++) { + metric[o] = (o == minmi ? 0.0 : 1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } +} - void calc_metric(int O, int D, const std::vector<int> &TABLE, const int *input, - float *metric, digital::trellis_metric_type_t type) - { - float minm = FLT_MAX; - int minmi = 0; - - switch(type){ - case digital::TRELLIS_EUCLIDEAN: - for(int o=0;o<O;o++) { - metric[o]=0.0; - for(int m=0;m<D;m++) { - float s=input[m]-TABLE[o*D+m]; - metric[o]+=s*s; - } - } - break; - case digital::TRELLIS_HARD_SYMBOL: - for(int o=0;o<O;o++) { - metric[o]=0.0; - for(int m=0;m<D;m++) { - float s=input[m]-TABLE[o*D+m]; - metric[o]+=s*s; - } - if(metric[o]<minm) { - minm=metric[o]; - minmi=o; - } - } - for(int o=0;o<O;o++) { - metric[o] = (o==minmi?0.0:1.0); - } - break; - case digital::TRELLIS_HARD_BIT: - throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); - break; - default: - throw std::runtime_error("calc_metric: Invalid metric type."); +void calc_metric(int O, int D, const std::vector<int> &TABLE, const int *input, + float *metric, digital::trellis_metric_type_t type) +{ + float minm = FLT_MAX; + int minmi = 0; + + switch(type){ + case digital::TRELLIS_EUCLIDEAN: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; + } + if(metric[o]<minm) { + minm=metric[o]; + minmi=o; } } + for(int o=0;o<O;o++) { + metric[o] = (o==minmi?0.0:1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } +} + +void calc_metric(int O, int D, const std::vector<float> &TABLE, const float *input, + float *metric, digital::trellis_metric_type_t type) +{ + float minm = FLT_MAX; + int minmi = 0; - void calc_metric(int O, int D, const std::vector<float> &TABLE, const float *input, - float *metric, digital::trellis_metric_type_t type) - { - float minm = FLT_MAX; - int minmi = 0; - - switch(type) { - case digital::TRELLIS_EUCLIDEAN: - for(int o=0;o<O;o++) { - metric[o]=0.0; - for(int m=0;m<D;m++) { - float s=input[m]-TABLE[o*D+m]; - metric[o]+=s*s; - } - } - break; - case digital::TRELLIS_HARD_SYMBOL: - for(int o=0;o<O;o++) { - metric[o]=0.0; - for(int m=0;m<D;m++) { - float s=input[m]-TABLE[o*D+m]; - metric[o]+=s*s; - } - if(metric[o]<minm) { - minm=metric[o]; - minmi=o; - } - } - for(int o=0;o<O;o++) { - metric[o] = (o==minmi?0.0:1.0); - } - break; - case digital::TRELLIS_HARD_BIT: - throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); - break; - default: - throw std::runtime_error("calc_metric: Invalid metric type."); + switch(type) { + case digital::TRELLIS_EUCLIDEAN: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; } } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; + } + if(metric[o]<minm) { + minm=metric[o]; + minmi=o; + } + } + for(int o=0;o<O;o++) { + metric[o] = (o==minmi?0.0:1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } +} */ - void calc_metric(int O, int D, const std::vector<gr_complex> &TABLE, const gr_complex *input, - float *metric, digital::trellis_metric_type_t type) - { - float minm = FLT_MAX; - int minmi = 0; - - switch(type) { - case digital::TRELLIS_EUCLIDEAN: - for(int o = 0; o < O; o++) { - metric[o] = 0.0; - for(int m = 0; m < D; m++) { - gr_complex s = input[m]-TABLE[o*D+m]; - metric[o] += s.real()*s.real()+s.imag()*s.imag(); - } - } - break; - case digital::TRELLIS_HARD_SYMBOL: - for(int o = 0; o < O; o++) { - metric[o] = 0.0; - for(int m = 0; m < D; m++) { - gr_complex s = input[m]-TABLE[o*D+m]; - metric[o] += s.real()*s.real()+s.imag()*s.imag(); - } - if(metric[o] < minm) { - minm = metric[o]; - minmi = o; - } - } - for(int o = 0; o < O; o++) { - metric[o] = (o == minmi ? 0.0 : 1.0); - } - break; - case digital::TRELLIS_HARD_BIT: - throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); - break; - default: - throw std::runtime_error("calc_metric: Invalid metric type."); - } +void calc_metric(int O, + int D, + const std::vector<gr_complex>& TABLE, + const gr_complex* input, + float* metric, + digital::trellis_metric_type_t type) +{ + float minm = FLT_MAX; + int minmi = 0; + + switch (type) { + case digital::TRELLIS_EUCLIDEAN: + for (int o = 0; o < O; o++) { + metric[o] = 0.0; + for (int m = 0; m < D; m++) { + gr_complex s = input[m] - TABLE[o * D + m]; + metric[o] += s.real() * s.real() + s.imag() * s.imag(); + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for (int o = 0; o < O; o++) { + metric[o] = 0.0; + for (int m = 0; m < D; m++) { + gr_complex s = input[m] - TABLE[o * D + m]; + metric[o] += s.real() * s.real() + s.imag() * s.imag(); + } + if (metric[o] < minm) { + minm = metric[o]; + minmi = o; + } + } + for (int o = 0; o < O; o++) { + metric[o] = (o == minmi ? 0.0 : 1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error( + "calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); } +} - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ - diff --git a/gr-trellis/lib/constellation_metrics_cf_impl.cc b/gr-trellis/lib/constellation_metrics_cf_impl.cc index 79dbe414bd..6658e0e518 100644 --- a/gr-trellis/lib/constellation_metrics_cf_impl.cc +++ b/gr-trellis/lib/constellation_metrics_cf_impl.cc @@ -31,66 +31,62 @@ #include <iostream> namespace gr { - namespace trellis { +namespace trellis { - constellation_metrics_cf::sptr - constellation_metrics_cf::make(digital::constellation_sptr constellation, - digital::trellis_metric_type_t TYPE) - { - return gnuradio::get_initial_sptr - (new constellation_metrics_cf_impl(constellation, TYPE)); - } - - constellation_metrics_cf_impl::constellation_metrics_cf_impl(digital::constellation_sptr constellation, - digital::trellis_metric_type_t TYPE) - : block("constellation_metrics_cf", - io_signature::make(1, -1, sizeof(gr_complex)), - io_signature::make(1, -1, sizeof(float))), - d_constellation(constellation), - d_TYPE(TYPE), - d_O(constellation->arity()), - d_D(constellation->dimensionality()) - { - set_relative_rate((uint64_t)d_O, (uint64_t)d_D); - set_output_multiple((int)d_O); - } +constellation_metrics_cf::sptr +constellation_metrics_cf::make(digital::constellation_sptr constellation, + digital::trellis_metric_type_t TYPE) +{ + return gnuradio::get_initial_sptr( + new constellation_metrics_cf_impl(constellation, TYPE)); +} - constellation_metrics_cf_impl::~constellation_metrics_cf_impl() - { - } +constellation_metrics_cf_impl::constellation_metrics_cf_impl( + digital::constellation_sptr constellation, digital::trellis_metric_type_t TYPE) + : block("constellation_metrics_cf", + io_signature::make(1, -1, sizeof(gr_complex)), + io_signature::make(1, -1, sizeof(float))), + d_constellation(constellation), + d_TYPE(TYPE), + d_O(constellation->arity()), + d_D(constellation->dimensionality()) +{ + set_relative_rate((uint64_t)d_O, (uint64_t)d_D); + set_output_multiple((int)d_O); +} - void - constellation_metrics_cf_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - assert(noutput_items % d_O == 0); +constellation_metrics_cf_impl::~constellation_metrics_cf_impl() {} - unsigned int input_required = d_D * noutput_items / d_O; - unsigned int ninputs = ninput_items_required.size(); - for(unsigned int i = 0; i < ninputs; i++) - ninput_items_required[i] = input_required; - } +void constellation_metrics_cf_impl::forecast(int noutput_items, + gr_vector_int& ninput_items_required) +{ + assert(noutput_items % d_O == 0); - int - constellation_metrics_cf_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - unsigned int nstreams = input_items.size(); + unsigned int input_required = d_D * noutput_items / d_O; + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = input_required; +} - for(unsigned int m=0;m<nstreams;m++) { - const gr_complex *in = (gr_complex*)input_items[m]; - float *out = (float*)output_items[m]; +int constellation_metrics_cf_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + unsigned int nstreams = input_items.size(); - for(unsigned int i = 0; i < noutput_items / d_O ; i++) { - d_constellation->calc_metric(&(in[i*d_D]), &(out[i*d_O]), d_TYPE); - } - } + for (unsigned int m = 0; m < nstreams; m++) { + const gr_complex* in = (gr_complex*)input_items[m]; + float* out = (float*)output_items[m]; - consume_each(d_D * noutput_items / d_O); - return noutput_items; + for (unsigned int i = 0; i < noutput_items / d_O; i++) { + d_constellation->calc_metric(&(in[i * d_D]), &(out[i * d_O]), d_TYPE); + } } - } /* namespace trellis */ + consume_each(d_D * noutput_items / d_O); + return noutput_items; +} + +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/constellation_metrics_cf_impl.h b/gr-trellis/lib/constellation_metrics_cf_impl.h index a2f165857b..8a3b367c6f 100644 --- a/gr-trellis/lib/constellation_metrics_cf_impl.h +++ b/gr-trellis/lib/constellation_metrics_cf_impl.h @@ -27,31 +27,30 @@ #include <gnuradio/trellis/constellation_metrics_cf.h> namespace gr { - namespace trellis { - - class constellation_metrics_cf_impl : public constellation_metrics_cf - { - private: - digital::constellation_sptr d_constellation; - digital::trellis_metric_type_t d_TYPE; - unsigned int d_O; - unsigned int d_D; - - public: - constellation_metrics_cf_impl(digital::constellation_sptr constellation, - digital::trellis_metric_type_t TYPE); - ~constellation_metrics_cf_impl(); - - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); - - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } /* namespace trellis */ +namespace trellis { + +class constellation_metrics_cf_impl : public constellation_metrics_cf +{ +private: + digital::constellation_sptr d_constellation; + digital::trellis_metric_type_t d_TYPE; + unsigned int d_O; + unsigned int d_D; + +public: + constellation_metrics_cf_impl(digital::constellation_sptr constellation, + digital::trellis_metric_type_t TYPE); + ~constellation_metrics_cf_impl(); + + void forecast(int noutput_items, gr_vector_int& ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; + +} /* namespace trellis */ } /* namespace gr */ #endif /* INCLUDED_TRELLIS_CONSTELLATION_METRICS_CF_IMPL_H */ diff --git a/gr-trellis/lib/core_algorithms.cc b/gr-trellis/lib/core_algorithms.cc index b26ee331f2..d12896d342 100644 --- a/gr-trellis/lib/core_algorithms.cc +++ b/gr-trellis/lib/core_algorithms.cc @@ -27,1337 +27,1720 @@ #include <gnuradio/trellis/calc_metric.h> namespace gr { - namespace trellis { +namespace trellis { + +static const float INF = 1.0e9; + +float min(float a, float b) { return a <= b ? a : b; } + +float min_star(float a, float b) +{ + return (a <= b ? a : b) - log(1 + exp(a <= b ? a - b : b - a)); +} + +template <class T> +void viterbi_algorithm(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + const float* in, + T* out) //, + // std::vector<int> &trace) +{ + std::vector<int> trace(S * K); + std::vector<float> alpha(S * 2); + int alphai; + float norm, mm, minm; + int minmi; + int st; + + if (S0 < 0) { // initial state not specified + for (int i = 0; i < S; i++) + alpha[0 * S + i] = 0; + } else { + for (int i = 0; i < S; i++) + alpha[0 * S + i] = INF; + alpha[0 * S + S0] = 0.0; + } - static const float INF = 1.0e9; + alphai = 0; + for (int k = 0; k < K; k++) { + norm = INF; + for (int j = 0; j < S; j++) { // for each next state do ACS + minm = INF; + minmi = 0; + for (unsigned int i = 0; i < PS[j].size(); i++) { + // int i0 = j*I+i; + if ((mm = alpha[alphai * S + PS[j][i]] + + in[k * O + OS[PS[j][i] * I + PI[j][i]]]) < minm) + minm = mm, minmi = i; + } + trace[k * S + j] = minmi; + alpha[((alphai + 1) % 2) * S + j] = minm; + if (minm < norm) + norm = minm; + } + for (int j = 0; j < S; j++) + alpha[((alphai + 1) % 2) * S + j] -= + norm; // normalize total metrics so they do not explode + alphai = (alphai + 1) % 2; + } - float - min(float a, float b) - { - return a <= b ? a : b; + if (SK < 0) { // final state not specified + minm = INF; + minmi = 0; + for (int i = 0; i < S; i++) + if ((mm = alpha[alphai * S + i]) < minm) + minm = mm, minmi = i; + st = minmi; + } else { + st = SK; } - float - min_star(float a, float b) - { - return (a <= b ? a : b)-log(1+exp(a <= b ? a-b : b-a)); + for (int k = K - 1; k >= 0; k--) { // traceback + int i0 = trace[k * S + st]; + out[k] = (T)PI[st][i0]; + st = PS[st][i0]; + } +} + +template void viterbi_algorithm<unsigned char>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + const float* in, + unsigned char* out); + +template void viterbi_algorithm<short>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + const float* in, + short* out); + +template void viterbi_algorithm<int>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + const float* in, + int* out); + +//============================================== + +template <class Ti, class To> +void viterbi_algorithm_combined(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<Ti>& TABLE, + digital::trellis_metric_type_t TYPE, + const Ti* in, + To* out) +{ + std::vector<int> trace(S * K); + std::vector<float> alpha(S * 2); + float* metric = new float[O]; + int alphai; + float norm, mm, minm; + int minmi; + int st; + + if (S0 < 0) { // initial state not specified + for (int i = 0; i < S; i++) + alpha[0 * S + i] = 0; + } else { + for (int i = 0; i < S; i++) + alpha[0 * S + i] = INF; + alpha[0 * S + S0] = 0.0; + } + + alphai = 0; + for (int k = 0; k < K; k++) { + calc_metric(O, D, TABLE, &(in[k * D]), metric, TYPE); // calc metrics + norm = INF; + for (int j = 0; j < S; j++) { // for each next state do ACS + minm = INF; + minmi = 0; + for (unsigned int i = 0; i < PS[j].size(); i++) { + // int i0 = j*I+i; + if ((mm = alpha[alphai * S + PS[j][i]] + + metric[OS[PS[j][i] * I + PI[j][i]]]) < minm) + minm = mm, minmi = i; + } + trace[k * S + j] = minmi; + alpha[((alphai + 1) % 2) * S + j] = minm; + if (minm < norm) + norm = minm; + } + for (int j = 0; j < S; j++) + alpha[((alphai + 1) % 2) * S + j] -= + norm; // normalize total metrics so they do not explode + alphai = (alphai + 1) % 2; } - template <class T> void - viterbi_algorithm(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - const float *in, T *out)//, - //std::vector<int> &trace) - { - std::vector<int> trace(S*K); - std::vector<float> alpha(S*2); - int alphai; - float norm,mm,minm; - int minmi; - int st; - - if(S0<0) { // initial state not specified - for(int i=0;i<S;i++) alpha[0*S+i]=0; - } - else { - for(int i=0;i<S;i++) alpha[0*S+i]=INF; - alpha[0*S+S0]=0.0; - } - - alphai=0; - for(int k=0;k<K;k++) { - norm=INF; - for(int j=0;j<S;j++) { // for each next state do ACS - minm=INF; - minmi=0; - for(unsigned int i=0;i<PS[j].size();i++) { - //int i0 = j*I+i; - if((mm=alpha[alphai*S+PS[j][i]]+in[k*O+OS[PS[j][i]*I+PI[j][i]]])<minm) - minm=mm,minmi=i; - } - trace[k*S+j]=minmi; - alpha[((alphai+1)%2)*S+j]=minm; - if(minm<norm) norm=minm; - } - for(int j=0;j<S;j++) - alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode - alphai=(alphai+1)%2; - } - - if(SK<0) { // final state not specified - minm=INF; - minmi=0; - for(int i=0;i<S;i++) - if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i; - st=minmi; - } - else { - st=SK; - } - - for(int k=K-1;k>=0;k--) { // traceback - int i0=trace[k*S+st]; - out[k]= (T) PI[st][i0]; - st=PS[st][i0]; - } + if (SK < 0) { // final state not specified + minm = INF; + minmi = 0; + for (int i = 0; i < S; i++) + if ((mm = alpha[alphai * S + i]) < minm) + minm = mm, minmi = i; + st = minmi; + } else { + st = SK; } - template void - viterbi_algorithm<unsigned char>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - const float *in, unsigned char *out); - - template void - viterbi_algorithm<short>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - const float *in, short *out); - - template void - viterbi_algorithm<int>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - const float *in, int *out); - - //============================================== - - template <class Ti, class To> void - viterbi_algorithm_combined(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<Ti> &TABLE, - digital::trellis_metric_type_t TYPE, - const Ti *in, To *out) - { - std::vector<int> trace(S*K); - std::vector<float> alpha(S*2); - float *metric = new float[O]; - int alphai; - float norm,mm,minm; - int minmi; - int st; - - if(S0<0) { // initial state not specified - for(int i=0;i<S;i++) alpha[0*S+i]=0; - } - else { - for(int i=0;i<S;i++) alpha[0*S+i]=INF; - alpha[0*S+S0]=0.0; - } - - alphai=0; - for(int k=0;k<K;k++) { - calc_metric(O, D, TABLE, &(in[k*D]), metric,TYPE); // calc metrics - norm=INF; - for(int j=0;j<S;j++) { // for each next state do ACS - minm=INF; - minmi=0; - for(unsigned int i=0;i<PS[j].size();i++) { - //int i0 = j*I+i; - if((mm=alpha[alphai*S+PS[j][i]]+metric[OS[PS[j][i]*I+PI[j][i]]])<minm) - minm=mm,minmi=i; - } - trace[k*S+j]=minmi; - alpha[((alphai+1)%2)*S+j]=minm; - if(minm<norm) norm=minm; - } - for(int j=0;j<S;j++) - alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode - alphai=(alphai+1)%2; - } - - if(SK<0) { // final state not specified - minm=INF; - minmi=0; - for(int i=0;i<S;i++) - if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i; - st=minmi; - } - else { - st=SK; - } - - for(int k=K-1;k>=0;k--) { // traceback - int i0=trace[k*S+st]; - out[k]= (To) PI[st][i0]; - st=PS[st][i0]; - } - - delete [] metric; + for (int k = K - 1; k >= 0; k--) { // traceback + int i0 = trace[k * S + st]; + out[k] = (To)PI[st][i0]; + st = PS[st][i0]; } - // Ti = s i f c - // To = b s i - - //--------------- - - template void - viterbi_algorithm_combined<char,unsigned char>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<char> &TABLE, - digital::trellis_metric_type_t TYPE, - const char *in, unsigned char *out); - - template void - viterbi_algorithm_combined<short,unsigned char>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<short> &TABLE, - digital::trellis_metric_type_t TYPE, - const short *in, unsigned char *out); - - template void - viterbi_algorithm_combined<int,unsigned char>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<int> &TABLE, - digital::trellis_metric_type_t TYPE, - const int *in, unsigned char *out); - - template void - viterbi_algorithm_combined<float,unsigned char>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *in, unsigned char *out); - - template void - viterbi_algorithm_combined<gr_complex,unsigned char>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t TYPE, - const gr_complex *in, unsigned char *out); - - //--------------- - - template void - viterbi_algorithm_combined<char,short>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<char> &TABLE, - digital::trellis_metric_type_t TYPE, - const char *in, short *out); - - template void - viterbi_algorithm_combined<short,short>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<short> &TABLE, - digital::trellis_metric_type_t TYPE, - const short *in, short *out); - - template void - viterbi_algorithm_combined<int,short>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<int> &TABLE, - digital::trellis_metric_type_t TYPE, - const int *in, short *out); - - template void - viterbi_algorithm_combined<float,short>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *in, short *out); - - template void - viterbi_algorithm_combined<gr_complex,short>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t TYPE, - const gr_complex *in, short *out); - - //-------------- - - template void - viterbi_algorithm_combined<char,int>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<char> &TABLE, - digital::trellis_metric_type_t TYPE, - const char *in, int *out); - - template void - viterbi_algorithm_combined<short,int>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<short> &TABLE, - digital::trellis_metric_type_t TYPE, - const short *in, int *out); - - template void - viterbi_algorithm_combined<int,int>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<int> &TABLE, - digital::trellis_metric_type_t TYPE, - const int *in, int *out); - - template void - viterbi_algorithm_combined<float,int>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *in, int *out); - - template void - viterbi_algorithm_combined<gr_complex,int>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - int D, - const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t TYPE, - const gr_complex *in, int *out); - - //=============================================== - - void - siso_algorithm(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - bool POSTI, bool POSTO, - float (*p2mymin)(float,float), - const float *priori, const float *prioro, float *post//, - //std::vector<float> &alpha, - //std::vector<float> &beta - ) - { - float norm,mm,minm; - std::vector<float> alpha(S*(K+1)); - std::vector<float> beta(S*(K+1)); - - if(S0<0) { // initial state not specified - for(int i=0;i<S;i++) alpha[0*S+i]=0; - } - else { - for(int i=0;i<S;i++) alpha[0*S+i]=INF; - alpha[0*S+S0]=0.0; - } - - for(int k=0;k<K;k++) { // forward recursion - norm=INF; - for(int j=0;j<S;j++) { - minm=INF; - for(unsigned int i=0;i<PS[j].size();i++) { - //int i0 = j*I+i; - mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]]; - minm=(*p2mymin)(minm,mm); - } - alpha[(k+1)*S+j]=minm; - if(minm<norm) norm=minm; - } - for(int j=0;j<S;j++) - alpha[(k+1)*S+j]-=norm; // normalize total metrics so they do not explode - } - - if(SK<0) { // final state not specified - for(int i=0;i<S;i++) beta[K*S+i]=0; - } - else { - for(int i=0;i<S;i++) beta[K*S+i]=INF; - beta[K*S+SK]=0.0; - } - - for(int k=K-1;k>=0;k--) { // backward recursion - norm=INF; - for(int j=0;j<S;j++) { - minm=INF; - for(int i=0;i<I;i++) { - int i0 = j*I+i; - mm=beta[(k+1)*S+NS[i0]]+priori[k*I+i]+prioro[k*O+OS[i0]]; - minm=(*p2mymin)(minm,mm); - } - beta[k*S+j]=minm; - if(minm<norm) norm=minm; - } - for(int j=0;j<S;j++) - beta[k*S+j]-=norm; // normalize total metrics so they do not explode - } - - if(POSTI && POSTO) - { - for(int k=0;k<K;k++) { // input combining - norm=INF; - for(int i=0;i<I;i++) { - minm=INF; - for(int j=0;j<S;j++) { - mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; - minm=(*p2mymin)(minm,mm); - } - post[k*(I+O)+i]=minm; - if(minm<norm) norm=minm; - } - for(int i=0;i<I;i++) - post[k*(I+O)+i]-=norm; // normalize metrics - } - - for(int k=0;k<K;k++) { // output combining - norm=INF; - for(int n=0;n<O;n++) { - minm=INF; - for(int j=0;j<S;j++) { - for(int i=0;i<I;i++) { - mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); - minm=(*p2mymin)(minm,mm); - } - } - post[k*(I+O)+I+n]=minm; - if(minm<norm) norm=minm; - } - for(int n=0;n<O;n++) - post[k*(I+O)+I+n]-=norm; // normalize metrics - } - } - else if(POSTI) - { - for(int k=0;k<K;k++) { // input combining - norm=INF; - for(int i=0;i<I;i++) { - minm=INF; - for(int j=0;j<S;j++) { - mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; - minm=(*p2mymin)(minm,mm); - } - post[k*I+i]=minm; - if(minm<norm) norm=minm; - } - for(int i=0;i<I;i++) - post[k*I+i]-=norm; // normalize metrics - } - } - else if(POSTO) - { - for(int k=0;k<K;k++) { // output combining - norm=INF; - for(int n=0;n<O;n++) { - minm=INF; - for(int j=0;j<S;j++) { - for(int i=0;i<I;i++) { - mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); - minm=(*p2mymin)(minm,mm); - } - } - post[k*O+n]=minm; - if(minm<norm) norm=minm; - } - for(int n=0;n<O;n++) - post[k*O+n]-=norm; // normalize metrics - } - } - else - throw std::runtime_error("Not both POSTI and POSTO can be false."); + delete[] metric; +} + +// Ti = s i f c +// To = b s i + +//--------------- + +template void +viterbi_algorithm_combined<char, unsigned char>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<char>& TABLE, + digital::trellis_metric_type_t TYPE, + const char* in, + unsigned char* out); + +template void +viterbi_algorithm_combined<short, unsigned char>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<short>& TABLE, + digital::trellis_metric_type_t TYPE, + const short* in, + unsigned char* out); + +template void +viterbi_algorithm_combined<int, unsigned char>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<int>& TABLE, + digital::trellis_metric_type_t TYPE, + const int* in, + unsigned char* out); + +template void +viterbi_algorithm_combined<float, unsigned char>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* in, + unsigned char* out); + +template void viterbi_algorithm_combined<gr_complex, unsigned char>( + int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t TYPE, + const gr_complex* in, + unsigned char* out); + +//--------------- + +template void +viterbi_algorithm_combined<char, short>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<char>& TABLE, + digital::trellis_metric_type_t TYPE, + const char* in, + short* out); + +template void +viterbi_algorithm_combined<short, short>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<short>& TABLE, + digital::trellis_metric_type_t TYPE, + const short* in, + short* out); + +template void +viterbi_algorithm_combined<int, short>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<int>& TABLE, + digital::trellis_metric_type_t TYPE, + const int* in, + short* out); + +template void +viterbi_algorithm_combined<float, short>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* in, + short* out); + +template void +viterbi_algorithm_combined<gr_complex, short>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t TYPE, + const gr_complex* in, + short* out); + +//-------------- + +template void +viterbi_algorithm_combined<char, int>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<char>& TABLE, + digital::trellis_metric_type_t TYPE, + const char* in, + int* out); + +template void +viterbi_algorithm_combined<short, int>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<short>& TABLE, + digital::trellis_metric_type_t TYPE, + const short* in, + int* out); + +template void +viterbi_algorithm_combined<int, int>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<int>& TABLE, + digital::trellis_metric_type_t TYPE, + const int* in, + int* out); + +template void +viterbi_algorithm_combined<float, int>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* in, + int* out); + +template void +viterbi_algorithm_combined<gr_complex, int>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t TYPE, + const gr_complex* in, + int* out); + +//=============================================== + +void siso_algorithm(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + float (*p2mymin)(float, float), + const float* priori, + const float* prioro, + float* post //, + // std::vector<float> &alpha, + // std::vector<float> &beta +) +{ + float norm, mm, minm; + std::vector<float> alpha(S * (K + 1)); + std::vector<float> beta(S * (K + 1)); + + if (S0 < 0) { // initial state not specified + for (int i = 0; i < S; i++) + alpha[0 * S + i] = 0; + } else { + for (int i = 0; i < S; i++) + alpha[0 * S + i] = INF; + alpha[0 * S + S0] = 0.0; } - //=========================================================== - - template <class T> void - siso_algorithm_combined(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - bool POSTI, bool POSTO, - float (*p2mymin)(float,float), - int D, - const std::vector<T> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *priori, const T *observations, float *post) - { - float norm,mm,minm; - std::vector<float> alpha(S*(K+1)); - std::vector<float> beta(S*(K+1)); - float *prioro = new float[O*K]; - - if(S0<0) { // initial state not specified - for(int i=0;i<S;i++) alpha[0*S+i]=0; - } - else { - for(int i=0;i<S;i++) alpha[0*S+i]=INF; - alpha[0*S+S0]=0.0; - } - - for(int k=0;k<K;k++) { // forward recursion - calc_metric(O, D, TABLE, &(observations[k*D]), &(prioro[k*O]),TYPE); // calc metrics - norm=INF; - for(int j=0;j<S;j++) { - minm=INF; - for(unsigned int i=0;i<PS[j].size();i++) { - //int i0 = j*I+i; - mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]]; - minm=(*p2mymin)(minm,mm); - } - alpha[(k+1)*S+j]=minm; - if(minm<norm) norm=minm; - } - for(int j=0;j<S;j++) - alpha[(k+1)*S+j]-=norm; // normalize total metrics so they do not explode - } - - if(SK<0) { // final state not specified - for(int i=0;i<S;i++) beta[K*S+i]=0; - } - else { - for(int i=0;i<S;i++) beta[K*S+i]=INF; - beta[K*S+SK]=0.0; - } - - for(int k=K-1;k>=0;k--) { // backward recursion - norm=INF; - for(int j=0;j<S;j++) { - minm=INF; - for(int i=0;i<I;i++) { - int i0 = j*I+i; - mm=beta[(k+1)*S+NS[i0]]+priori[k*I+i]+prioro[k*O+OS[i0]]; - minm=(*p2mymin)(minm,mm); - } - beta[k*S+j]=minm; - if(minm<norm) norm=minm; - } - for(int j=0;j<S;j++) - beta[k*S+j]-=norm; // normalize total metrics so they do not explode - } - - if(POSTI && POSTO) - { - for(int k=0;k<K;k++) { // input combining - norm=INF; - for(int i=0;i<I;i++) { - minm=INF; - for(int j=0;j<S;j++) { - mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; - minm=(*p2mymin)(minm,mm); - } - post[k*(I+O)+i]=minm; - if(minm<norm) norm=minm; - } - for(int i=0;i<I;i++) - post[k*(I+O)+i]-=norm; // normalize metrics - } - - for(int k=0;k<K;k++) { // output combining - norm=INF; - for(int n=0;n<O;n++) { - minm=INF; - for(int j=0;j<S;j++) { - for(int i=0;i<I;i++) { - mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); - minm=(*p2mymin)(minm,mm); + for (int k = 0; k < K; k++) { // forward recursion + norm = INF; + for (int j = 0; j < S; j++) { + minm = INF; + for (unsigned int i = 0; i < PS[j].size(); i++) { + // int i0 = j*I+i; + mm = alpha[k * S + PS[j][i]] + priori[k * I + PI[j][i]] + + prioro[k * O + OS[PS[j][i] * I + PI[j][i]]]; + minm = (*p2mymin)(minm, mm); + } + alpha[(k + 1) * S + j] = minm; + if (minm < norm) + norm = minm; + } + for (int j = 0; j < S; j++) + alpha[(k + 1) * S + j] -= + norm; // normalize total metrics so they do not explode + } + + if (SK < 0) { // final state not specified + for (int i = 0; i < S; i++) + beta[K * S + i] = 0; + } else { + for (int i = 0; i < S; i++) + beta[K * S + i] = INF; + beta[K * S + SK] = 0.0; + } + + for (int k = K - 1; k >= 0; k--) { // backward recursion + norm = INF; + for (int j = 0; j < S; j++) { + minm = INF; + for (int i = 0; i < I; i++) { + int i0 = j * I + i; + mm = beta[(k + 1) * S + NS[i0]] + priori[k * I + i] + + prioro[k * O + OS[i0]]; + minm = (*p2mymin)(minm, mm); + } + beta[k * S + j] = minm; + if (minm < norm) + norm = minm; + } + for (int j = 0; j < S; j++) + beta[k * S + j] -= norm; // normalize total metrics so they do not explode + } + + if (POSTI && POSTO) { + for (int k = 0; k < K; k++) { // input combining + norm = INF; + for (int i = 0; i < I; i++) { + minm = INF; + for (int j = 0; j < S; j++) { + mm = alpha[k * S + j] + prioro[k * O + OS[j * I + i]] + + beta[(k + 1) * S + NS[j * I + i]]; + minm = (*p2mymin)(minm, mm); + } + post[k * (I + O) + i] = minm; + if (minm < norm) + norm = minm; + } + for (int i = 0; i < I; i++) + post[k * (I + O) + i] -= norm; // normalize metrics + } + + for (int k = 0; k < K; k++) { // output combining + norm = INF; + for (int n = 0; n < O; n++) { + minm = INF; + for (int j = 0; j < S; j++) { + for (int i = 0; i < I; i++) { + mm = (n == OS[j * I + i] ? alpha[k * S + j] + priori[k * I + i] + + beta[(k + 1) * S + NS[j * I + i]] + : INF); + minm = (*p2mymin)(minm, mm); + } + } + post[k * (I + O) + I + n] = minm; + if (minm < norm) + norm = minm; + } + for (int n = 0; n < O; n++) + post[k * (I + O) + I + n] -= norm; // normalize metrics + } + } else if (POSTI) { + for (int k = 0; k < K; k++) { // input combining + norm = INF; + for (int i = 0; i < I; i++) { + minm = INF; + for (int j = 0; j < S; j++) { + mm = alpha[k * S + j] + prioro[k * O + OS[j * I + i]] + + beta[(k + 1) * S + NS[j * I + i]]; + minm = (*p2mymin)(minm, mm); } - } - post[k*(I+O)+I+n]=minm; - if(minm<norm) norm=minm; - } - for(int n=0;n<O;n++) - post[k*(I+O)+I+n]-=norm; // normalize metrics - } - } - else if(POSTI) - { - for(int k=0;k<K;k++) { // input combining - norm=INF; - for(int i=0;i<I;i++) { - minm=INF; - for(int j=0;j<S;j++) { - mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; - minm=(*p2mymin)(minm,mm); - } - post[k*I+i]=minm; - if(minm<norm) norm=minm; - } - for(int i=0;i<I;i++) - post[k*I+i]-=norm; // normalize metrics - } - } - else if(POSTO) { - for(int k=0;k<K;k++) { // output combining - norm=INF; - for(int n=0;n<O;n++) { - minm=INF; - for(int j=0;j<S;j++) { - for(int i=0;i<I;i++) { - mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); - minm=(*p2mymin)(minm,mm); - } + post[k * I + i] = minm; + if (minm < norm) + norm = minm; } - post[k*O+n]=minm; - if(minm<norm) norm=minm; - } - for(int n=0;n<O;n++) - post[k*O+n]-=norm; // normalize metrics - } - } - else - throw std::runtime_error ("Not both POSTI and POSTO can be false."); - - delete [] prioro; + for (int i = 0; i < I; i++) + post[k * I + i] -= norm; // normalize metrics + } + } else if (POSTO) { + for (int k = 0; k < K; k++) { // output combining + norm = INF; + for (int n = 0; n < O; n++) { + minm = INF; + for (int j = 0; j < S; j++) { + for (int i = 0; i < I; i++) { + mm = (n == OS[j * I + i] ? alpha[k * S + j] + priori[k * I + i] + + beta[(k + 1) * S + NS[j * I + i]] + : INF); + minm = (*p2mymin)(minm, mm); + } + } + post[k * O + n] = minm; + if (minm < norm) + norm = minm; + } + for (int n = 0; n < O; n++) + post[k * O + n] -= norm; // normalize metrics + } + } else + throw std::runtime_error("Not both POSTI and POSTO can be false."); +} + +//=========================================================== + +template <class T> +void siso_algorithm_combined(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + float (*p2mymin)(float, float), + int D, + const std::vector<T>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* priori, + const T* observations, + float* post) +{ + float norm, mm, minm; + std::vector<float> alpha(S * (K + 1)); + std::vector<float> beta(S * (K + 1)); + float* prioro = new float[O * K]; + + if (S0 < 0) { // initial state not specified + for (int i = 0; i < S; i++) + alpha[0 * S + i] = 0; + } else { + for (int i = 0; i < S; i++) + alpha[0 * S + i] = INF; + alpha[0 * S + S0] = 0.0; } - //--------- - - template void - siso_algorithm_combined<short>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - bool POSTI, bool POSTO, - float (*p2mymin)(float,float), - int D, - const std::vector<short> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *priori, const short *observations, float *post); - - template void - siso_algorithm_combined<int>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - bool POSTI, bool POSTO, - float (*p2mymin)(float,float), - int D, - const std::vector<int> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *priori, const int *observations, float *post); - - template void - siso_algorithm_combined<float>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - bool POSTI, bool POSTO, - float (*p2mymin)(float,float), - int D, - const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *priori, const float *observations, float *post); - - template void - siso_algorithm_combined<gr_complex>(int I, int S, int O, - const std::vector<int> &NS, - const std::vector<int> &OS, - const std::vector< std::vector<int> > &PS, - const std::vector< std::vector<int> > &PI, - int K, - int S0,int SK, - bool POSTI, bool POSTO, - float (*p2mymin)(float,float), - int D, - const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t TYPE, - const float *priori, const gr_complex *observations, float *post); - - //========================================================= - - template<class Ti, class To> void - sccc_decoder_combined(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<Ti> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const Ti *observations, To *data) - { - //allocate space for priori, prioro and posti of inner FSM - std::vector<float> ipriori(blocklength*FSMi.I(),0.0); - std::vector<float> iprioro(blocklength*FSMi.O()); - std::vector<float> iposti(blocklength*FSMi.I()); - - //allocate space for priori, prioro and posto of outer FSM - std::vector<float> opriori(blocklength*FSMo.I(),0.0); - std::vector<float> oprioro(blocklength*FSMo.O()); - std::vector<float> oposti(blocklength*FSMo.I()); - std::vector<float> oposto(blocklength*FSMo.O()); - - // turn observations to neg-log-priors - for(int k=0;k<blocklength;k++) { - calc_metric(FSMi.O(), D, TABLE, &(observations[k*D]), &(iprioro[k*FSMi.O()]),METRIC_TYPE); - iprioro[k*FSMi.O()] *= scaling; - } - - for(int rep=0;rep<iterations;rep++) { - // run inner SISO - siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(), - FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(), - blocklength, - STi0,STiK, - true, false, - p2mymin, - &(ipriori[0]), &(iprioro[0]), &(iposti[0])); - - //interleave soft info inner -> outer - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.DEINTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; - //} - memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float)); - } - - // run outer SISO - - if(rep<iterations-1) { // do not produce posti - siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), - FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), - blocklength, - STo0,SToK, - false, true, - p2mymin, - &(opriori[0]), &(oprioro[0]), &(oposto[0])); - - //interleave soft info outer --> inner - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.DEINTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; - //} - memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float)); - } - } - else // produce posti but not posto - - siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), - FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), - blocklength, - STo0,SToK, - true, false, - p2mymin, - &(opriori[0]), &(oprioro[0]), &(oposti[0])); - - /* - viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), - FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), - blocklength, - STo0,SToK, - &(oprioro[0]), data - ); - */ - } - - // generate hard decisions - for(int k=0;k<blocklength;k++) { - float min=INF; - int mini=0; - for(int i=0;i<FSMo.I();i++) { - if(oposti[k*FSMo.I()+i]<min) { - min=oposti[k*FSMo.I()+i]; - mini=i; - } - } - data[k]=(To)mini; - } + for (int k = 0; k < K; k++) { // forward recursion + calc_metric( + O, D, TABLE, &(observations[k * D]), &(prioro[k * O]), TYPE); // calc metrics + norm = INF; + for (int j = 0; j < S; j++) { + minm = INF; + for (unsigned int i = 0; i < PS[j].size(); i++) { + // int i0 = j*I+i; + mm = alpha[k * S + PS[j][i]] + priori[k * I + PI[j][i]] + + prioro[k * O + OS[PS[j][i] * I + PI[j][i]]]; + minm = (*p2mymin)(minm, mm); + } + alpha[(k + 1) * S + j] = minm; + if (minm < norm) + norm = minm; + } + for (int j = 0; j < S; j++) + alpha[(k + 1) * S + j] -= + norm; // normalize total metrics so they do not explode } - //------- - - template void - sccc_decoder_combined<float,unsigned char>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const float *observations, unsigned char *data); - - template void - sccc_decoder_combined<float,short>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const float *observations, short *data); - - template void - sccc_decoder_combined<float,int>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const float *observations, int *data); - - template void - sccc_decoder_combined<gr_complex,unsigned char>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const gr_complex *observations, unsigned char *data - ); - - template void - sccc_decoder_combined<gr_complex,short>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const gr_complex *observations, short *data); - - template void - sccc_decoder_combined<gr_complex,int>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const gr_complex *observations, int *data); - - //========================================================= - - template<class T> void - sccc_decoder(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, int iterations, - float (*p2mymin)(float,float), - const float *iprioro, T *data) - { - //allocate space for priori, and posti of inner FSM - std::vector<float> ipriori(blocklength*FSMi.I(),0.0); - std::vector<float> iposti(blocklength*FSMi.I()); - - //allocate space for priori, prioro and posto of outer FSM - std::vector<float> opriori(blocklength*FSMo.I(),0.0); - std::vector<float> oprioro(blocklength*FSMo.O()); - std::vector<float> oposti(blocklength*FSMo.I()); - std::vector<float> oposto(blocklength*FSMo.O()); - - for(int rep=0;rep<iterations;rep++) { - // run inner SISO - siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(), - FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(), - blocklength, - STi0,STiK, - true, false, - p2mymin, - &(ipriori[0]), &(iprioro[0]), &(iposti[0])); - - //interleave soft info inner -> outer - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.DEINTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; - //} - memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float)); - } - - // run outer SISO - - if(rep<iterations-1) { // do not produce posti - siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), - FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), - blocklength, - STo0,SToK, - false, true, - p2mymin, - &(opriori[0]), &(oprioro[0]), &(oposto[0])); - - //interleave soft info outer --> inner - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.DEINTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; - //} - memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float)); - } - } - else {// produce posti but not posto - siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), - FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), - blocklength, - STo0,SToK, - true, false, - p2mymin, - &(opriori[0]), &(oprioro[0]), &(oposti[0])); - - /* - viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), - FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), - blocklength, - STo0,SToK, - &(oprioro[0]), data); - */ - } - } // end iterations - - // generate hard decisions - for(int k=0;k<blocklength;k++) { - float min=INF; - int mini=0; - for(int i=0;i<FSMo.I();i++) { - if(oposti[k*FSMo.I()+i]<min) { - min=oposti[k*FSMo.I()+i]; - mini=i; - } - } - data[k]=(T)mini; - } + if (SK < 0) { // final state not specified + for (int i = 0; i < S; i++) + beta[K * S + i] = 0; + } else { + for (int i = 0; i < S; i++) + beta[K * S + i] = INF; + beta[K * S + SK] = 0.0; } - //------- - - template void - sccc_decoder<unsigned char>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - const float *iprioro, unsigned char *data); - - template void - sccc_decoder<short>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - const float *iprioro, short *data); - - template void - sccc_decoder<int>(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - const float *iprioro, int *data); - - //==================================================== - - template<class T> void - pccc_decoder(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - const float *cprioro, T *data) - { - //allocate space for priori, prioro and posti of FSM1 - std::vector<float> priori1(blocklength*FSM1.I(),0.0); - std::vector<float> prioro1(blocklength*FSM1.O()); - std::vector<float> posti1(blocklength*FSM1.I()); - - //allocate space for priori, prioro and posti of FSM2 - std::vector<float> priori2(blocklength*FSM2.I(),0.0); - std::vector<float> prioro2(blocklength*FSM2.O()); - std::vector<float> posti2(blocklength*FSM2.I()); - - //generate prioro1,2 (metrics are not updated per iteration: this is not the best you can do...) - for(int k=0;k<blocklength;k++) { - //std::cout << k << std::endl; - for(int i=0;i<FSM1.O();i++) { - float x=cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+0]; - for(int j=1;j<FSM2.O();j++) - x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+j]); - prioro1[k*FSM1.O()+i]=x; - //std::cout << prioro1[k*FSM1.O()+i] << ", "; - } - //std::cout << std::endl; - for(int i=0;i<FSM2.O();i++) { - float x=cprioro[k*FSM1.O()*FSM2.O()+0*FSM1.O()+i]; - for(int j=1;j<FSM1.O();j++) - x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+j*FSM1.O()+i]); - prioro2[k*FSM2.O()+i]=x; - } - } - - for(int rep=0;rep<iterations;rep++) { - // run SISO 1 - siso_algorithm(FSM1.I(),FSM1.S(),FSM1.O(), - FSM1.NS(), FSM1.OS(), FSM1.PS(), FSM1.PI(), - blocklength, - ST10,ST1K, - true, false, - p2mymin, - &(priori1[0]), &(prioro1[0]), &(posti1[0])); - - //for(int k=0;k<blocklength;k++){ - //for(int i=0;i<FSM1.I();i++) - //std::cout << posti1[k*FSM1.I()+i] << ", "; - //std::cout << std::endl; - //} - - //interleave soft info 1 -> 2 - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.INTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; - //} - memcpy(&(priori2[k*FSM2.I()]),&(posti1[ki*FSM1.I()]),FSM1.I()*sizeof(float)); - } - - // run SISO 2 - siso_algorithm(FSM2.I(),FSM2.S(),FSM2.O(), - FSM2.NS(), FSM2.OS(), FSM2.PS(), FSM2.PI(), - blocklength, - ST20,ST2K, - true, false, - p2mymin, - &(priori2[0]), &(prioro2[0]), &(posti2[0])); - - //interleave soft info 2 --> 1 - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.INTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; - //} - memcpy(&(priori1[ki*FSM1.I()]),&(posti2[k*FSM2.I()]),FSM1.I()*sizeof(float)); - } - } // end iterations - - // generate hard decisions - for(int k=0;k<blocklength;k++) { - for(int i=0;i<FSM1.I();i++) - posti1[k*FSM1.I()+i] = (*p2mymin)(priori1[k*FSM1.I()+i],posti1[k*FSM1.I()+i]); - float min=INF; - int mini=0; - for(int i=0;i<FSM1.I();i++) { - if(posti1[k*FSM1.I()+i]<min) { - min=posti1[k*FSM1.I()+i]; - mini=i; - } - } - data[k]=(T)mini; - //std::cout << data[k] << ", "<< std::endl; - } - //std::cout << std::endl; + for (int k = K - 1; k >= 0; k--) { // backward recursion + norm = INF; + for (int j = 0; j < S; j++) { + minm = INF; + for (int i = 0; i < I; i++) { + int i0 = j * I + i; + mm = beta[(k + 1) * S + NS[i0]] + priori[k * I + i] + + prioro[k * O + OS[i0]]; + minm = (*p2mymin)(minm, mm); + } + beta[k * S + j] = minm; + if (minm < norm) + norm = minm; + } + for (int j = 0; j < S; j++) + beta[k * S + j] -= norm; // normalize total metrics so they do not explode } - //---------------- - - template void - pccc_decoder<unsigned char>(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - const float *cprioro, unsigned char *data); - - template void - pccc_decoder<short>(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - const float *cprioro, short *data); - - template void - pccc_decoder<int>(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - const float *cprioro, int *data); - - //---------------- - - template<class Ti, class To> void - pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<Ti> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const Ti *observations, To *data) - { - //allocate space for cprioro - std::vector<float> cprioro(blocklength*FSM1.O()*FSM2.O(),0.0); - - //allocate space for priori, prioro and posti of FSM1 - std::vector<float> priori1(blocklength*FSM1.I(),0.0); - std::vector<float> prioro1(blocklength*FSM1.O()); - std::vector<float> posti1(blocklength*FSM1.I()); - - //allocate space for priori, prioro and posti of FSM2 - std::vector<float> priori2(blocklength*FSM2.I(),0.0); - std::vector<float> prioro2(blocklength*FSM2.O()); - std::vector<float> posti2(blocklength*FSM2.I()); - - // turn observations to neg-log-priors for cprioiro - int O=FSM1.O()*FSM2.O(); - for(int k=0;k<blocklength;k++) { - calc_metric(O, D, TABLE, &(observations[k*D]), &(cprioro[k*O]),METRIC_TYPE); - cprioro[k*O] *= scaling; - } - - //generate prioro1,2 (metrics are not updated per iteration: this is not the best you can do...) - for(int k=0;k<blocklength;k++) { - //std::cout << k << std::endl; - for(int i=0;i<FSM1.O();i++) { - float x=cprioro[k*O+i*FSM2.O()+0]; - for(int j=1;j<FSM2.O();j++) - x = (*p2mymin)(x,cprioro[k*O+i*FSM2.O()+j]); - prioro1[k*FSM1.O()+i]=x; - //std::cout << prioro1[k*FSM1.O()+i] << ", "; - } - //std::cout << std::endl; - for(int i=0;i<FSM2.O();i++) { - float x=cprioro[k*O+0*FSM2.O()+i]; - for(int j=1;j<FSM1.O();j++) - x = (*p2mymin)(x,cprioro[k*O+j*FSM2.O()+i]); - prioro2[k*FSM2.O()+i]=x; - } - } - - for(int rep=0;rep<iterations;rep++) { - // run SISO 1 - siso_algorithm(FSM1.I(),FSM1.S(),FSM1.O(), - FSM1.NS(), FSM1.OS(), FSM1.PS(), FSM1.PI(), - blocklength, - ST10,ST1K, - true, false, - p2mymin, - &(priori1[0]), &(prioro1[0]), &(posti1[0])); - - //for(int k=0;k<blocklength;k++){ - //for(int i=0;i<FSM1.I();i++) - //std::cout << posti1[k*FSM1.I()+i] << ", "; - //std::cout << std::endl; - //} - - //interleave soft info 1 -> 2 - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.INTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; - //} - memcpy(&(priori2[k*FSM2.I()]),&(posti1[ki*FSM1.I()]),FSM1.I()*sizeof(float)); - } - - // run SISO 2 - siso_algorithm(FSM2.I(),FSM2.S(),FSM2.O(), - FSM2.NS(), FSM2.OS(), FSM2.PS(), FSM2.PI(), - blocklength, - ST20,ST2K, - true, false, - p2mymin, - &(priori2[0]), &(prioro2[0]), &(posti2[0])); - - //interleave soft info 2 --> 1 - for(int k=0;k<blocklength;k++) { - int ki = INTERLEAVER.INTER()[k]; - //for(int i=0;i<FSMi.I();i++) { - //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; - //} - memcpy(&(priori1[ki*FSM1.I()]),&(posti2[k*FSM2.I()]),FSM1.I()*sizeof(float)); - } - } // end iterations - - // generate hard decisions - for(int k=0;k<blocklength;k++) { - for(int i=0;i<FSM1.I();i++) - posti1[k*FSM1.I()+i] = (*p2mymin)(priori1[k*FSM1.I()+i],posti1[k*FSM1.I()+i]); - float min=INF; - int mini=0; - for(int i=0;i<FSM1.I();i++) { - if(posti1[k*FSM1.I()+i]<min) { - min=posti1[k*FSM1.I()+i]; - mini=i; - } - } - data[k]=(To)mini; - //std::cout << data[k] << ", "<< std::endl; - } - //std::cout << std::endl; + if (POSTI && POSTO) { + for (int k = 0; k < K; k++) { // input combining + norm = INF; + for (int i = 0; i < I; i++) { + minm = INF; + for (int j = 0; j < S; j++) { + mm = alpha[k * S + j] + prioro[k * O + OS[j * I + i]] + + beta[(k + 1) * S + NS[j * I + i]]; + minm = (*p2mymin)(minm, mm); + } + post[k * (I + O) + i] = minm; + if (minm < norm) + norm = minm; + } + for (int i = 0; i < I; i++) + post[k * (I + O) + i] -= norm; // normalize metrics + } + + for (int k = 0; k < K; k++) { // output combining + norm = INF; + for (int n = 0; n < O; n++) { + minm = INF; + for (int j = 0; j < S; j++) { + for (int i = 0; i < I; i++) { + mm = (n == OS[j * I + i] ? alpha[k * S + j] + priori[k * I + i] + + beta[(k + 1) * S + NS[j * I + i]] + : INF); + minm = (*p2mymin)(minm, mm); + } + } + post[k * (I + O) + I + n] = minm; + if (minm < norm) + norm = minm; + } + for (int n = 0; n < O; n++) + post[k * (I + O) + I + n] -= norm; // normalize metrics + } + } else if (POSTI) { + for (int k = 0; k < K; k++) { // input combining + norm = INF; + for (int i = 0; i < I; i++) { + minm = INF; + for (int j = 0; j < S; j++) { + mm = alpha[k * S + j] + prioro[k * O + OS[j * I + i]] + + beta[(k + 1) * S + NS[j * I + i]]; + minm = (*p2mymin)(minm, mm); + } + post[k * I + i] = minm; + if (minm < norm) + norm = minm; + } + for (int i = 0; i < I; i++) + post[k * I + i] -= norm; // normalize metrics + } + } else if (POSTO) { + for (int k = 0; k < K; k++) { // output combining + norm = INF; + for (int n = 0; n < O; n++) { + minm = INF; + for (int j = 0; j < S; j++) { + for (int i = 0; i < I; i++) { + mm = (n == OS[j * I + i] ? alpha[k * S + j] + priori[k * I + i] + + beta[(k + 1) * S + NS[j * I + i]] + : INF); + minm = (*p2mymin)(minm, mm); + } + } + post[k * O + n] = minm; + if (minm < norm) + norm = minm; + } + for (int n = 0; n < O; n++) + post[k * O + n] -= norm; // normalize metrics + } + } else + throw std::runtime_error("Not both POSTI and POSTO can be false."); + + delete[] prioro; +} + +//--------- + +template void siso_algorithm_combined<short>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + float (*p2mymin)(float, float), + int D, + const std::vector<short>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* priori, + const short* observations, + float* post); + +template void siso_algorithm_combined<int>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + float (*p2mymin)(float, float), + int D, + const std::vector<int>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* priori, + const int* observations, + float* post); + +template void siso_algorithm_combined<float>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + float (*p2mymin)(float, float), + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* priori, + const float* observations, + float* post); + +template void siso_algorithm_combined<gr_complex>(int I, + int S, + int O, + const std::vector<int>& NS, + const std::vector<int>& OS, + const std::vector<std::vector<int>>& PS, + const std::vector<std::vector<int>>& PI, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + float (*p2mymin)(float, float), + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t TYPE, + const float* priori, + const gr_complex* observations, + float* post); + +//========================================================= + +template <class Ti, class To> +void sccc_decoder_combined(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<Ti>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const Ti* observations, + To* data) +{ + // allocate space for priori, prioro and posti of inner FSM + std::vector<float> ipriori(blocklength * FSMi.I(), 0.0); + std::vector<float> iprioro(blocklength * FSMi.O()); + std::vector<float> iposti(blocklength * FSMi.I()); + + // allocate space for priori, prioro and posto of outer FSM + std::vector<float> opriori(blocklength * FSMo.I(), 0.0); + std::vector<float> oprioro(blocklength * FSMo.O()); + std::vector<float> oposti(blocklength * FSMo.I()); + std::vector<float> oposto(blocklength * FSMo.O()); + + // turn observations to neg-log-priors + for (int k = 0; k < blocklength; k++) { + calc_metric(FSMi.O(), + D, + TABLE, + &(observations[k * D]), + &(iprioro[k * FSMi.O()]), + METRIC_TYPE); + iprioro[k * FSMi.O()] *= scaling; + } + + for (int rep = 0; rep < iterations; rep++) { + // run inner SISO + siso_algorithm(FSMi.I(), + FSMi.S(), + FSMi.O(), + FSMi.NS(), + FSMi.OS(), + FSMi.PS(), + FSMi.PI(), + blocklength, + STi0, + STiK, + true, + false, + p2mymin, + &(ipriori[0]), + &(iprioro[0]), + &(iposti[0])); + + // interleave soft info inner -> outer + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.DEINTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(oprioro[k * FSMi.I()]), + &(iposti[ki * FSMi.I()]), + FSMi.I() * sizeof(float)); + } + + // run outer SISO + + if (rep < iterations - 1) { // do not produce posti + siso_algorithm(FSMo.I(), + FSMo.S(), + FSMo.O(), + FSMo.NS(), + FSMo.OS(), + FSMo.PS(), + FSMo.PI(), + blocklength, + STo0, + SToK, + false, + true, + p2mymin, + &(opriori[0]), + &(oprioro[0]), + &(oposto[0])); + + // interleave soft info outer --> inner + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.DEINTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(ipriori[ki * FSMi.I()]), + &(oposto[k * FSMi.I()]), + FSMi.I() * sizeof(float)); + } + } else // produce posti but not posto + + siso_algorithm(FSMo.I(), + FSMo.S(), + FSMo.O(), + FSMo.NS(), + FSMo.OS(), + FSMo.PS(), + FSMo.PI(), + blocklength, + STo0, + SToK, + true, + false, + p2mymin, + &(opriori[0]), + &(oprioro[0]), + &(oposti[0])); + + /* + viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + &(oprioro[0]), data + ); + */ + } + + // generate hard decisions + for (int k = 0; k < blocklength; k++) { + float min = INF; + int mini = 0; + for (int i = 0; i < FSMo.I(); i++) { + if (oposti[k * FSMo.I() + i] < min) { + min = oposti[k * FSMo.I() + i]; + mini = i; + } + } + data[k] = (To)mini; + } +} + +//------- + +template void +sccc_decoder_combined<float, unsigned char>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float* observations, + unsigned char* data); + +template void +sccc_decoder_combined<float, short>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float* observations, + short* data); + +template void +sccc_decoder_combined<float, int>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float* observations, + int* data); + +template void sccc_decoder_combined<gr_complex, unsigned char>( + const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex* observations, + unsigned char* data); + +template void +sccc_decoder_combined<gr_complex, short>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex* observations, + short* data); + +template void +sccc_decoder_combined<gr_complex, int>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex* observations, + int* data); + +//========================================================= + +template <class T> +void sccc_decoder(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* iprioro, + T* data) +{ + // allocate space for priori, and posti of inner FSM + std::vector<float> ipriori(blocklength * FSMi.I(), 0.0); + std::vector<float> iposti(blocklength * FSMi.I()); + + // allocate space for priori, prioro and posto of outer FSM + std::vector<float> opriori(blocklength * FSMo.I(), 0.0); + std::vector<float> oprioro(blocklength * FSMo.O()); + std::vector<float> oposti(blocklength * FSMo.I()); + std::vector<float> oposto(blocklength * FSMo.O()); + + for (int rep = 0; rep < iterations; rep++) { + // run inner SISO + siso_algorithm(FSMi.I(), + FSMi.S(), + FSMi.O(), + FSMi.NS(), + FSMi.OS(), + FSMi.PS(), + FSMi.PI(), + blocklength, + STi0, + STiK, + true, + false, + p2mymin, + &(ipriori[0]), + &(iprioro[0]), + &(iposti[0])); + + // interleave soft info inner -> outer + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.DEINTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(oprioro[k * FSMi.I()]), + &(iposti[ki * FSMi.I()]), + FSMi.I() * sizeof(float)); + } + + // run outer SISO + + if (rep < iterations - 1) { // do not produce posti + siso_algorithm(FSMo.I(), + FSMo.S(), + FSMo.O(), + FSMo.NS(), + FSMo.OS(), + FSMo.PS(), + FSMo.PI(), + blocklength, + STo0, + SToK, + false, + true, + p2mymin, + &(opriori[0]), + &(oprioro[0]), + &(oposto[0])); + + // interleave soft info outer --> inner + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.DEINTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(ipriori[ki * FSMi.I()]), + &(oposto[k * FSMi.I()]), + FSMi.I() * sizeof(float)); + } + } else { // produce posti but not posto + siso_algorithm(FSMo.I(), + FSMo.S(), + FSMo.O(), + FSMo.NS(), + FSMo.OS(), + FSMo.PS(), + FSMo.PI(), + blocklength, + STo0, + SToK, + true, + false, + p2mymin, + &(opriori[0]), + &(oprioro[0]), + &(oposti[0])); + + /* + viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + &(oprioro[0]), data); + */ + } + } // end iterations + + // generate hard decisions + for (int k = 0; k < blocklength; k++) { + float min = INF; + int mini = 0; + for (int i = 0; i < FSMo.I(); i++) { + if (oposti[k * FSMo.I() + i] < min) { + min = oposti[k * FSMo.I() + i]; + mini = i; + } + } + data[k] = (T)mini; + } +} + +//------- + +template void sccc_decoder<unsigned char>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* iprioro, + unsigned char* data); + +template void sccc_decoder<short>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* iprioro, + short* data); + +template void sccc_decoder<int>(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* iprioro, + int* data); + +//==================================================== + +template <class T> +void pccc_decoder(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* cprioro, + T* data) +{ + // allocate space for priori, prioro and posti of FSM1 + std::vector<float> priori1(blocklength * FSM1.I(), 0.0); + std::vector<float> prioro1(blocklength * FSM1.O()); + std::vector<float> posti1(blocklength * FSM1.I()); + + // allocate space for priori, prioro and posti of FSM2 + std::vector<float> priori2(blocklength * FSM2.I(), 0.0); + std::vector<float> prioro2(blocklength * FSM2.O()); + std::vector<float> posti2(blocklength * FSM2.I()); + + // generate prioro1,2 (metrics are not updated per iteration: this is not the best you + // can do...) + for (int k = 0; k < blocklength; k++) { + // std::cout << k << std::endl; + for (int i = 0; i < FSM1.O(); i++) { + float x = cprioro[k * FSM1.O() * FSM2.O() + i * FSM1.O() + 0]; + for (int j = 1; j < FSM2.O(); j++) + x = (*p2mymin)(x, cprioro[k * FSM1.O() * FSM2.O() + i * FSM1.O() + j]); + prioro1[k * FSM1.O() + i] = x; + // std::cout << prioro1[k*FSM1.O()+i] << ", "; + } + // std::cout << std::endl; + for (int i = 0; i < FSM2.O(); i++) { + float x = cprioro[k * FSM1.O() * FSM2.O() + 0 * FSM1.O() + i]; + for (int j = 1; j < FSM1.O(); j++) + x = (*p2mymin)(x, cprioro[k * FSM1.O() * FSM2.O() + j * FSM1.O() + i]); + prioro2[k * FSM2.O() + i] = x; + } + } + + for (int rep = 0; rep < iterations; rep++) { + // run SISO 1 + siso_algorithm(FSM1.I(), + FSM1.S(), + FSM1.O(), + FSM1.NS(), + FSM1.OS(), + FSM1.PS(), + FSM1.PI(), + blocklength, + ST10, + ST1K, + true, + false, + p2mymin, + &(priori1[0]), + &(prioro1[0]), + &(posti1[0])); + + // for(int k=0;k<blocklength;k++){ + // for(int i=0;i<FSM1.I();i++) + // std::cout << posti1[k*FSM1.I()+i] << ", "; + // std::cout << std::endl; + //} + + // interleave soft info 1 -> 2 + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.INTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(priori2[k * FSM2.I()]), + &(posti1[ki * FSM1.I()]), + FSM1.I() * sizeof(float)); + } + + // run SISO 2 + siso_algorithm(FSM2.I(), + FSM2.S(), + FSM2.O(), + FSM2.NS(), + FSM2.OS(), + FSM2.PS(), + FSM2.PI(), + blocklength, + ST20, + ST2K, + true, + false, + p2mymin, + &(priori2[0]), + &(prioro2[0]), + &(posti2[0])); + + // interleave soft info 2 --> 1 + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.INTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(priori1[ki * FSM1.I()]), + &(posti2[k * FSM2.I()]), + FSM1.I() * sizeof(float)); + } + } // end iterations + + // generate hard decisions + for (int k = 0; k < blocklength; k++) { + for (int i = 0; i < FSM1.I(); i++) + posti1[k * FSM1.I() + i] = + (*p2mymin)(priori1[k * FSM1.I() + i], posti1[k * FSM1.I() + i]); + float min = INF; + int mini = 0; + for (int i = 0; i < FSM1.I(); i++) { + if (posti1[k * FSM1.I() + i] < min) { + min = posti1[k * FSM1.I() + i]; + mini = i; + } + } + data[k] = (T)mini; + // std::cout << data[k] << ", "<< std::endl; + } + // std::cout << std::endl; +} + +//---------------- + +template void pccc_decoder<unsigned char>(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* cprioro, + unsigned char* data); + +template void pccc_decoder<short>(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* cprioro, + short* data); + +template void pccc_decoder<int>(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + const float* cprioro, + int* data); + +//---------------- + +template <class Ti, class To> +void pccc_decoder_combined(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<Ti>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const Ti* observations, + To* data) +{ + // allocate space for cprioro + std::vector<float> cprioro(blocklength * FSM1.O() * FSM2.O(), 0.0); + + // allocate space for priori, prioro and posti of FSM1 + std::vector<float> priori1(blocklength * FSM1.I(), 0.0); + std::vector<float> prioro1(blocklength * FSM1.O()); + std::vector<float> posti1(blocklength * FSM1.I()); + + // allocate space for priori, prioro and posti of FSM2 + std::vector<float> priori2(blocklength * FSM2.I(), 0.0); + std::vector<float> prioro2(blocklength * FSM2.O()); + std::vector<float> posti2(blocklength * FSM2.I()); + + // turn observations to neg-log-priors for cprioiro + int O = FSM1.O() * FSM2.O(); + for (int k = 0; k < blocklength; k++) { + calc_metric(O, D, TABLE, &(observations[k * D]), &(cprioro[k * O]), METRIC_TYPE); + cprioro[k * O] *= scaling; + } + + // generate prioro1,2 (metrics are not updated per iteration: this is not the best you + // can do...) + for (int k = 0; k < blocklength; k++) { + // std::cout << k << std::endl; + for (int i = 0; i < FSM1.O(); i++) { + float x = cprioro[k * O + i * FSM2.O() + 0]; + for (int j = 1; j < FSM2.O(); j++) + x = (*p2mymin)(x, cprioro[k * O + i * FSM2.O() + j]); + prioro1[k * FSM1.O() + i] = x; + // std::cout << prioro1[k*FSM1.O()+i] << ", "; + } + // std::cout << std::endl; + for (int i = 0; i < FSM2.O(); i++) { + float x = cprioro[k * O + 0 * FSM2.O() + i]; + for (int j = 1; j < FSM1.O(); j++) + x = (*p2mymin)(x, cprioro[k * O + j * FSM2.O() + i]); + prioro2[k * FSM2.O() + i] = x; + } } - template void - pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const float *observations, unsigned char *data); - - template void - pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const float *observations, short *data); - - template void - pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const float *observations, int *data); - - template void - pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const gr_complex *observations, unsigned char *data); - - template void - pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const gr_complex *observations, short *data); - - template void - pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, int blocklength, - int iterations, - float (*p2mymin)(float,float), - int D, const std::vector<gr_complex> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling, - const gr_complex *observations, int *data); - - } /* namespace trellis */ + for (int rep = 0; rep < iterations; rep++) { + // run SISO 1 + siso_algorithm(FSM1.I(), + FSM1.S(), + FSM1.O(), + FSM1.NS(), + FSM1.OS(), + FSM1.PS(), + FSM1.PI(), + blocklength, + ST10, + ST1K, + true, + false, + p2mymin, + &(priori1[0]), + &(prioro1[0]), + &(posti1[0])); + + // for(int k=0;k<blocklength;k++){ + // for(int i=0;i<FSM1.I();i++) + // std::cout << posti1[k*FSM1.I()+i] << ", "; + // std::cout << std::endl; + //} + + // interleave soft info 1 -> 2 + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.INTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(priori2[k * FSM2.I()]), + &(posti1[ki * FSM1.I()]), + FSM1.I() * sizeof(float)); + } + + // run SISO 2 + siso_algorithm(FSM2.I(), + FSM2.S(), + FSM2.O(), + FSM2.NS(), + FSM2.OS(), + FSM2.PS(), + FSM2.PI(), + blocklength, + ST20, + ST2K, + true, + false, + p2mymin, + &(priori2[0]), + &(prioro2[0]), + &(posti2[0])); + + // interleave soft info 2 --> 1 + for (int k = 0; k < blocklength; k++) { + int ki = INTERLEAVER.INTER()[k]; + // for(int i=0;i<FSMi.I();i++) { + // ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(priori1[ki * FSM1.I()]), + &(posti2[k * FSM2.I()]), + FSM1.I() * sizeof(float)); + } + } // end iterations + + // generate hard decisions + for (int k = 0; k < blocklength; k++) { + for (int i = 0; i < FSM1.I(); i++) + posti1[k * FSM1.I() + i] = + (*p2mymin)(priori1[k * FSM1.I() + i], posti1[k * FSM1.I() + i]); + float min = INF; + int mini = 0; + for (int i = 0; i < FSM1.I(); i++) { + if (posti1[k * FSM1.I() + i] < min) { + min = posti1[k * FSM1.I() + i]; + mini = i; + } + } + data[k] = (To)mini; + // std::cout << data[k] << ", "<< std::endl; + } + // std::cout << std::endl; +} + +template void pccc_decoder_combined(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float* observations, + unsigned char* data); + +template void pccc_decoder_combined(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float* observations, + short* data); + +template void pccc_decoder_combined(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float* observations, + int* data); + +template void pccc_decoder_combined(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex* observations, + unsigned char* data); + +template void pccc_decoder_combined(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex* observations, + short* data); + +template void pccc_decoder_combined(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int iterations, + float (*p2mymin)(float, float), + int D, + const std::vector<gr_complex>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex* observations, + int* data); + +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/encoder_impl.cc b/gr-trellis/lib/encoder_impl.cc index ecb0410a5f..28c1db304d 100644 --- a/gr-trellis/lib/encoder_impl.cc +++ b/gr-trellis/lib/encoder_impl.cc @@ -29,103 +29,100 @@ #include <iostream> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T, class OUT_T> - typename encoder<IN_T,OUT_T>::sptr - encoder<IN_T,OUT_T>::make(const fsm &FSM, int ST) - { - return gnuradio::get_initial_sptr - (new encoder_impl<IN_T,OUT_T>(FSM,ST,0,false)); - } +template <class IN_T, class OUT_T> +typename encoder<IN_T, OUT_T>::sptr encoder<IN_T, OUT_T>::make(const fsm& FSM, int ST) +{ + return gnuradio::get_initial_sptr(new encoder_impl<IN_T, OUT_T>(FSM, ST, 0, false)); +} - template <class IN_T, class OUT_T> - typename encoder<IN_T,OUT_T>::sptr - encoder<IN_T,OUT_T>::make(const fsm &FSM, int ST, int K) - { - return gnuradio::get_initial_sptr - (new encoder_impl<IN_T,OUT_T>(FSM,ST,K,true)); - } +template <class IN_T, class OUT_T> +typename encoder<IN_T, OUT_T>::sptr +encoder<IN_T, OUT_T>::make(const fsm& FSM, int ST, int K) +{ + return gnuradio::get_initial_sptr(new encoder_impl<IN_T, OUT_T>(FSM, ST, K, true)); +} - template <class IN_T, class OUT_T> - encoder_impl<IN_T,OUT_T>::encoder_impl(const fsm &FSM, int ST, int K, bool B) +template <class IN_T, class OUT_T> +encoder_impl<IN_T, OUT_T>::encoder_impl(const fsm& FSM, int ST, int K, bool B) : sync_block("encoder<IN_T,OUT_T>", - io_signature::make(1, 1, sizeof(IN_T)), - io_signature::make(1, 1, sizeof(OUT_T))), + io_signature::make(1, 1, sizeof(IN_T)), + io_signature::make(1, 1, sizeof(OUT_T))), d_FSM(FSM), d_ST(ST), d_K(K), d_B(B) - { - } +{ +} - template <class IN_T, class OUT_T> - void encoder_impl<IN_T,OUT_T>::set_FSM(const fsm &FSM) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_FSM = FSM; - } +template <class IN_T, class OUT_T> +void encoder_impl<IN_T, OUT_T>::set_FSM(const fsm& FSM) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_FSM = FSM; +} - template <class IN_T, class OUT_T> - void encoder_impl<IN_T,OUT_T>::set_ST(int ST) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_ST = ST; - } +template <class IN_T, class OUT_T> +void encoder_impl<IN_T, OUT_T>::set_ST(int ST) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_ST = ST; +} - template <class IN_T, class OUT_T> - void encoder_impl<IN_T,OUT_T>::set_K(int K) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_K = K; - } +template <class IN_T, class OUT_T> +void encoder_impl<IN_T, OUT_T>::set_K(int K) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_K = K; +} - template <class IN_T, class OUT_T> - encoder_impl<IN_T,OUT_T>::~encoder_impl() - { - } +template <class IN_T, class OUT_T> +encoder_impl<IN_T, OUT_T>::~encoder_impl() +{ +} - template <class IN_T, class OUT_T> - int - encoder_impl<IN_T,OUT_T>::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(this->d_setlock); - int ST_tmp = 0; +template <class IN_T, class OUT_T> +int encoder_impl<IN_T, OUT_T>::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(this->d_setlock); + int ST_tmp = 0; - if (d_B){ // blockwise operation - int nblocks = noutput_items /d_K; - const IN_T *in = (const IN_T*)input_items[0]; - OUT_T *out = (OUT_T *) output_items[0]; - for(int n = 0; n < nblocks; n++) { - ST_tmp = d_ST; - for(int i = 0; i < d_K; i++) { - out[n*d_K+i] = (OUT_T)d_FSM.OS()[ST_tmp*d_FSM.I()+in[n*d_K+i]]; - ST_tmp = (int)d_FSM.NS()[ST_tmp*d_FSM.I()+in[n*d_K+i]]; - } + if (d_B) { // blockwise operation + int nblocks = noutput_items / d_K; + const IN_T* in = (const IN_T*)input_items[0]; + OUT_T* out = (OUT_T*)output_items[0]; + for (int n = 0; n < nblocks; n++) { + ST_tmp = d_ST; + for (int i = 0; i < d_K; i++) { + out[n * d_K + i] = + (OUT_T)d_FSM.OS()[ST_tmp * d_FSM.I() + in[n * d_K + i]]; + ST_tmp = (int)d_FSM.NS()[ST_tmp * d_FSM.I() + in[n * d_K + i]]; + } } - return nblocks*d_K; - } // end blockwise operation - else{ // streaming operation - const IN_T *in = (const IN_T*)input_items[0]; - OUT_T *out = (OUT_T *) output_items[0]; + return nblocks * d_K; + } // end blockwise operation + else { // streaming operation + const IN_T* in = (const IN_T*)input_items[0]; + OUT_T* out = (OUT_T*)output_items[0]; ST_tmp = d_ST; - for(int i = 0; i < noutput_items; i++) { - out[i] = (OUT_T)d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; - ST_tmp = (int)d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]]; + for (int i = 0; i < noutput_items; i++) { + out[i] = (OUT_T)d_FSM.OS()[ST_tmp * d_FSM.I() + in[i]]; + ST_tmp = (int)d_FSM.NS()[ST_tmp * d_FSM.I() + in[i]]; } d_ST = ST_tmp; return noutput_items; - } // end streaming operation - } - template class encoder<std::uint8_t, std::uint8_t>; - template class encoder<std::uint8_t, std::int16_t>; - template class encoder<std::uint8_t, std::int32_t>; - template class encoder<std::int16_t, std::int16_t>; - template class encoder<std::int16_t, std::int32_t>; - template class encoder<std::int32_t, std::int32_t>; + } // end streaming operation +} +template class encoder<std::uint8_t, std::uint8_t>; +template class encoder<std::uint8_t, std::int16_t>; +template class encoder<std::uint8_t, std::int32_t>; +template class encoder<std::int16_t, std::int16_t>; +template class encoder<std::int16_t, std::int32_t>; +template class encoder<std::int32_t, std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/encoder_impl.h b/gr-trellis/lib/encoder_impl.h index 5832b9d848..d98465c883 100644 --- a/gr-trellis/lib/encoder_impl.h +++ b/gr-trellis/lib/encoder_impl.h @@ -26,34 +26,38 @@ #include <gnuradio/trellis/encoder.h> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T, class OUT_T> - class encoder_impl : public encoder<IN_T,OUT_T> +template <class IN_T, class OUT_T> +class encoder_impl : public encoder<IN_T, OUT_T> +{ +private: + fsm d_FSM; + int d_ST; + int d_K; + bool d_B; + + +public: + encoder_impl(const fsm& FSM, int ST, int K, bool B); + ~encoder_impl(); + + fsm FSM() const { - private: - fsm d_FSM; - int d_ST; - int d_K; - bool d_B; - - - public: - encoder_impl(const fsm &FSM, int ST, int K, bool B); - ~encoder_impl(); - - fsm FSM() const { return d_FSM;; } - int ST() const { return d_ST; } - int K() const { return d_K; } - void set_FSM(const fsm &FSM); - void set_ST(int ST); - void set_K(int K); - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } /* namespace trellis */ + return d_FSM; + ; + } + int ST() const { return d_ST; } + int K() const { return d_K; } + void set_FSM(const fsm& FSM); + void set_ST(int ST); + void set_K(int K); + int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; + +} /* namespace trellis */ } /* namespace gr */ #endif /* ENCODER_IMPL_H */ diff --git a/gr-trellis/lib/fsm.cc b/gr-trellis/lib/fsm.cc index 4c1fe69285..ca28266b70 100644 --- a/gr-trellis/lib/fsm.cc +++ b/gr-trellis/lib/fsm.cc @@ -31,299 +31,311 @@ #include <gnuradio/trellis/fsm.h> namespace gr { - namespace trellis { - - fsm::fsm() - { - d_I=0; - d_S=0; - d_O=0; - d_NS.resize(0); - d_OS.resize(0); - d_PS.resize(0); - d_PI.resize(0); - d_TMi.resize(0); - d_TMl.resize(0); +namespace trellis { + +fsm::fsm() +{ + d_I = 0; + d_S = 0; + d_O = 0; + d_NS.resize(0); + d_OS.resize(0); + d_PS.resize(0); + d_PI.resize(0); + d_TMi.resize(0); + d_TMl.resize(0); +} + +fsm::fsm(const fsm& FSM) +{ + d_I = FSM.I(); + d_S = FSM.S(); + d_O = FSM.O(); + d_NS = FSM.NS(); + d_OS = FSM.OS(); + d_PS = FSM.PS(); // is this going to make a deep copy? + d_PI = FSM.PI(); + d_TMi = FSM.TMi(); + d_TMl = FSM.TMl(); +} + +fsm::fsm(int I, int S, int O, const std::vector<int>& NS, const std::vector<int>& OS) +{ + d_I = I; + d_S = S; + d_O = O; + d_NS = NS; + d_OS = OS; + + generate_PS_PI(); + generate_TM(); +} + +//###################################################################### +//# Read an FSM specification from a file. +//# Format (hopefully will become more flexible in the future...): +//# I S O (in the first line) +//# blank line +//# Next state matrix (S lines, each with I integers separated by spaces) +//# blank line +//# output symbol matrix (S lines, each with I integers separated by spaces) +//# optional comments +//###################################################################### +fsm::fsm(const char* name) +{ + FILE* fsmfile; + + if ((fsmfile = fopen(name, "r")) == NULL) + throw std::runtime_error("fsm::fsm(const char *name): file open error\n"); + // printf("file open error in fsm()\n"); + + if (fscanf(fsmfile, "%d %d %d\n", &d_I, &d_S, &d_O) == EOF) { + if (ferror(fsmfile) != 0) + throw std::runtime_error("fsm::fsm(const char *name): file read error\n"); } - fsm::fsm(const fsm &FSM) - { - d_I=FSM.I(); - d_S=FSM.S(); - d_O=FSM.O(); - d_NS=FSM.NS(); - d_OS=FSM.OS(); - d_PS=FSM.PS(); // is this going to make a deep copy? - d_PI=FSM.PI(); - d_TMi=FSM.TMi(); - d_TMl=FSM.TMl(); - } - - fsm::fsm(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS) - { - d_I=I; - d_S=S; - d_O=O; - d_NS=NS; - d_OS=OS; + d_NS.resize(d_I * d_S); + d_OS.resize(d_I * d_S); - generate_PS_PI(); - generate_TM(); + for (int i = 0; i < d_S; i++) { + for (int j = 0; j < d_I; j++) { + if (fscanf(fsmfile, "%d", &(d_NS[i * d_I + j])) == EOF) { + if (ferror(fsmfile) != 0) + throw std::runtime_error( + "fsm::fsm(const char *name): file read error\n"); + } + } + } + for (int i = 0; i < d_S; i++) { + for (int j = 0; j < d_I; j++) { + if (fscanf(fsmfile, "%d", &(d_OS[i * d_I + j])) == EOF) { + if (ferror(fsmfile) != 0) + throw std::runtime_error( + "fsm::fsm(const char *name): file read error\n"); + } + } } - //###################################################################### - //# Read an FSM specification from a file. - //# Format (hopefully will become more flexible in the future...): - //# I S O (in the first line) - //# blank line - //# Next state matrix (S lines, each with I integers separated by spaces) - //# blank line - //# output symbol matrix (S lines, each with I integers separated by spaces) - //# optional comments - //###################################################################### - fsm::fsm(const char *name) - { - FILE *fsmfile; - - if((fsmfile=fopen(name,"r"))==NULL) - throw std::runtime_error ("fsm::fsm(const char *name): file open error\n"); - //printf("file open error in fsm()\n"); - - if(fscanf(fsmfile,"%d %d %d\n",&d_I,&d_S,&d_O) == EOF) { - if(ferror(fsmfile) != 0) - throw std::runtime_error ("fsm::fsm(const char *name): file read error\n"); - } - - d_NS.resize(d_I*d_S); - d_OS.resize(d_I*d_S); - - for(int i=0;i<d_S;i++) { - for(int j=0;j<d_I;j++) { - if(fscanf(fsmfile,"%d",&(d_NS[i*d_I+j])) == EOF) { - if(ferror(fsmfile) != 0) - throw std::runtime_error ("fsm::fsm(const char *name): file read error\n"); - } - } - } - for(int i=0;i<d_S;i++) { - for(int j=0;j<d_I;j++) { - if(fscanf(fsmfile,"%d",&(d_OS[i*d_I+j])) == EOF) { - if(ferror(fsmfile) != 0) - throw std::runtime_error ("fsm::fsm(const char *name): file read error\n"); - } - } - } - - fclose(fsmfile); - - generate_PS_PI(); - generate_TM(); + fclose(fsmfile); + + generate_PS_PI(); + generate_TM(); +} + +//###################################################################### +//# Automatically generate the FSM from the generator matrix +//# of a (n,k) binary convolutional code +//###################################################################### +fsm::fsm(int k, int n, const std::vector<int>& G) +{ + // calculate maximum memory requirements for each input stream + std::vector<int> max_mem_x(k, -1); + int max_mem = -1; + for (int i = 0; i < k; i++) { + for (int j = 0; j < n; j++) { + int mem = -1; + if (G[i * n + j] != 0) + mem = (int)(log(double(G[i * n + j])) / log(2.0)); + if (mem > max_mem_x[i]) + max_mem_x[i] = mem; + if (mem > max_mem) + max_mem = mem; + } } - //###################################################################### - //# Automatically generate the FSM from the generator matrix - //# of a (n,k) binary convolutional code - //###################################################################### - fsm::fsm(int k, int n, const std::vector<int> &G) - { - // calculate maximum memory requirements for each input stream - std::vector<int> max_mem_x(k,-1); - int max_mem = -1; - for(int i=0;i<k;i++) { - for(int j=0;j<n;j++) { - int mem = -1; - if(G[i*n+j]!=0) - mem=(int)(log(double(G[i*n+j]))/log(2.0)); - if(mem>max_mem_x[i]) - max_mem_x[i]=mem; - if(mem>max_mem) - max_mem=mem; - } - } - - //printf("max_mem_x\n"); - //for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n"); - - // calculate total memory requirements to set S - int sum_max_mem = 0; - for(int i=0;i<k;i++) - sum_max_mem += max_mem_x[i]; - - //printf("sum_max_mem = %d\n",sum_max_mem); - - d_I=1<<k; - d_S=1<<sum_max_mem; - d_O=1<<n; - - // binary representation of the G matrix - std::vector<std::vector<int> > Gb(k*n); - for(int j=0;j<k*n;j++) { - Gb[j].resize(max_mem+1); - dec2base(G[j],2,Gb[j]); - //printf("Gb\n"); - //for(int m=0;m<Gb[j].size();m++) printf("%d ",Gb[j][m]); printf("\n"); - } - - // alphabet size of each shift register - std::vector<int> bases_x(k); - for(int j=0;j<k ;j++) - bases_x[j] = 1 << max_mem_x[j]; - //printf("bases_x\n"); - //for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n"); - - d_NS.resize(d_I*d_S); - d_OS.resize(d_I*d_S); - - std::vector<int> sx(k); - std::vector<int> nsx(k); - std::vector<int> tx(k); - std::vector<std::vector<int> > tb(k); - for(int j=0;j<k;j++) - tb[j].resize(max_mem+1); - std::vector<int> inb(k); - std::vector<int> outb(n); - - for(int s=0;s<d_S;s++) { - dec2bases(s,bases_x,sx); // split s into k values, each representing one of the k shift registers - //printf("state = %d \nstates = ",s); - //for(int j=0;j<sx.size();j++) printf("%d ",sx[j]); printf("\n"); - for(int i=0;i<d_I;i++) { - dec2base(i,2,inb); // input in binary - //printf("input = %d \ninputs = ",i); - //for(int j=0;j<inb.size();j++) printf("%d ",inb[j]); printf("\n"); - - // evaluate next state - for(int j=0;j<k;j++) - nsx[j] = (inb[j]*bases_x[j]+sx[j])/2; // next state (for each shift register) MSB first - d_NS[s*d_I+i]=bases2dec(nsx,bases_x); // collect all values into the new state - - // evaluate transitions - for(int j=0;j<k;j++) - tx[j] = inb[j]*bases_x[j]+sx[j]; // transition (for each shift register)MSB first - for(int j=0;j<k;j++) { - dec2base(tx[j],2,tb[j]); // transition in binary - //printf("transition = %d \ntransitions = ",tx[j]); - //for(int m=0;m<tb[j].size();m++) printf("%d ",tb[j][m]); printf("\n"); - } - - // evaluate outputs - for(int nn=0;nn<n;nn++) { - outb[nn] = 0; - for(int j=0;j<k;j++) { - for(int m=0;m<max_mem+1;m++) - outb[nn] = (outb[nn] + Gb[j*n+nn][m]*tb[j][m]) % 2; // careful: polynomial 1+D ir represented as 110, not as 011 - //printf("output %d equals %d\n",nn,outb[nn]); - } - } - d_OS[s*d_I+i] = base2dec(outb,2); - } - } - - generate_PS_PI(); - generate_TM(); + // printf("max_mem_x\n"); + // for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n"); + + // calculate total memory requirements to set S + int sum_max_mem = 0; + for (int i = 0; i < k; i++) + sum_max_mem += max_mem_x[i]; + + // printf("sum_max_mem = %d\n",sum_max_mem); + + d_I = 1 << k; + d_S = 1 << sum_max_mem; + d_O = 1 << n; + + // binary representation of the G matrix + std::vector<std::vector<int>> Gb(k * n); + for (int j = 0; j < k * n; j++) { + Gb[j].resize(max_mem + 1); + dec2base(G[j], 2, Gb[j]); + // printf("Gb\n"); + // for(int m=0;m<Gb[j].size();m++) printf("%d ",Gb[j][m]); printf("\n"); } - //###################################################################### - //# Automatically generate an FSM specification describing the - //# ISI for a channel - //# of length ch_length and a modulation of size mod_size - //###################################################################### - fsm::fsm(int mod_size, int ch_length) - { - d_I=mod_size; - d_S=(int) (pow(1.0*d_I,1.0*ch_length-1)+0.5); - d_O=d_S*d_I; - - d_NS.resize(d_I*d_S); - d_OS.resize(d_I*d_S); - - for(int s=0;s<d_S;s++) { - for(int i=0;i<d_I;i++) { - int t=i*d_S+s; - d_NS[s*d_I+i] = t/d_I; - d_OS[s*d_I+i] = t; - } - } - - generate_PS_PI(); - generate_TM(); + // alphabet size of each shift register + std::vector<int> bases_x(k); + for (int j = 0; j < k; j++) + bases_x[j] = 1 << max_mem_x[j]; + // printf("bases_x\n"); + // for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n"); + + d_NS.resize(d_I * d_S); + d_OS.resize(d_I * d_S); + + std::vector<int> sx(k); + std::vector<int> nsx(k); + std::vector<int> tx(k); + std::vector<std::vector<int>> tb(k); + for (int j = 0; j < k; j++) + tb[j].resize(max_mem + 1); + std::vector<int> inb(k); + std::vector<int> outb(n); + + for (int s = 0; s < d_S; s++) { + dec2bases( + s, + bases_x, + sx); // split s into k values, each representing one of the k shift registers + // printf("state = %d \nstates = ",s); + // for(int j=0;j<sx.size();j++) printf("%d ",sx[j]); printf("\n"); + for (int i = 0; i < d_I; i++) { + dec2base(i, 2, inb); // input in binary + // printf("input = %d \ninputs = ",i); + // for(int j=0;j<inb.size();j++) printf("%d ",inb[j]); printf("\n"); + + // evaluate next state + for (int j = 0; j < k; j++) + nsx[j] = (inb[j] * bases_x[j] + sx[j]) / + 2; // next state (for each shift register) MSB first + d_NS[s * d_I + i] = + bases2dec(nsx, bases_x); // collect all values into the new state + + // evaluate transitions + for (int j = 0; j < k; j++) + tx[j] = inb[j] * bases_x[j] + + sx[j]; // transition (for each shift register)MSB first + for (int j = 0; j < k; j++) { + dec2base(tx[j], 2, tb[j]); // transition in binary + // printf("transition = %d \ntransitions = ",tx[j]); + // for(int m=0;m<tb[j].size();m++) printf("%d ",tb[j][m]); printf("\n"); + } + + // evaluate outputs + for (int nn = 0; nn < n; nn++) { + outb[nn] = 0; + for (int j = 0; j < k; j++) { + for (int m = 0; m < max_mem + 1; m++) + outb[nn] = (outb[nn] + Gb[j * n + nn][m] * tb[j][m]) % + 2; // careful: polynomial 1+D ir represented as 110, + // not as 011 + // printf("output %d equals %d\n",nn,outb[nn]); + } + } + d_OS[s * d_I + i] = base2dec(outb, 2); + } } - //###################################################################### - //# Automatically generate an FSM specification describing the - //# the trellis for a CPM with h=K/P (relatively prime), - //# alphabet size M, and frequency pulse duration L symbols - //# - //# This FSM is based on the paper by B. Rimoldi - //# "A decomposition approach to CPM", IEEE Trans. Info Theory, March 1988 - //# See also my own notes at http://www.eecs.umich.edu/~anastas/docs/cpm.pdf - //###################################################################### - fsm::fsm(int P, int M, int L) - { - d_I=M; - d_S=(int)(pow(1.0*M,1.0*L-1)+0.5)*P; - d_O=(int)(pow(1.0*M,1.0*L)+0.5)*P; - - d_NS.resize(d_I*d_S); - d_OS.resize(d_I*d_S); - int nv; - for(int s=0;s<d_S;s++) { - for(int i=0;i<d_I;i++) { - int s1=s/P; - int v=s%P; - int ns1= (i*(int)(pow(1.0*M,1.0*(L-1))+0.5)+s1)/M; - if (L==1) - nv=(i+v)%P; - else - nv=(s1%M+v)%P; - d_NS[s*d_I+i] = ns1*P+nv; - d_OS[s*d_I+i] = i*d_S+s; - } - } - - generate_PS_PI(); - generate_TM(); + generate_PS_PI(); + generate_TM(); +} + +//###################################################################### +//# Automatically generate an FSM specification describing the +//# ISI for a channel +//# of length ch_length and a modulation of size mod_size +//###################################################################### +fsm::fsm(int mod_size, int ch_length) +{ + d_I = mod_size; + d_S = (int)(pow(1.0 * d_I, 1.0 * ch_length - 1) + 0.5); + d_O = d_S * d_I; + + d_NS.resize(d_I * d_S); + d_OS.resize(d_I * d_S); + + for (int s = 0; s < d_S; s++) { + for (int i = 0; i < d_I; i++) { + int t = i * d_S + s; + d_NS[s * d_I + i] = t / d_I; + d_OS[s * d_I + i] = t; + } } - //###################################################################### - //# Automatically generate an FSM specification describing the - //# the joint trellis of fsm1 and fsm2 - //###################################################################### - fsm::fsm(const fsm &FSM1, const fsm &FSM2) - { - d_I=FSM1.I()*FSM2.I(); - d_S=FSM1.S()*FSM2.S(); - d_O=FSM1.O()*FSM2.O(); - - d_NS.resize(d_I*d_S); - d_OS.resize(d_I*d_S); - - for(int s=0;s<d_S;s++) { - for(int i=0;i<d_I;i++) { - int s1=s/FSM2.S(); - int s2=s%FSM2.S(); - int i1=i/FSM2.I(); - int i2=i%FSM2.I(); - d_NS[s*d_I+i] = FSM1.NS()[s1 * FSM1.I() + i1] * FSM2.S() + FSM2.NS()[s2 * FSM2.I() + i2]; - d_OS[s*d_I+i] = FSM1.OS()[s1 * FSM1.I() + i1] * FSM2.O() + FSM2.OS()[s2 * FSM2.I() + i2]; - } - } - - generate_PS_PI(); - generate_TM(); + generate_PS_PI(); + generate_TM(); +} + +//###################################################################### +//# Automatically generate an FSM specification describing the +//# the trellis for a CPM with h=K/P (relatively prime), +//# alphabet size M, and frequency pulse duration L symbols +//# +//# This FSM is based on the paper by B. Rimoldi +//# "A decomposition approach to CPM", IEEE Trans. Info Theory, March 1988 +//# See also my own notes at http://www.eecs.umich.edu/~anastas/docs/cpm.pdf +//###################################################################### +fsm::fsm(int P, int M, int L) +{ + d_I = M; + d_S = (int)(pow(1.0 * M, 1.0 * L - 1) + 0.5) * P; + d_O = (int)(pow(1.0 * M, 1.0 * L) + 0.5) * P; + + d_NS.resize(d_I * d_S); + d_OS.resize(d_I * d_S); + int nv; + for (int s = 0; s < d_S; s++) { + for (int i = 0; i < d_I; i++) { + int s1 = s / P; + int v = s % P; + int ns1 = (i * (int)(pow(1.0 * M, 1.0 * (L - 1)) + 0.5) + s1) / M; + if (L == 1) + nv = (i + v) % P; + else + nv = (s1 % M + v) % P; + d_NS[s * d_I + i] = ns1 * P + nv; + d_OS[s * d_I + i] = i * d_S + s; + } } + generate_PS_PI(); + generate_TM(); +} + +//###################################################################### +//# Automatically generate an FSM specification describing the +//# the joint trellis of fsm1 and fsm2 +//###################################################################### +fsm::fsm(const fsm& FSM1, const fsm& FSM2) +{ + d_I = FSM1.I() * FSM2.I(); + d_S = FSM1.S() * FSM2.S(); + d_O = FSM1.O() * FSM2.O(); + + d_NS.resize(d_I * d_S); + d_OS.resize(d_I * d_S); + + for (int s = 0; s < d_S; s++) { + for (int i = 0; i < d_I; i++) { + int s1 = s / FSM2.S(); + int s2 = s % FSM2.S(); + int i1 = i / FSM2.I(); + int i2 = i % FSM2.I(); + d_NS[s * d_I + i] = + FSM1.NS()[s1 * FSM1.I() + i1] * FSM2.S() + FSM2.NS()[s2 * FSM2.I() + i2]; + d_OS[s * d_I + i] = + FSM1.OS()[s1 * FSM1.I() + i1] * FSM2.O() + FSM2.OS()[s2 * FSM2.I() + i2]; + } + } - //###################################################################### - //# Automatically generate an FSM specification describing the - //# the joint trellis of two serially concatenated fsms. - //###################################################################### - fsm::fsm(const fsm &FSMo, const fsm &FSMi, bool serial) - { - if(serial==false || FSMo.O()!=FSMi.I()) { - d_I=0; - d_S=0; - d_O=0; + generate_PS_PI(); + generate_TM(); +} + + +//###################################################################### +//# Automatically generate an FSM specification describing the +//# the joint trellis of two serially concatenated fsms. +//###################################################################### +fsm::fsm(const fsm& FSMo, const fsm& FSMi, bool serial) +{ + if (serial == false || FSMo.O() != FSMi.I()) { + d_I = 0; + d_S = 0; + d_O = 0; d_NS.resize(0); d_OS.resize(0); d_PS.resize(0); @@ -331,243 +343,260 @@ namespace gr { d_TMi.resize(0); d_TMl.resize(0); return; - } - - d_I=FSMo.I(); - d_S=FSMo.S()*FSMi.S(); - d_O=FSMi.O(); - - d_NS.resize(d_I*d_S); - d_OS.resize(d_I*d_S); - - for(int s=0;s<d_S;s++) { - for(int i=0;i<d_I;i++) { - int so=s/FSMi.S(); - int si=s%FSMi.S(); - int oo=FSMo.OS()[so * FSMo.I() + i]; - int oi=FSMi.OS()[si * FSMi.I() + oo]; - d_NS[s*d_I+i] = FSMo.NS()[so * FSMo.I() + i] * FSMo.S() + FSMi.NS()[si * FSMi.I() + oo]; - d_OS[s*d_I+i] = oi; - } - } - - generate_PS_PI(); - generate_TM(); } - - - - - - - //###################################################################### - //# Generate a new FSM representing n stages through the original FSM - //# AKA radix-n FSM - //###################################################################### - fsm::fsm(const fsm &FSM, int n) - { - d_I=(int) (pow(1.0*FSM.I(),1.0*n)+0.5); - d_S=FSM.S(); - d_O=(int) (pow(1.0*FSM.O(),1.0*n)+0.5); - - d_NS.resize(d_I*d_S); - d_OS.resize(d_I*d_S); - - for(int s=0;s<d_S;s++ ) { - for(int i=0;i<d_I;i++ ) { - std::vector<int> ii(n); - dec2base(i,FSM.I(),ii); - std::vector<int> oo(n); - int ns=s; - for(int k=0;k<n;k++) { - oo[k]=FSM.OS()[ns*FSM.I()+ii[k]]; - ns=FSM.NS()[ns*FSM.I()+ii[k]]; - } - d_NS[s*d_I+i]=ns; - d_OS[s*d_I+i]=base2dec(oo,FSM.O()); - } - } - - generate_PS_PI(); - generate_TM(); + d_I = FSMo.I(); + d_S = FSMo.S() * FSMi.S(); + d_O = FSMi.O(); + + d_NS.resize(d_I * d_S); + d_OS.resize(d_I * d_S); + + for (int s = 0; s < d_S; s++) { + for (int i = 0; i < d_I; i++) { + int so = s / FSMi.S(); + int si = s % FSMi.S(); + int oo = FSMo.OS()[so * FSMo.I() + i]; + int oi = FSMi.OS()[si * FSMi.I() + oo]; + d_NS[s * d_I + i] = + FSMo.NS()[so * FSMo.I() + i] * FSMo.S() + FSMi.NS()[si * FSMi.I() + oo]; + d_OS[s * d_I + i] = oi; + } } - //###################################################################### - //# generate the PS and PI tables for later use - //###################################################################### - void - fsm::generate_PS_PI() - { - d_PS.resize(d_S); - d_PI.resize(d_S); - - for(int i=0;i<d_S;i++) { - d_PS[i].resize(d_I*d_S); // max possible size - d_PI[i].resize(d_I*d_S); - int j=0; - for(int ii=0;ii<d_S;ii++) for(int jj=0;jj<d_I;jj++) { - if(d_NS[ii*d_I+jj]!=i) continue; - d_PS[i][j]=ii; - d_PI[i][j]=jj; - j++; - } - d_PS[i].resize(j); - d_PI[i].resize(j); - } + generate_PS_PI(); + generate_TM(); +} + + +//###################################################################### +//# Generate a new FSM representing n stages through the original FSM +//# AKA radix-n FSM +//###################################################################### +fsm::fsm(const fsm& FSM, int n) +{ + d_I = (int)(pow(1.0 * FSM.I(), 1.0 * n) + 0.5); + d_S = FSM.S(); + d_O = (int)(pow(1.0 * FSM.O(), 1.0 * n) + 0.5); + + d_NS.resize(d_I * d_S); + d_OS.resize(d_I * d_S); + + for (int s = 0; s < d_S; s++) { + for (int i = 0; i < d_I; i++) { + std::vector<int> ii(n); + dec2base(i, FSM.I(), ii); + std::vector<int> oo(n); + int ns = s; + for (int k = 0; k < n; k++) { + oo[k] = FSM.OS()[ns * FSM.I() + ii[k]]; + ns = FSM.NS()[ns * FSM.I() + ii[k]]; + } + d_NS[s * d_I + i] = ns; + d_OS[s * d_I + i] = base2dec(oo, FSM.O()); + } } - //###################################################################### - //# generate the termination matrices TMl and TMi for later use - //###################################################################### - void - fsm::generate_TM() - { - d_TMi.resize(d_S*d_S); - d_TMl.resize(d_S*d_S); - - for(int i=0;i<d_S*d_S;i++) { - d_TMi[i] = -1; // no meaning - d_TMl[i] = d_S; //infinity: you need at most S-1 steps - if (i/d_S == i%d_S) - d_TMl[i] = 0; - } - - for(int s=0;s<d_S;s++) { - bool done = false; - int attempts = 0; - while (done == false && attempts < d_S-1) { - done = find_es(s); - attempts ++; - } - if (done == false && d_S > 1) { - //throw std::runtime_error ("fsm::generate_TM(): FSM appears to be disconnected\n"); - printf("fsm::generate_TM(): FSM appears to be disconnected\n"); - printf("state %d cannot be reached from all other states\n",s); - } - } + generate_PS_PI(); + generate_TM(); +} + +//###################################################################### +//# generate the PS and PI tables for later use +//###################################################################### +void fsm::generate_PS_PI() +{ + d_PS.resize(d_S); + d_PI.resize(d_S); + + for (int i = 0; i < d_S; i++) { + d_PS[i].resize(d_I * d_S); // max possible size + d_PI[i].resize(d_I * d_S); + int j = 0; + for (int ii = 0; ii < d_S; ii++) + for (int jj = 0; jj < d_I; jj++) { + if (d_NS[ii * d_I + jj] != i) + continue; + d_PS[i][j] = ii; + d_PI[i][j] = jj; + j++; + } + d_PS[i].resize(j); + d_PI[i].resize(j); } - - // find a path from any state to the ending state "es" - bool - fsm::find_es(int es) - { - bool done = true; - for(int s=0;s<d_S;s++) { - if(d_TMl[s*d_S+es] < d_S) - continue; - int minl=d_S; - int mini=-1; - for(int i=0;i<d_I;i++) { - if( 1 + d_TMl[d_NS[s*d_I+i]*d_S+es] < minl) { - minl = 1 + d_TMl[d_NS[s*d_I+i]*d_S+es]; - mini = i; - } - } - if (mini != -1) { - d_TMl[s*d_S+es]=minl; - d_TMi[s*d_S+es]=mini; - } - else - done = false; - } - return done; +} + +//###################################################################### +//# generate the termination matrices TMl and TMi for later use +//###################################################################### +void fsm::generate_TM() +{ + d_TMi.resize(d_S * d_S); + d_TMl.resize(d_S * d_S); + + for (int i = 0; i < d_S * d_S; i++) { + d_TMi[i] = -1; // no meaning + d_TMl[i] = d_S; // infinity: you need at most S-1 steps + if (i / d_S == i % d_S) + d_TMl[i] = 0; } - //###################################################################### - //# generate trellis representation of FSM as an SVG file - //###################################################################### - void - fsm::write_trellis_svg(std::string filename, int number_stages) - { - std::ofstream trellis_fname (filename.c_str()); - if(!trellis_fname) { - std::cout << "file not found " << std::endl ; exit(-1); - } - const int TRELLIS_Y_OFFSET = 30; - const int TRELLIS_X_OFFSET = 20; - const int STAGE_LABEL_Y_OFFSET = 25; - const int STAGE_LABEL_X_OFFSET = 20; - const int STATE_LABEL_Y_OFFSET = 30; - const int STATE_LABEL_X_OFFSET = 5; - const int STAGE_STATE_OFFSETS = 10; - // std::cout << "################## BEGIN SVG TRELLIS PIC #####################" << std::endl; - trellis_fname << - "<?xml version=\"1.0\" standalone=\"no\"?>" - "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" - "<svg viewBox=\"0 0 200 200\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">" - << std::endl; - - for(int stage_num = 0;stage_num < number_stages;stage_num ++) { - // draw states - for(int state_num = 0;state_num < d_S ; state_num ++ ) { - trellis_fname << "<circle cx = \"" << stage_num * STAGE_STATE_OFFSETS + TRELLIS_X_OFFSET << - "\" cy = \"" << state_num * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET << "\" r = \"1\"/>" << std::endl; - //draw branches - if(stage_num != number_stages-1) { - for(int branch_num = 0;branch_num < d_I; branch_num++) { - trellis_fname << "<line x1 =\"" << STAGE_STATE_OFFSETS * stage_num+ TRELLIS_X_OFFSET << "\" "; - trellis_fname << "y1 =\"" << state_num * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET<< "\" "; - trellis_fname << "x2 =\"" << STAGE_STATE_OFFSETS *stage_num + STAGE_STATE_OFFSETS+ TRELLIS_X_OFFSET << "\" "; - trellis_fname << "y2 =\"" << d_NS[d_I * state_num + branch_num] * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET << "\" "; - trellis_fname << " stroke-dasharray = \"3," << branch_num << "\" "; - trellis_fname << " stroke = \"black\" stroke-width = \"0.3\"/>" << std::endl; - } - } - } - } - // label the stages - trellis_fname << "<g font-size = \"4\" font= \"times\" fill = \"black\">" << std::endl; - for(int stage_num = 0;stage_num < number_stages ;stage_num ++) { - trellis_fname << "<text x = \"" << stage_num * STAGE_STATE_OFFSETS + STAGE_LABEL_X_OFFSET << - "\" y = \"" << STAGE_LABEL_Y_OFFSET << "\" >" << std::endl; - trellis_fname << stage_num << std::endl; - trellis_fname << "</text>" << std::endl; - } - trellis_fname << "</g>" << std::endl; - - // label the states - trellis_fname << "<g font-size = \"4\" font= \"times\" fill = \"black\">" << std::endl; - for(int state_num = 0;state_num < d_S ; state_num ++) { - trellis_fname << "<text y = \"" << state_num * STAGE_STATE_OFFSETS + STATE_LABEL_Y_OFFSET << - "\" x = \"" << STATE_LABEL_X_OFFSET << "\" >" << std::endl; - trellis_fname << state_num << std::endl; - trellis_fname << "</text>" << std::endl; - } - trellis_fname << "</g>" << std::endl; - - trellis_fname << "</svg>" << std::endl; - // std::cout << "################## END SVG TRELLIS PIC ##################### " << std::endl; - trellis_fname.close(); + for (int s = 0; s < d_S; s++) { + bool done = false; + int attempts = 0; + while (done == false && attempts < d_S - 1) { + done = find_es(s); + attempts++; + } + if (done == false && d_S > 1) { + // throw std::runtime_error ("fsm::generate_TM(): FSM appears to be + // disconnected\n"); + printf("fsm::generate_TM(): FSM appears to be disconnected\n"); + printf("state %d cannot be reached from all other states\n", s); + } } - - //###################################################################### - //# Write trellis specification to a text file, - //# in the same format used when reading FSM files - //###################################################################### - void - fsm::write_fsm_txt(std::string filename) - { - std::ofstream trellis_fname (filename.c_str()); - if(!trellis_fname) { - std::cout << "file not found " << std::endl ; exit(-1); - } - trellis_fname << d_I << ' ' << d_S << ' ' << d_O << std::endl; - trellis_fname << std::endl; - for(int i=0;i<d_S;i++) { - for(int j=0;j<d_I;j++) - trellis_fname << d_NS[i*d_I+j] << ' '; - trellis_fname << std::endl; - } - trellis_fname << std::endl; - for(int i=0;i<d_S;i++) { - for(int j=0;j<d_I;j++) - trellis_fname << d_OS[i*d_I+j] << ' '; - trellis_fname << std::endl; - } - trellis_fname << std::endl; - trellis_fname.close(); +} + +// find a path from any state to the ending state "es" +bool fsm::find_es(int es) +{ + bool done = true; + for (int s = 0; s < d_S; s++) { + if (d_TMl[s * d_S + es] < d_S) + continue; + int minl = d_S; + int mini = -1; + for (int i = 0; i < d_I; i++) { + if (1 + d_TMl[d_NS[s * d_I + i] * d_S + es] < minl) { + minl = 1 + d_TMl[d_NS[s * d_I + i] * d_S + es]; + mini = i; + } + } + if (mini != -1) { + d_TMl[s * d_S + es] = minl; + d_TMi[s * d_S + es] = mini; + } else + done = false; + } + return done; +} + +//###################################################################### +//# generate trellis representation of FSM as an SVG file +//###################################################################### +void fsm::write_trellis_svg(std::string filename, int number_stages) +{ + std::ofstream trellis_fname(filename.c_str()); + if (!trellis_fname) { + std::cout << "file not found " << std::endl; + exit(-1); + } + const int TRELLIS_Y_OFFSET = 30; + const int TRELLIS_X_OFFSET = 20; + const int STAGE_LABEL_Y_OFFSET = 25; + const int STAGE_LABEL_X_OFFSET = 20; + const int STATE_LABEL_Y_OFFSET = 30; + const int STATE_LABEL_X_OFFSET = 5; + const int STAGE_STATE_OFFSETS = 10; + // std::cout << "################## BEGIN SVG TRELLIS PIC #####################" << + // std::endl; + trellis_fname << "<?xml version=\"1.0\" standalone=\"no\"?>" + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" " + "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" + "<svg viewBox=\"0 0 200 200\" version=\"1.1\" " + "xmlns=\"http://www.w3.org/2000/svg\">" + << std::endl; + + for (int stage_num = 0; stage_num < number_stages; stage_num++) { + // draw states + for (int state_num = 0; state_num < d_S; state_num++) { + trellis_fname << "<circle cx = \"" + << stage_num * STAGE_STATE_OFFSETS + TRELLIS_X_OFFSET + << "\" cy = \"" + << state_num * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET + << "\" r = \"1\"/>" << std::endl; + // draw branches + if (stage_num != number_stages - 1) { + for (int branch_num = 0; branch_num < d_I; branch_num++) { + trellis_fname << "<line x1 =\"" + << STAGE_STATE_OFFSETS * stage_num + TRELLIS_X_OFFSET + << "\" "; + trellis_fname << "y1 =\"" + << state_num * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET + << "\" "; + trellis_fname << "x2 =\"" + << STAGE_STATE_OFFSETS * stage_num + + STAGE_STATE_OFFSETS + TRELLIS_X_OFFSET + << "\" "; + trellis_fname + << "y2 =\"" + << d_NS[d_I * state_num + branch_num] * STAGE_STATE_OFFSETS + + TRELLIS_Y_OFFSET + << "\" "; + trellis_fname << " stroke-dasharray = \"3," << branch_num << "\" "; + trellis_fname << " stroke = \"black\" stroke-width = \"0.3\"/>" + << std::endl; + } + } + } + } + // label the stages + trellis_fname << "<g font-size = \"4\" font= \"times\" fill = \"black\">" + << std::endl; + for (int stage_num = 0; stage_num < number_stages; stage_num++) { + trellis_fname << "<text x = \"" + << stage_num * STAGE_STATE_OFFSETS + STAGE_LABEL_X_OFFSET + << "\" y = \"" << STAGE_LABEL_Y_OFFSET << "\" >" << std::endl; + trellis_fname << stage_num << std::endl; + trellis_fname << "</text>" << std::endl; + } + trellis_fname << "</g>" << std::endl; + + // label the states + trellis_fname << "<g font-size = \"4\" font= \"times\" fill = \"black\">" + << std::endl; + for (int state_num = 0; state_num < d_S; state_num++) { + trellis_fname << "<text y = \"" + << state_num * STAGE_STATE_OFFSETS + STATE_LABEL_Y_OFFSET + << "\" x = \"" << STATE_LABEL_X_OFFSET << "\" >" << std::endl; + trellis_fname << state_num << std::endl; + trellis_fname << "</text>" << std::endl; + } + trellis_fname << "</g>" << std::endl; + + trellis_fname << "</svg>" << std::endl; + // std::cout << "################## END SVG TRELLIS PIC ##################### " << + // std::endl; + trellis_fname.close(); +} + +//###################################################################### +//# Write trellis specification to a text file, +//# in the same format used when reading FSM files +//###################################################################### +void fsm::write_fsm_txt(std::string filename) +{ + std::ofstream trellis_fname(filename.c_str()); + if (!trellis_fname) { + std::cout << "file not found " << std::endl; + exit(-1); + } + trellis_fname << d_I << ' ' << d_S << ' ' << d_O << std::endl; + trellis_fname << std::endl; + for (int i = 0; i < d_S; i++) { + for (int j = 0; j < d_I; j++) + trellis_fname << d_NS[i * d_I + j] << ' '; + trellis_fname << std::endl; + } + trellis_fname << std::endl; + for (int i = 0; i < d_S; i++) { + for (int j = 0; j < d_I; j++) + trellis_fname << d_OS[i * d_I + j] << ' '; + trellis_fname << std::endl; } + trellis_fname << std::endl; + trellis_fname.close(); +} - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/interleaver.cc b/gr-trellis/lib/interleaver.cc index 72bb296e5f..ae6fb05aa2 100644 --- a/gr-trellis/lib/interleaver.cc +++ b/gr-trellis/lib/interleaver.cc @@ -32,131 +32,132 @@ #include <gnuradio/xoroshiro128p.h> namespace gr { - namespace trellis { - - interleaver::interleaver() - { - d_K=0; - d_INTER.resize(0); - d_DEINTER.resize(0); +namespace trellis { + +interleaver::interleaver() +{ + d_K = 0; + d_INTER.resize(0); + d_DEINTER.resize(0); +} + +interleaver::interleaver(const interleaver& INTERLEAVER) +{ + d_K = INTERLEAVER.K(); + d_INTER = INTERLEAVER.INTER(); + d_DEINTER = INTERLEAVER.DEINTER(); +} + +interleaver::interleaver(unsigned int K, const std::vector<int>& INTER) +{ + d_K = K; + d_INTER = INTER; + d_DEINTER.resize(d_K); + + // generate DEINTER table + for (unsigned int i = 0; i < d_K; i++) { + d_DEINTER[d_INTER[i]] = i; } - - interleaver::interleaver(const interleaver &INTERLEAVER) - { - d_K=INTERLEAVER.K(); - d_INTER=INTERLEAVER.INTER(); - d_DEINTER=INTERLEAVER.DEINTER(); +} + +//###################################################################### +//# Read an INTERLEAVER specification from a file. +//# Format (hopefully will become more flexible in the future...): +//# K +//# blank line +//# list of space separated K integers from 0 to K-1 in appropriate order +//# optional comments +//###################################################################### +interleaver::interleaver(const char* name) +{ + FILE* interleaverfile; + + if ((interleaverfile = fopen(name, "r")) == NULL) + throw std::runtime_error("file open error in interleaver()"); + // printf("file open error in interleaver()\n"); + + if (fscanf(interleaverfile, "%d\n", &d_K) == EOF) { + if (ferror(interleaverfile) != 0) + throw std::runtime_error( + "interleaver::interleaver(const char *name): file read error\n"); } - interleaver::interleaver(unsigned int K, const std::vector<int> &INTER) - { - d_K=K; - d_INTER=INTER; - d_DEINTER.resize(d_K); + d_INTER.resize(d_K); + d_DEINTER.resize(d_K); - // generate DEINTER table - for(unsigned int i = 0; i < d_K; i++) { - d_DEINTER[d_INTER[i]]=i; - } + for (unsigned int i = 0; i < d_K; i++) { + if (fscanf(interleaverfile, "%d", &(d_INTER[i])) == EOF) { + if (ferror(interleaverfile) != 0) + throw std::runtime_error( + "interleaver::interleaver(const char *name): file read error\n"); + } } - //###################################################################### - //# Read an INTERLEAVER specification from a file. - //# Format (hopefully will become more flexible in the future...): - //# K - //# blank line - //# list of space separated K integers from 0 to K-1 in appropriate order - //# optional comments - //###################################################################### - interleaver::interleaver(const char *name) - { - FILE *interleaverfile; - - if((interleaverfile=fopen(name,"r")) == NULL) - throw std::runtime_error ("file open error in interleaver()"); - //printf("file open error in interleaver()\n"); - - if(fscanf(interleaverfile,"%d\n",&d_K) == EOF) { - if(ferror(interleaverfile) != 0) - throw std::runtime_error ("interleaver::interleaver(const char *name): file read error\n"); - } - - d_INTER.resize(d_K); - d_DEINTER.resize(d_K); - - for (unsigned int i = 0; i < d_K; i++) { - if (fscanf(interleaverfile, "%d", &(d_INTER[i])) == EOF) { - if (ferror(interleaverfile) != 0) - throw std::runtime_error( - "interleaver::interleaver(const char *name): file read error\n"); - } - } - - // generate DEINTER table - for (unsigned int i = 0; i < d_K; i++) { - d_DEINTER[d_INTER[i]] = i; - } - - fclose(interleaverfile); + // generate DEINTER table + for (unsigned int i = 0; i < d_K; i++) { + d_DEINTER[d_INTER[i]] = i; } - //###################################################################### - //# Generate a random interleaver - //###################################################################### - interleaver::interleaver(unsigned int K, int seed) - { - d_K=K; - d_INTER.resize(d_K); - d_DEINTER.resize(d_K); - - uint64_t rng_state[2]; - xoroshiro128p_seed(rng_state, seed); - std::vector<int> tmp(d_K); - unsigned char *bytes = reinterpret_cast<unsigned char*>(&tmp[0]); - - for(unsigned int i = 0; i < d_K; i += 8) { - *(reinterpret_cast<uint64_t*>(bytes + i)) = xoroshiro128p_next(rng_state); - } - if(d_K % 8) { - uint64_t randval = xoroshiro128p_next(rng_state); - unsigned char *valptr = reinterpret_cast<unsigned char*>(&randval); - for(unsigned int idx = (d_K / 8)*8; idx < d_K; ++idx) { - bytes[idx] = *valptr++; - } - } - for (unsigned int i = 0; i < d_K; i++) { - d_INTER[i] = i; - } - quicksort_index <int> (tmp,d_INTER,0,d_K-1); - - // generate DEINTER table - for(unsigned int i=0;i<d_K;i++) { - d_DEINTER[d_INTER[i]]=i; - } + fclose(interleaverfile); +} + +//###################################################################### +//# Generate a random interleaver +//###################################################################### +interleaver::interleaver(unsigned int K, int seed) +{ + d_K = K; + d_INTER.resize(d_K); + d_DEINTER.resize(d_K); + + uint64_t rng_state[2]; + xoroshiro128p_seed(rng_state, seed); + std::vector<int> tmp(d_K); + unsigned char* bytes = reinterpret_cast<unsigned char*>(&tmp[0]); + + for (unsigned int i = 0; i < d_K; i += 8) { + *(reinterpret_cast<uint64_t*>(bytes + i)) = xoroshiro128p_next(rng_state); } - - //###################################################################### - //# Write an INTERLEAVER specification to a file. - //# Format - //# K - //# blank line - //# list of space separated K integers from 0 to K-1 in appropriate order - //# optional comments - //###################################################################### - void - interleaver::write_interleaver_txt(std::string filename) - { - std::ofstream interleaver_fname (filename.c_str()); - if(!interleaver_fname) { - std::cout << "file not found " << std::endl ; exit(-1); - } - interleaver_fname << d_K << std::endl; - interleaver_fname << std::endl; - for(unsigned int i=0;i<d_K;i++) - interleaver_fname << d_INTER[i] << ' '; - interleaver_fname << std::endl; - interleaver_fname.close(); + if (d_K % 8) { + uint64_t randval = xoroshiro128p_next(rng_state); + unsigned char* valptr = reinterpret_cast<unsigned char*>(&randval); + for (unsigned int idx = (d_K / 8) * 8; idx < d_K; ++idx) { + bytes[idx] = *valptr++; + } } + for (unsigned int i = 0; i < d_K; i++) { + d_INTER[i] = i; + } + quicksort_index<int>(tmp, d_INTER, 0, d_K - 1); - } /* namespace trellis */ + // generate DEINTER table + for (unsigned int i = 0; i < d_K; i++) { + d_DEINTER[d_INTER[i]] = i; + } +} + +//###################################################################### +//# Write an INTERLEAVER specification to a file. +//# Format +//# K +//# blank line +//# list of space separated K integers from 0 to K-1 in appropriate order +//# optional comments +//###################################################################### +void interleaver::write_interleaver_txt(std::string filename) +{ + std::ofstream interleaver_fname(filename.c_str()); + if (!interleaver_fname) { + std::cout << "file not found " << std::endl; + exit(-1); + } + interleaver_fname << d_K << std::endl; + interleaver_fname << std::endl; + for (unsigned int i = 0; i < d_K; i++) + interleaver_fname << d_INTER[i] << ' '; + interleaver_fname << std::endl; + interleaver_fname.close(); +} + +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/metrics_impl.cc b/gr-trellis/lib/metrics_impl.cc index 1ed6c69803..f3ebb4f5d3 100644 --- a/gr-trellis/lib/metrics_impl.cc +++ b/gr-trellis/lib/metrics_impl.cc @@ -32,104 +32,105 @@ #include <iostream> namespace gr { - namespace trellis { - - template <class T> - typename metrics<T>::sptr - metrics<T>::make(int O, int D, const std::vector<T> &TABLE, - digital::trellis_metric_type_t TYPE) - { - return gnuradio::get_initial_sptr - (new metrics_impl<T>(O,D,TABLE,TYPE)); - } - - template <class T> - metrics_impl<T>::metrics_impl(int O, int D, const std::vector<T> &TABLE, - digital::trellis_metric_type_t TYPE) +namespace trellis { + +template <class T> +typename metrics<T>::sptr metrics<T>::make(int O, + int D, + const std::vector<T>& TABLE, + digital::trellis_metric_type_t TYPE) +{ + return gnuradio::get_initial_sptr(new metrics_impl<T>(O, D, TABLE, TYPE)); +} + +template <class T> +metrics_impl<T>::metrics_impl(int O, + int D, + const std::vector<T>& TABLE, + digital::trellis_metric_type_t TYPE) : block("metrics", - io_signature::make(1, -1, sizeof (T)), - io_signature::make(1, -1, sizeof (float))), - d_O(O), d_D(D), d_TYPE(TYPE), d_TABLE(TABLE) - { - this->set_relative_rate ((uint64_t)d_O, (uint64_t)d_D); - this->set_output_multiple ((int)d_O); - } - - template <class T> - void metrics_impl<T>::set_O(int O) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_O = O; - this->set_relative_rate ((uint64_t)d_O, (uint64_t)d_D); - this->set_output_multiple ((int)d_O); - } - - template <class T> - void metrics_impl<T>::set_D(int D) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_D = D; - this->set_relative_rate ((uint64_t)d_O, (uint64_t)d_D); - } - - template <class T> - void - metrics_impl<T>::set_TYPE(digital::trellis_metric_type_t type) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_TYPE = type; + io_signature::make(1, -1, sizeof(T)), + io_signature::make(1, -1, sizeof(float))), + d_O(O), + d_D(D), + d_TYPE(TYPE), + d_TABLE(TABLE) +{ + this->set_relative_rate((uint64_t)d_O, (uint64_t)d_D); + this->set_output_multiple((int)d_O); +} + +template <class T> +void metrics_impl<T>::set_O(int O) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_O = O; + this->set_relative_rate((uint64_t)d_O, (uint64_t)d_D); + this->set_output_multiple((int)d_O); +} + +template <class T> +void metrics_impl<T>::set_D(int D) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_D = D; + this->set_relative_rate((uint64_t)d_O, (uint64_t)d_D); +} + +template <class T> +void metrics_impl<T>::set_TYPE(digital::trellis_metric_type_t type) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_TYPE = type; +} + +template <class T> +void metrics_impl<T>::set_TABLE(const std::vector<T>& table) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_TABLE = table; +} + +template <class T> +metrics_impl<T>::~metrics_impl() +{ +} + + +template <class T> +void metrics_impl<T>::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + int input_required = d_D * noutput_items / d_O; + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = input_required; +} + +template <class T> +int metrics_impl<T>::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(this->d_setlock); + int nstreams = input_items.size(); + + for (int m = 0; m < nstreams; m++) { + const T* in = (T*)input_items[m]; + float* out = (float*)output_items[m]; + + for (int i = 0; i < noutput_items / d_O; i++) { + calc_metric(d_O, d_D, d_TABLE, &(in[i * d_D]), &(out[i * d_O]), d_TYPE); + } } - template <class T> - void - metrics_impl<T>::set_TABLE(const std::vector<T> &table) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_TABLE = table; - } - - template <class T> - metrics_impl<T>::~metrics_impl() - { - } - - - template <class T> - void - metrics_impl<T>::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - int input_required = d_D * noutput_items / d_O; - unsigned ninputs = ninput_items_required.size(); - for(unsigned int i = 0; i < ninputs; i++) - ninput_items_required[i] = input_required; - } - - template <class T> - int - metrics_impl<T>::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(this->d_setlock); - int nstreams = input_items.size(); - - for(int m = 0; m < nstreams; m++) { - const T *in = (T*)input_items[m]; - float *out = (float*)output_items[m]; - - for(int i = 0; i < noutput_items / d_O ; i++) { - calc_metric(d_O, d_D, d_TABLE,&(in[i*d_D]), &(out[i*d_O]), d_TYPE); - } - } - - this->consume_each(d_D * noutput_items / d_O); - return noutput_items; - } + this->consume_each(d_D * noutput_items / d_O); + return noutput_items; +} template class metrics<std::int16_t>; template class metrics<std::int32_t>; template class metrics<float>; template class metrics<gr_complex>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/metrics_impl.h b/gr-trellis/lib/metrics_impl.h index 95c5f44845..a6f6d8baa4 100644 --- a/gr-trellis/lib/metrics_impl.h +++ b/gr-trellis/lib/metrics_impl.h @@ -27,42 +27,43 @@ #include <gnuradio/trellis/metrics.h> namespace gr { - namespace trellis { +namespace trellis { -template<class T> - class metrics_impl : public metrics<T> - { - private: - int d_O; - int d_D; - digital::trellis_metric_type_t d_TYPE; - std::vector<T> d_TABLE; +template <class T> +class metrics_impl : public metrics<T> +{ +private: + int d_O; + int d_D; + digital::trellis_metric_type_t d_TYPE; + std::vector<T> d_TABLE; - public: - metrics_impl(int O, int D, const std::vector<T> &TABLE, - digital::trellis_metric_type_t TYPE); - ~metrics_impl(); +public: + metrics_impl(int O, + int D, + const std::vector<T>& TABLE, + digital::trellis_metric_type_t TYPE); + ~metrics_impl(); - int O() const { return d_O; } - int D() const { return d_D; } - digital::trellis_metric_type_t TYPE() const { return d_TYPE; } - std::vector<T> TABLE() const { return d_TABLE; } + int O() const { return d_O; } + int D() const { return d_D; } + digital::trellis_metric_type_t TYPE() const { return d_TYPE; } + std::vector<T> TABLE() const { return d_TABLE; } - void set_O(int O); - void set_D(int D); - void set_TYPE(digital::trellis_metric_type_t type); - void set_TABLE(const std::vector<T> &table); + void set_O(int O); + void set_D(int D); + void set_TYPE(digital::trellis_metric_type_t type); + void set_TABLE(const std::vector<T>& table); - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* METRICS_IMPL_H */ diff --git a/gr-trellis/lib/pccc_decoder_blk_impl.cc b/gr-trellis/lib/pccc_decoder_blk_impl.cc index b001998416..d6c817685d 100644 --- a/gr-trellis/lib/pccc_decoder_blk_impl.cc +++ b/gr-trellis/lib/pccc_decoder_blk_impl.cc @@ -31,95 +31,114 @@ #include <gnuradio/trellis/core_algorithms.h> namespace gr { - namespace trellis { +namespace trellis { - template <class T> - typename pccc_decoder_blk<T>::sptr - pccc_decoder_blk<T>::make(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE) - { - return gnuradio::get_initial_sptr - (new pccc_decoder_blk_impl<T>(FSM1, ST10, ST1K, - FSM2, ST20, ST2K, - INTERLEAVER, - blocklength, - repetitions, - SISO_TYPE)); - } +template <class T> +typename pccc_decoder_blk<T>::sptr +pccc_decoder_blk<T>::make(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) +{ + return gnuradio::get_initial_sptr(new pccc_decoder_blk_impl<T>(FSM1, + ST10, + ST1K, + FSM2, + ST20, + ST2K, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE)); +} - template <class T> - pccc_decoder_blk_impl<T>::pccc_decoder_blk_impl(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE) +template <class T> +pccc_decoder_blk_impl<T>::pccc_decoder_blk_impl(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) : block("pccc_decoder_blk", - io_signature::make(1, 1, sizeof(float)), - io_signature::make(1, 1, sizeof(T))), - d_FSM1(FSM1), d_ST10(ST10), d_ST1K(ST1K), - d_FSM2(FSM2), d_ST20(ST20), d_ST2K(ST2K), + io_signature::make(1, 1, sizeof(float)), + io_signature::make(1, 1, sizeof(T))), + d_FSM1(FSM1), + d_ST10(ST10), + d_ST1K(ST1K), + d_FSM2(FSM2), + d_ST20(ST20), + d_ST2K(ST2K), d_INTERLEAVER(INTERLEAVER), d_blocklength(blocklength), d_repetitions(repetitions), d_SISO_TYPE(SISO_TYPE) - { - this->set_relative_rate (1, (uint64_t)(d_FSM1.O() * d_FSM2.O())); - this->set_output_multiple (d_blocklength); - } - - template <class T> - pccc_decoder_blk_impl<T>::~pccc_decoder_blk_impl() - { - } +{ + this->set_relative_rate(1, (uint64_t)(d_FSM1.O() * d_FSM2.O())); + this->set_output_multiple(d_blocklength); +} - template <class T> - void - pccc_decoder_blk_impl<T>::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - int input_required = d_FSM1.O() * d_FSM2.O() * noutput_items; - ninput_items_required[0] = input_required; - } +template <class T> +pccc_decoder_blk_impl<T>::~pccc_decoder_blk_impl() +{ +} - //=========================================================== +template <class T> +void pccc_decoder_blk_impl<T>::forecast(int noutput_items, + gr_vector_int& ninput_items_required) +{ + int input_required = d_FSM1.O() * d_FSM2.O() * noutput_items; + ninput_items_required[0] = input_required; +} - template <class T> - int - pccc_decoder_blk_impl<T>::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - int nblocks = noutput_items / d_blocklength; +//=========================================================== - float (*p2min)(float, float) = NULL; - if(d_SISO_TYPE == TRELLIS_MIN_SUM) - p2min = &min; - else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) - p2min = &min_star; +template <class T> +int pccc_decoder_blk_impl<T>::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + int nblocks = noutput_items / d_blocklength; - const float *in = (const float *) input_items[0]; - T *out = (T *) output_items[0]; - for(int n=0;n<nblocks;n++) { - pccc_decoder(d_FSM1, d_ST10, d_ST1K, - d_FSM2, d_ST20, d_ST2K, - d_INTERLEAVER, d_blocklength, d_repetitions, - p2min, - &(in[n*d_blocklength*d_FSM1.O()*d_FSM2.O()]), - &(out[n*d_blocklength])); - } + float (*p2min)(float, float) = NULL; + if (d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if (d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; - this->consume_each(d_FSM1.O() * d_FSM2.O() * noutput_items); - return noutput_items; + const float* in = (const float*)input_items[0]; + T* out = (T*)output_items[0]; + for (int n = 0; n < nblocks; n++) { + pccc_decoder(d_FSM1, + d_ST10, + d_ST1K, + d_FSM2, + d_ST20, + d_ST2K, + d_INTERLEAVER, + d_blocklength, + d_repetitions, + p2min, + &(in[n * d_blocklength * d_FSM1.O() * d_FSM2.O()]), + &(out[n * d_blocklength])); } + this->consume_each(d_FSM1.O() * d_FSM2.O() * noutput_items); + return noutput_items; +} + template class pccc_decoder_blk<std::uint8_t>; template class pccc_decoder_blk<std::int16_t>; template class pccc_decoder_blk<std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/pccc_decoder_blk_impl.h b/gr-trellis/lib/pccc_decoder_blk_impl.h index ed4e2d24a6..047951f02f 100644 --- a/gr-trellis/lib/pccc_decoder_blk_impl.h +++ b/gr-trellis/lib/pccc_decoder_blk_impl.h @@ -27,54 +27,57 @@ #include <gnuradio/trellis/pccc_decoder_blk.h> namespace gr { - namespace trellis { +namespace trellis { -template<class T> - class pccc_decoder_blk_impl : public pccc_decoder_blk<T> - { - private: - fsm d_FSM1; - int d_ST10; - int d_ST1K; - fsm d_FSM2; - int d_ST20; - int d_ST2K; - interleaver d_INTERLEAVER; - int d_blocklength; - int d_repetitions; - siso_type_t d_SISO_TYPE; - std::vector<float> d_buffer; +template <class T> +class pccc_decoder_blk_impl : public pccc_decoder_blk<T> +{ +private: + fsm d_FSM1; + int d_ST10; + int d_ST1K; + fsm d_FSM2; + int d_ST20; + int d_ST2K; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + std::vector<float> d_buffer; - public: - pccc_decoder_blk_impl(const fsm &FSM1, int ST10, int ST1K, - const fsm &FSM2, int ST20, int ST2K, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE); - ~pccc_decoder_blk_impl(); +public: + pccc_decoder_blk_impl(const fsm& FSM1, + int ST10, + int ST1K, + const fsm& FSM2, + int ST20, + int ST2K, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE); + ~pccc_decoder_blk_impl(); - fsm FSM1() const { return d_FSM1; } - fsm FSM2() const { return d_FSM2; } - int ST10() const { return d_ST10; } - int ST1K() const { return d_ST1K; } - int ST20() const { return d_ST20; } - int ST2K() const { return d_ST2K; } - interleaver INTERLEAVER() const { return d_INTERLEAVER; } - int blocklength() const { return d_blocklength; } - int repetitions() const { return d_repetitions; } - siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + fsm FSM1() const { return d_FSM1; } + fsm FSM2() const { return d_FSM2; } + int ST10() const { return d_ST10; } + int ST1K() const { return d_ST1K; } + int ST20() const { return d_ST20; } + int ST2K() const { return d_ST2K; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* PCCC_DECODER_BLK_IMPL_H */ diff --git a/gr-trellis/lib/pccc_decoder_combined_blk_impl.cc b/gr-trellis/lib/pccc_decoder_combined_blk_impl.cc index a1e0772ab8..b8a93d9118 100644 --- a/gr-trellis/lib/pccc_decoder_combined_blk_impl.cc +++ b/gr-trellis/lib/pccc_decoder_combined_blk_impl.cc @@ -30,43 +30,67 @@ #include <gnuradio/trellis/core_algorithms.h> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T,class OUT_T> - typename pccc_decoder_combined_blk<IN_T,OUT_T>::sptr - pccc_decoder_combined_blk<IN_T,OUT_T>::make(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE, - int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling) - { - return gnuradio::get_initial_sptr - (new pccc_decoder_combined_blk_impl<IN_T,OUT_T>(FSMo, STo0, SToK, FSMi, STi0, STiK, - INTERLEAVER, blocklength, repetitions, - SISO_TYPE, D, TABLE,METRIC_TYPE, scaling)); - } +template <class IN_T, class OUT_T> +typename pccc_decoder_combined_blk<IN_T, OUT_T>::sptr +pccc_decoder_combined_blk<IN_T, OUT_T>::make(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) +{ + return gnuradio::get_initial_sptr( + new pccc_decoder_combined_blk_impl<IN_T, OUT_T>(FSMo, + STo0, + SToK, + FSMi, + STi0, + STiK, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE, + D, + TABLE, + METRIC_TYPE, + scaling)); +} - template <class IN_T,class OUT_T> - pccc_decoder_combined_blk_impl<IN_T,OUT_T>::pccc_decoder_combined_blk_impl(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE, - int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling) +template <class IN_T, class OUT_T> +pccc_decoder_combined_blk_impl<IN_T, OUT_T>::pccc_decoder_combined_blk_impl( + const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) : block("pccc_decoder_combined_blk<IN_T,OUT_T>", - io_signature::make(1, 1, sizeof(IN_T)), - io_signature::make(1, 1, sizeof(OUT_T))), - d_FSMo(FSMo), d_STo0(STo0), d_SToK(SToK), - d_FSMi(FSMi), d_STi0(STi0), d_STiK(STiK), + io_signature::make(1, 1, sizeof(IN_T)), + io_signature::make(1, 1, sizeof(OUT_T))), + d_FSMo(FSMo), + d_STo0(STo0), + d_SToK(SToK), + d_FSMi(FSMi), + d_STi0(STi0), + d_STiK(STiK), d_INTERLEAVER(INTERLEAVER), d_blocklength(blocklength), d_repetitions(repetitions), @@ -75,76 +99,81 @@ namespace gr { d_TABLE(TABLE), d_METRIC_TYPE(METRIC_TYPE), d_scaling(scaling) - { - assert(d_FSMo.I() == d_FSMi.I()); - this->set_relative_rate (1, (uint64_t) d_D); - this->set_output_multiple (d_blocklength); - } +{ + assert(d_FSMo.I() == d_FSMi.I()); + this->set_relative_rate(1, (uint64_t)d_D); + this->set_output_multiple(d_blocklength); +} - template <class IN_T,class OUT_T> - pccc_decoder_combined_blk_impl<IN_T,OUT_T>::~pccc_decoder_combined_blk_impl() - { - } +template <class IN_T, class OUT_T> +pccc_decoder_combined_blk_impl<IN_T, OUT_T>::~pccc_decoder_combined_blk_impl() +{ +} - template <class IN_T,class OUT_T> - void - pccc_decoder_combined_blk_impl<IN_T,OUT_T>::set_scaling(float scaling) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_scaling = scaling; - } +template <class IN_T, class OUT_T> +void pccc_decoder_combined_blk_impl<IN_T, OUT_T>::set_scaling(float scaling) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_scaling = scaling; +} - template <class IN_T,class OUT_T> - void - pccc_decoder_combined_blk_impl<IN_T,OUT_T>::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - int input_required = d_D * noutput_items; - ninput_items_required[0] = input_required; - } - - //=========================================================== +template <class IN_T, class OUT_T> +void pccc_decoder_combined_blk_impl<IN_T, OUT_T>::forecast( + int noutput_items, gr_vector_int& ninput_items_required) +{ + int input_required = d_D * noutput_items; + ninput_items_required[0] = input_required; +} - template <class IN_T,class OUT_T> - int - pccc_decoder_combined_blk_impl<IN_T,OUT_T>::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(this->d_setlock); - int nblocks = noutput_items / d_blocklength; +//=========================================================== - float (*p2min)(float, float) = NULL; - if(d_SISO_TYPE == TRELLIS_MIN_SUM) - p2min = &min; - else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) - p2min = &min_star; +template <class IN_T, class OUT_T> +int pccc_decoder_combined_blk_impl<IN_T, OUT_T>::general_work( + int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(this->d_setlock); + int nblocks = noutput_items / d_blocklength; - const IN_T *in = (const IN_T *) input_items[0]; - OUT_T *out = (OUT_T *) output_items[0]; - for (int n=0;n<nblocks;n++) { - pccc_decoder_combined(d_FSMo, d_STo0, d_SToK, - d_FSMi, d_STi0, d_STiK, - d_INTERLEAVER, d_blocklength, d_repetitions, - p2min, - d_D,d_TABLE, - d_METRIC_TYPE, - d_scaling, - &(in[n*d_blocklength*d_D]), - &(out[n*d_blocklength])); - } + float (*p2min)(float, float) = NULL; + if (d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if (d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; - this->consume_each(d_D * noutput_items); - return noutput_items; + const IN_T* in = (const IN_T*)input_items[0]; + OUT_T* out = (OUT_T*)output_items[0]; + for (int n = 0; n < nblocks; n++) { + pccc_decoder_combined(d_FSMo, + d_STo0, + d_SToK, + d_FSMi, + d_STi0, + d_STiK, + d_INTERLEAVER, + d_blocklength, + d_repetitions, + p2min, + d_D, + d_TABLE, + d_METRIC_TYPE, + d_scaling, + &(in[n * d_blocklength * d_D]), + &(out[n * d_blocklength])); } - template class pccc_decoder_combined_blk<float, std::uint8_t>; - template class pccc_decoder_combined_blk<float, std::int16_t>; - template class pccc_decoder_combined_blk<float, std::int32_t>; - template class pccc_decoder_combined_blk<gr_complex, std::uint8_t>; - template class pccc_decoder_combined_blk<gr_complex, std::int16_t>; - template class pccc_decoder_combined_blk<gr_complex, std::int32_t>; + + this->consume_each(d_D * noutput_items); + return noutput_items; +} +template class pccc_decoder_combined_blk<float, std::uint8_t>; +template class pccc_decoder_combined_blk<float, std::int16_t>; +template class pccc_decoder_combined_blk<float, std::int32_t>; +template class pccc_decoder_combined_blk<gr_complex, std::uint8_t>; +template class pccc_decoder_combined_blk<gr_complex, std::int16_t>; +template class pccc_decoder_combined_blk<gr_complex, std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/pccc_decoder_combined_blk_impl.h b/gr-trellis/lib/pccc_decoder_combined_blk_impl.h index 544a965607..3a25fad4b1 100644 --- a/gr-trellis/lib/pccc_decoder_combined_blk_impl.h +++ b/gr-trellis/lib/pccc_decoder_combined_blk_impl.h @@ -26,67 +26,70 @@ #include <gnuradio/trellis/pccc_decoder_combined_blk.h> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T,class OUT_T> - class pccc_decoder_combined_blk_impl : public pccc_decoder_combined_blk<IN_T,OUT_T> - { - private: - fsm d_FSMo; - int d_STo0; - int d_SToK; - fsm d_FSMi; - int d_STi0; - int d_STiK; - interleaver d_INTERLEAVER; - int d_blocklength; - int d_repetitions; - siso_type_t d_SISO_TYPE; - int d_D; - std::vector<IN_T> d_TABLE; - digital::trellis_metric_type_t d_METRIC_TYPE; - float d_scaling; - std::vector<float> d_buffer; +template <class IN_T, class OUT_T> +class pccc_decoder_combined_blk_impl : public pccc_decoder_combined_blk<IN_T, OUT_T> +{ +private: + fsm d_FSMo; + int d_STo0; + int d_SToK; + fsm d_FSMi; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + int d_D; + std::vector<IN_T> d_TABLE; + digital::trellis_metric_type_t d_METRIC_TYPE; + float d_scaling; + std::vector<float> d_buffer; - public: - pccc_decoder_combined_blk_impl(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE, - int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling); - ~pccc_decoder_combined_blk_impl(); +public: + pccc_decoder_combined_blk_impl(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling); + ~pccc_decoder_combined_blk_impl(); - fsm FSM1() const { return d_FSMo; } - fsm FSM2() const { return d_FSMi; } - int ST10() const { return d_STo0; } - int ST1K() const { return d_SToK; } - int ST20() const { return d_STi0; } - int ST2K() const { return d_STiK; } - interleaver INTERLEAVER() const { return d_INTERLEAVER; } - int blocklength() const { return d_blocklength; } - int repetitions() const { return d_repetitions; } - int D() const { return d_D; } - std::vector<IN_T> TABLE() const { return d_TABLE; } - digital::trellis_metric_type_t METRIC_TYPE() const { return d_METRIC_TYPE; } - siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } - float scaling() const { return d_scaling; } - void set_scaling(float scaling); + fsm FSM1() const { return d_FSMo; } + fsm FSM2() const { return d_FSMi; } + int ST10() const { return d_STo0; } + int ST1K() const { return d_SToK; } + int ST20() const { return d_STi0; } + int ST2K() const { return d_STiK; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + int D() const { return d_D; } + std::vector<IN_T> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t METRIC_TYPE() const { return d_METRIC_TYPE; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + float scaling() const { return d_scaling; } + void set_scaling(float scaling); - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* PCCC_DECODER_COMBINED_BLK_IMPL_H */ diff --git a/gr-trellis/lib/pccc_encoder_impl.cc b/gr-trellis/lib/pccc_encoder_impl.cc index 2804f4b39c..f6ee50b65e 100644 --- a/gr-trellis/lib/pccc_encoder_impl.cc +++ b/gr-trellis/lib/pccc_encoder_impl.cc @@ -29,71 +29,76 @@ #include <iostream> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T, class OUT_T> - typename pccc_encoder<IN_T,OUT_T>::sptr - pccc_encoder<IN_T,OUT_T>::make(const fsm &FSM1, int ST1, - const fsm &FSM2, int ST2, - const interleaver &INTERLEAVER, - int blocklength) - { - return gnuradio::get_initial_sptr - (new pccc_encoder_impl<IN_T,OUT_T>(FSM1, ST1, FSM2, ST2, INTERLEAVER, blocklength)); - } +template <class IN_T, class OUT_T> +typename pccc_encoder<IN_T, OUT_T>::sptr +pccc_encoder<IN_T, OUT_T>::make(const fsm& FSM1, + int ST1, + const fsm& FSM2, + int ST2, + const interleaver& INTERLEAVER, + int blocklength) +{ + return gnuradio::get_initial_sptr(new pccc_encoder_impl<IN_T, OUT_T>( + FSM1, ST1, FSM2, ST2, INTERLEAVER, blocklength)); +} - template <class IN_T, class OUT_T> - pccc_encoder_impl<IN_T,OUT_T>::pccc_encoder_impl(const fsm &FSM1, int ST1, - const fsm &FSM2, int ST2, - const interleaver &INTERLEAVER, - int blocklength) +template <class IN_T, class OUT_T> +pccc_encoder_impl<IN_T, OUT_T>::pccc_encoder_impl(const fsm& FSM1, + int ST1, + const fsm& FSM2, + int ST2, + const interleaver& INTERLEAVER, + int blocklength) : sync_block("pccc_encoder<IN_T,OUT_T>", - io_signature::make(1, 1, sizeof(IN_T)), - io_signature::make(1, 1, sizeof(OUT_T))), - d_FSM1(FSM1), d_ST1(ST1), - d_FSM2(FSM2), d_ST2(ST2), + io_signature::make(1, 1, sizeof(IN_T)), + io_signature::make(1, 1, sizeof(OUT_T))), + d_FSM1(FSM1), + d_ST1(ST1), + d_FSM2(FSM2), + d_ST2(ST2), d_INTERLEAVER(INTERLEAVER), d_blocklength(blocklength) - { - assert(d_FSM1.I() == d_FSM2.I()); - this->set_output_multiple(d_blocklength); - d_buffer.resize(d_blocklength); - } +{ + assert(d_FSM1.I() == d_FSM2.I()); + this->set_output_multiple(d_blocklength); + d_buffer.resize(d_blocklength); +} - template <class IN_T, class OUT_T> - pccc_encoder_impl<IN_T,OUT_T>::~pccc_encoder_impl() - { - } +template <class IN_T, class OUT_T> +pccc_encoder_impl<IN_T, OUT_T>::~pccc_encoder_impl() +{ +} - template <class IN_T, class OUT_T> - int - pccc_encoder_impl<IN_T,OUT_T>::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - for(int b = 0 ; b<noutput_items/d_blocklength; b++) { - const IN_T *in = (const IN_T*)input_items[0]+b*d_blocklength; - OUT_T *out = (OUT_T*)output_items[0]+b*d_blocklength; +template <class IN_T, class OUT_T> +int pccc_encoder_impl<IN_T, OUT_T>::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + for (int b = 0; b < noutput_items / d_blocklength; b++) { + const IN_T* in = (const IN_T*)input_items[0] + b * d_blocklength; + OUT_T* out = (OUT_T*)output_items[0] + b * d_blocklength; - int ST1_tmp = d_ST1; - int ST2_tmp = d_ST2; - for(int i = 0; i < d_blocklength; i++) { - int k = d_INTERLEAVER.INTER()[i]; - int o1 = d_FSM1.OS()[ST1_tmp*d_FSM1.I()+in[i]]; - ST1_tmp = (int) d_FSM1.NS()[ST1_tmp*d_FSM1.I()+in[i]]; - int o2 = d_FSM2.OS()[ST2_tmp*d_FSM2.I()+in[k]]; - ST2_tmp = (int) d_FSM2.NS()[ST2_tmp*d_FSM2.I()+in[k]]; - out[i] = (OUT_T) (o1*d_FSM2.O() + o2); - } - } - return noutput_items; + int ST1_tmp = d_ST1; + int ST2_tmp = d_ST2; + for (int i = 0; i < d_blocklength; i++) { + int k = d_INTERLEAVER.INTER()[i]; + int o1 = d_FSM1.OS()[ST1_tmp * d_FSM1.I() + in[i]]; + ST1_tmp = (int)d_FSM1.NS()[ST1_tmp * d_FSM1.I() + in[i]]; + int o2 = d_FSM2.OS()[ST2_tmp * d_FSM2.I() + in[k]]; + ST2_tmp = (int)d_FSM2.NS()[ST2_tmp * d_FSM2.I() + in[k]]; + out[i] = (OUT_T)(o1 * d_FSM2.O() + o2); + } } - template class pccc_encoder<std::uint8_t, std::uint8_t>; - template class pccc_encoder<std::uint8_t, std::int16_t>; - template class pccc_encoder<std::uint8_t, std::int32_t>; - template class pccc_encoder<std::int16_t, std::int16_t>; - template class pccc_encoder<std::int16_t, std::int32_t>; - template class pccc_encoder<std::int32_t, std::int32_t>; + return noutput_items; +} +template class pccc_encoder<std::uint8_t, std::uint8_t>; +template class pccc_encoder<std::uint8_t, std::int16_t>; +template class pccc_encoder<std::uint8_t, std::int32_t>; +template class pccc_encoder<std::int16_t, std::int16_t>; +template class pccc_encoder<std::int16_t, std::int32_t>; +template class pccc_encoder<std::int32_t, std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/pccc_encoder_impl.h b/gr-trellis/lib/pccc_encoder_impl.h index 834e8986c4..67ff36918b 100644 --- a/gr-trellis/lib/pccc_encoder_impl.h +++ b/gr-trellis/lib/pccc_encoder_impl.h @@ -26,40 +26,42 @@ #include <gnuradio/trellis/pccc_encoder.h> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T, class OUT_T> - class pccc_encoder_impl : public pccc_encoder<IN_T,OUT_T> - { - private: - fsm d_FSM1; - int d_ST1; - fsm d_FSM2; - int d_ST2; - interleaver d_INTERLEAVER; - int d_blocklength; - std::vector<int> d_buffer; +template <class IN_T, class OUT_T> +class pccc_encoder_impl : public pccc_encoder<IN_T, OUT_T> +{ +private: + fsm d_FSM1; + int d_ST1; + fsm d_FSM2; + int d_ST2; + interleaver d_INTERLEAVER; + int d_blocklength; + std::vector<int> d_buffer; - public: - pccc_encoder_impl(const fsm &FSM1, int ST1, - const fsm &FSM2, int ST2, - const interleaver &INTERLEAVER, - int blocklength); - ~pccc_encoder_impl(); +public: + pccc_encoder_impl(const fsm& FSM1, + int ST1, + const fsm& FSM2, + int ST2, + const interleaver& INTERLEAVER, + int blocklength); + ~pccc_encoder_impl(); - fsm FSM1() const { return d_FSM1; } - int ST1() const { return d_ST1; } - fsm FSM2() const { return d_FSM2; } - int ST2() const { return d_ST2; } - interleaver INTERLEAVER() const { return d_INTERLEAVER; } - int blocklength() const { return d_blocklength; } + fsm FSM1() const { return d_FSM1; } + int ST1() const { return d_ST1; } + fsm FSM2() const { return d_FSM2; } + int ST2() const { return d_ST2; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* PCCC_ENCODER_IMPL_H */ diff --git a/gr-trellis/lib/permutation_impl.cc b/gr-trellis/lib/permutation_impl.cc index 5a212a01a7..c0e732e1c3 100644 --- a/gr-trellis/lib/permutation_impl.cc +++ b/gr-trellis/lib/permutation_impl.cc @@ -30,82 +30,83 @@ #include <string.h> namespace gr { - namespace trellis { +namespace trellis { - permutation::sptr - permutation::make(int K, const std::vector<int> &TABLE, - int SYMS_PER_BLOCK, size_t BYTES_PER_SYMBOL) - { - return gnuradio::get_initial_sptr - (new permutation_impl(K,TABLE,SYMS_PER_BLOCK,BYTES_PER_SYMBOL)); - } +permutation::sptr permutation::make(int K, + const std::vector<int>& TABLE, + int SYMS_PER_BLOCK, + size_t BYTES_PER_SYMBOL) +{ + return gnuradio::get_initial_sptr( + new permutation_impl(K, TABLE, SYMS_PER_BLOCK, BYTES_PER_SYMBOL)); +} - permutation_impl::permutation_impl(int K, const std::vector<int> &TABLE, - int SYMS_PER_BLOCK, size_t BYTES_PER_SYMBOL) - : sync_block("permutation", - io_signature::make(1, -1, BYTES_PER_SYMBOL), - io_signature::make(1, -1, BYTES_PER_SYMBOL)), - d_K(K), d_TABLE(TABLE), - d_SYMS_PER_BLOCK(SYMS_PER_BLOCK), - d_BYTES_PER_SYMBOL(BYTES_PER_SYMBOL) - { - set_output_multiple(d_K*d_SYMS_PER_BLOCK); - //std::cout << d_K << "\n"; - } +permutation_impl::permutation_impl(int K, + const std::vector<int>& TABLE, + int SYMS_PER_BLOCK, + size_t BYTES_PER_SYMBOL) + : sync_block("permutation", + io_signature::make(1, -1, BYTES_PER_SYMBOL), + io_signature::make(1, -1, BYTES_PER_SYMBOL)), + d_K(K), + d_TABLE(TABLE), + d_SYMS_PER_BLOCK(SYMS_PER_BLOCK), + d_BYTES_PER_SYMBOL(BYTES_PER_SYMBOL) +{ + set_output_multiple(d_K * d_SYMS_PER_BLOCK); + // std::cout << d_K << "\n"; +} - void permutation_impl::set_K(int K) - { - gr::thread::scoped_lock guard(d_setlock); - d_K=K; - set_output_multiple(d_K*d_SYMS_PER_BLOCK); - } +void permutation_impl::set_K(int K) +{ + gr::thread::scoped_lock guard(d_setlock); + d_K = K; + set_output_multiple(d_K * d_SYMS_PER_BLOCK); +} - void permutation_impl::set_TABLE (const std::vector<int> &table) - { - gr::thread::scoped_lock guard(d_setlock); - d_TABLE = table; - } +void permutation_impl::set_TABLE(const std::vector<int>& table) +{ + gr::thread::scoped_lock guard(d_setlock); + d_TABLE = table; +} - void permutation_impl::set_SYMS_PER_BLOCK(int spb) - { - gr::thread::scoped_lock guard(d_setlock); - d_SYMS_PER_BLOCK=spb; - set_output_multiple(d_K*d_SYMS_PER_BLOCK); - } +void permutation_impl::set_SYMS_PER_BLOCK(int spb) +{ + gr::thread::scoped_lock guard(d_setlock); + d_SYMS_PER_BLOCK = spb; + set_output_multiple(d_K * d_SYMS_PER_BLOCK); +} - permutation_impl::~permutation_impl() - { - } +permutation_impl::~permutation_impl() {} - int - permutation_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(d_setlock); - int nstreams = input_items.size(); +int permutation_impl::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(d_setlock); + int nstreams = input_items.size(); - for(int m=0;m<nstreams;m++) { - const char *in = (const char *) input_items[m]; - char *out = (char *) output_items[m]; + for (int m = 0; m < nstreams; m++) { + const char* in = (const char*)input_items[m]; + char* out = (char*)output_items[m]; - // per stream processing - for(int i = 0; i < noutput_items/d_SYMS_PER_BLOCK; i++) { - // Index i refers to blocks. - // Beginning of packet (in blocks) - int i0 = d_K*(i/d_K); - // position of block within packet (in blocks) - int j0 = i%d_K; - // new position of block within packet (in blocks) - int k0 = d_TABLE[j0]; - memcpy(&(out[i*d_SYMS_PER_BLOCK*d_BYTES_PER_SYMBOL]), - &(in[(i0+k0)*d_SYMS_PER_BLOCK*d_BYTES_PER_SYMBOL]), - d_BYTES_PER_SYMBOL*d_SYMS_PER_BLOCK); - } - // end per stream processing - } - return noutput_items; + // per stream processing + for (int i = 0; i < noutput_items / d_SYMS_PER_BLOCK; i++) { + // Index i refers to blocks. + // Beginning of packet (in blocks) + int i0 = d_K * (i / d_K); + // position of block within packet (in blocks) + int j0 = i % d_K; + // new position of block within packet (in blocks) + int k0 = d_TABLE[j0]; + memcpy(&(out[i * d_SYMS_PER_BLOCK * d_BYTES_PER_SYMBOL]), + &(in[(i0 + k0) * d_SYMS_PER_BLOCK * d_BYTES_PER_SYMBOL]), + d_BYTES_PER_SYMBOL * d_SYMS_PER_BLOCK); + } + // end per stream processing } + return noutput_items; +} - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/permutation_impl.h b/gr-trellis/lib/permutation_impl.h index e013e52a20..f8adcca38d 100644 --- a/gr-trellis/lib/permutation_impl.h +++ b/gr-trellis/lib/permutation_impl.h @@ -27,36 +27,38 @@ #include <gnuradio/trellis/permutation.h> namespace gr { - namespace trellis { - - class permutation_impl : public permutation - { - private: - int d_K; - std::vector<int> d_TABLE; - int d_SYMS_PER_BLOCK; - size_t d_BYTES_PER_SYMBOL; - - public: - permutation_impl(int K, const std::vector<int> &TABLE, - int SYMS_PER_BLOCK, size_t NBYTES); - ~permutation_impl(); - - int K() const { return d_K; } - std::vector<int> TABLE() const { return d_TABLE; } - int SYMS_PER_BLOCK() const { return d_SYMS_PER_BLOCK; } - size_t BYTES_PER_SYMBOL() const { return d_BYTES_PER_SYMBOL; } - - void set_K(int K) ; - void set_TABLE (const std::vector<int> &table); - void set_SYMS_PER_BLOCK(int spb) ; - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } /* namespace trellis */ +namespace trellis { + +class permutation_impl : public permutation +{ +private: + int d_K; + std::vector<int> d_TABLE; + int d_SYMS_PER_BLOCK; + size_t d_BYTES_PER_SYMBOL; + +public: + permutation_impl(int K, + const std::vector<int>& TABLE, + int SYMS_PER_BLOCK, + size_t NBYTES); + ~permutation_impl(); + + int K() const { return d_K; } + std::vector<int> TABLE() const { return d_TABLE; } + int SYMS_PER_BLOCK() const { return d_SYMS_PER_BLOCK; } + size_t BYTES_PER_SYMBOL() const { return d_BYTES_PER_SYMBOL; } + + void set_K(int K); + void set_TABLE(const std::vector<int>& table); + void set_SYMS_PER_BLOCK(int spb); + + int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; + +} /* namespace trellis */ } /* namespace gr */ #endif /* INCLUDED_TRELLIS_PERMUTATION_IMPL_H */ diff --git a/gr-trellis/lib/quicksort_index.cc b/gr-trellis/lib/quicksort_index.cc index 2e7c21907a..aeccdb65ef 100644 --- a/gr-trellis/lib/quicksort_index.cc +++ b/gr-trellis/lib/quicksort_index.cc @@ -23,48 +23,46 @@ #include <gnuradio/trellis/quicksort_index.h> namespace gr { - namespace trellis { +namespace trellis { - template <class T> void - SWAP(T & a, T & b) - { - T temp = a; - a = b; - b = temp; - } +template <class T> +void SWAP(T& a, T& b) +{ + T temp = a; + a = b; + b = temp; +} - template <class T> void - quicksort_index (std::vector<T> & p, std::vector<int> & index, - int left, int right) - { - if(left < right) { - int i = left; - int j = right + 1; - T pivot = p[left]; - do { - do - i++; - while ((p[i] < pivot) && (i < right)); - do - j--; - while ((p[j] > pivot) && (j > left)); - if (i < j) { - SWAP <T> (p[i],p[j]); - SWAP <int> (index[i],index[j]); - } - } while (i < j); - SWAP <T> (p[left], p[j]); - SWAP <int> (index[left], index[j]); - quicksort_index <T> (p,index, left, j-1); - quicksort_index <T> (p,index, j+1, right); - } +template <class T> +void quicksort_index(std::vector<T>& p, std::vector<int>& index, int left, int right) +{ + if (left < right) { + int i = left; + int j = right + 1; + T pivot = p[left]; + do { + do + i++; + while ((p[i] < pivot) && (i < right)); + do + j--; + while ((p[j] > pivot) && (j > left)); + if (i < j) { + SWAP<T>(p[i], p[j]); + SWAP<int>(index[i], index[j]); + } + } while (i < j); + SWAP<T>(p[left], p[j]); + SWAP<int>(index[left], index[j]); + quicksort_index<T>(p, index, left, j - 1); + quicksort_index<T>(p, index, j + 1, right); } +} - // instantiate an <int> version of the quicksort_index - //template <int> void SWAP (int & a, int & b); - template void - quicksort_index<int>(std::vector<int> & p, std::vector<int> & index, - int left, int right); +// instantiate an <int> version of the quicksort_index +// template <int> void SWAP (int & a, int & b); +template void +quicksort_index<int>(std::vector<int>& p, std::vector<int>& index, int left, int right); - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/sccc_decoder_blk_impl.cc b/gr-trellis/lib/sccc_decoder_blk_impl.cc index 152079d94c..206dc3f5da 100644 --- a/gr-trellis/lib/sccc_decoder_blk_impl.cc +++ b/gr-trellis/lib/sccc_decoder_blk_impl.cc @@ -31,93 +31,115 @@ #include <gnuradio/trellis/core_algorithms.h> namespace gr { - namespace trellis { +namespace trellis { - template <class T> - typename sccc_decoder_blk<T>::sptr - sccc_decoder_blk<T>::make(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE) - { - return gnuradio::get_initial_sptr - (new sccc_decoder_blk_impl<T>(FSMo, STo0, SToK, FSMi, STi0, STiK, - INTERLEAVER, blocklength, repetitions, - SISO_TYPE)); - } +template <class T> +typename sccc_decoder_blk<T>::sptr +sccc_decoder_blk<T>::make(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) +{ + return gnuradio::get_initial_sptr(new sccc_decoder_blk_impl<T>(FSMo, + STo0, + SToK, + FSMi, + STi0, + STiK, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE)); +} - template <class T> - sccc_decoder_blk_impl<T>::sccc_decoder_blk_impl(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE) +template <class T> +sccc_decoder_blk_impl<T>::sccc_decoder_blk_impl(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) : block("sccc_decoder_blk", - io_signature::make(1, 1, sizeof(float)), - io_signature::make(1, 1, sizeof(T))), - d_FSMo(FSMo), d_STo0(STo0), d_SToK(SToK), - d_FSMi(FSMi), d_STi0(STi0), d_STiK(STiK), + io_signature::make(1, 1, sizeof(float)), + io_signature::make(1, 1, sizeof(T))), + d_FSMo(FSMo), + d_STo0(STo0), + d_SToK(SToK), + d_FSMi(FSMi), + d_STi0(STi0), + d_STiK(STiK), d_INTERLEAVER(INTERLEAVER), d_blocklength(blocklength), d_repetitions(repetitions), d_SISO_TYPE(SISO_TYPE) - { - this->set_relative_rate(1, (uint64_t) d_FSMi.O()); - this->set_output_multiple(d_blocklength); - } - - template <class T> - sccc_decoder_blk_impl<T>::~sccc_decoder_blk_impl() - { - } +{ + this->set_relative_rate(1, (uint64_t)d_FSMi.O()); + this->set_output_multiple(d_blocklength); +} - template <class T> - void - sccc_decoder_blk_impl<T>::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - int input_required = d_FSMi.O() * noutput_items ; - ninput_items_required[0] = input_required; - } +template <class T> +sccc_decoder_blk_impl<T>::~sccc_decoder_blk_impl() +{ +} - //=========================================================== +template <class T> +void sccc_decoder_blk_impl<T>::forecast(int noutput_items, + gr_vector_int& ninput_items_required) +{ + int input_required = d_FSMi.O() * noutput_items; + ninput_items_required[0] = input_required; +} - template <class T> - int - sccc_decoder_blk_impl<T>::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - int nblocks = noutput_items / d_blocklength; - float (*p2min)(float, float) = NULL; +//=========================================================== - if(d_SISO_TYPE == TRELLIS_MIN_SUM) - p2min = &min; - else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) - p2min = &min_star; +template <class T> +int sccc_decoder_blk_impl<T>::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + int nblocks = noutput_items / d_blocklength; + float (*p2min)(float, float) = NULL; - const float *in = (const float*)input_items[0]; - T *out = (T*)output_items[0]; + if (d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if (d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; - for(int n = 0; n < nblocks; n++) { - sccc_decoder(d_FSMo, d_STo0, d_SToK, - d_FSMi, d_STi0, d_STiK, - d_INTERLEAVER, d_blocklength, d_repetitions, - p2min, - &(in[n*d_blocklength*d_FSMi.O()]), - &(out[n*d_blocklength])); - } + const float* in = (const float*)input_items[0]; + T* out = (T*)output_items[0]; - this->consume_each(d_FSMi.O() * noutput_items ); - return noutput_items; + for (int n = 0; n < nblocks; n++) { + sccc_decoder(d_FSMo, + d_STo0, + d_SToK, + d_FSMi, + d_STi0, + d_STiK, + d_INTERLEAVER, + d_blocklength, + d_repetitions, + p2min, + &(in[n * d_blocklength * d_FSMi.O()]), + &(out[n * d_blocklength])); } + this->consume_each(d_FSMi.O() * noutput_items); + return noutput_items; +} + template class sccc_decoder_blk<std::uint8_t>; template class sccc_decoder_blk<std::int16_t>; template class sccc_decoder_blk<std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/sccc_decoder_blk_impl.h b/gr-trellis/lib/sccc_decoder_blk_impl.h index 0c3e2d9310..683f65190f 100644 --- a/gr-trellis/lib/sccc_decoder_blk_impl.h +++ b/gr-trellis/lib/sccc_decoder_blk_impl.h @@ -27,54 +27,57 @@ #include <gnuradio/trellis/sccc_decoder_blk.h> namespace gr { - namespace trellis { +namespace trellis { -template<class T> - class sccc_decoder_blk_impl : public sccc_decoder_blk<T> - { - private: - fsm d_FSMo; - int d_STo0; - int d_SToK; - fsm d_FSMi; - int d_STi0; - int d_STiK; - interleaver d_INTERLEAVER; - int d_blocklength; - int d_repetitions; - siso_type_t d_SISO_TYPE; - std::vector<float> d_buffer; +template <class T> +class sccc_decoder_blk_impl : public sccc_decoder_blk<T> +{ +private: + fsm d_FSMo; + int d_STo0; + int d_SToK; + fsm d_FSMi; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + std::vector<float> d_buffer; - public: - sccc_decoder_blk_impl(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE); - ~sccc_decoder_blk_impl(); +public: + sccc_decoder_blk_impl(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE); + ~sccc_decoder_blk_impl(); - fsm FSMo() const { return d_FSMo; } - fsm FSMi() const { return d_FSMi; } - int STo0() const { return d_STo0; } - int SToK() const { return d_SToK; } - int STi0() const { return d_STi0; } - int STiK() const { return d_STiK; } - interleaver INTERLEAVER() const { return d_INTERLEAVER; } - int blocklength() const { return d_blocklength; } - int repetitions() const { return d_repetitions; } - siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + fsm FSMo() const { return d_FSMo; } + fsm FSMi() const { return d_FSMi; } + int STo0() const { return d_STo0; } + int SToK() const { return d_SToK; } + int STi0() const { return d_STi0; } + int STiK() const { return d_STiK; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* SCCC_DECODER_BLK_IMPL_H */ diff --git a/gr-trellis/lib/sccc_decoder_combined_blk_impl.cc b/gr-trellis/lib/sccc_decoder_combined_blk_impl.cc index 9ef1321996..6f25189246 100644 --- a/gr-trellis/lib/sccc_decoder_combined_blk_impl.cc +++ b/gr-trellis/lib/sccc_decoder_combined_blk_impl.cc @@ -30,43 +30,67 @@ #include <gnuradio/trellis/core_algorithms.h> namespace gr { - namespace trellis { - - template <class IN_T, class OUT_T> - typename sccc_decoder_combined_blk<IN_T,OUT_T>::sptr - sccc_decoder_combined_blk<IN_T,OUT_T>::make(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE, - int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling) - { - return gnuradio::get_initial_sptr - (new sccc_decoder_combined_blk_impl<IN_T,OUT_T>(FSMo, STo0, SToK, FSMi, STi0, STiK, - INTERLEAVER, blocklength, repetitions, - SISO_TYPE, D, TABLE,METRIC_TYPE, scaling)); - } - - template <class IN_T, class OUT_T> - sccc_decoder_combined_blk_impl<IN_T,OUT_T>::sccc_decoder_combined_blk_impl(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE, - int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling) +namespace trellis { + +template <class IN_T, class OUT_T> +typename sccc_decoder_combined_blk<IN_T, OUT_T>::sptr +sccc_decoder_combined_blk<IN_T, OUT_T>::make(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) +{ + return gnuradio::get_initial_sptr( + new sccc_decoder_combined_blk_impl<IN_T, OUT_T>(FSMo, + STo0, + SToK, + FSMi, + STi0, + STiK, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE, + D, + TABLE, + METRIC_TYPE, + scaling)); +} + +template <class IN_T, class OUT_T> +sccc_decoder_combined_blk_impl<IN_T, OUT_T>::sccc_decoder_combined_blk_impl( + const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) : block("sccc_decoder_combined_blk<IN_T,OUT_T>", - io_signature::make(1, 1, sizeof(IN_T)), - io_signature::make(1, 1, sizeof(OUT_T))), - d_FSMo(FSMo), d_STo0(STo0), d_SToK(SToK), - d_FSMi(FSMi), d_STi0(STi0), d_STiK(STiK), + io_signature::make(1, 1, sizeof(IN_T)), + io_signature::make(1, 1, sizeof(OUT_T))), + d_FSMo(FSMo), + d_STo0(STo0), + d_SToK(SToK), + d_FSMi(FSMi), + d_STi0(STi0), + d_STiK(STiK), d_INTERLEAVER(INTERLEAVER), d_blocklength(blocklength), d_repetitions(repetitions), @@ -75,77 +99,82 @@ namespace gr { d_TABLE(TABLE), d_METRIC_TYPE(METRIC_TYPE), d_scaling(scaling) - { - this->set_relative_rate(1, (uint64_t) d_D); - this->set_output_multiple(d_blocklength); +{ + this->set_relative_rate(1, (uint64_t)d_D); + this->set_output_multiple(d_blocklength); +} + +template <class IN_T, class OUT_T> +sccc_decoder_combined_blk_impl<IN_T, OUT_T>::~sccc_decoder_combined_blk_impl() +{ +} + +template <class IN_T, class OUT_T> +void sccc_decoder_combined_blk_impl<IN_T, OUT_T>::set_scaling(float scaling) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_scaling = scaling; +} + +template <class IN_T, class OUT_T> +void sccc_decoder_combined_blk_impl<IN_T, OUT_T>::forecast( + int noutput_items, gr_vector_int& ninput_items_required) +{ + int input_required = d_D * noutput_items; + ninput_items_required[0] = input_required; +} + +//=========================================================== + +template <class IN_T, class OUT_T> +int sccc_decoder_combined_blk_impl<IN_T, OUT_T>::general_work( + int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(this->d_setlock); + int nblocks = noutput_items / d_blocklength; + float (*p2min)(float, float) = NULL; + + if (d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if (d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + const IN_T* in = (const IN_T*)input_items[0]; + OUT_T* out = (OUT_T*)output_items[0]; + + for (int n = 0; n < nblocks; n++) { + sccc_decoder_combined(d_FSMo, + d_STo0, + d_SToK, + d_FSMi, + d_STi0, + d_STiK, + d_INTERLEAVER, + d_blocklength, + d_repetitions, + p2min, + d_D, + d_TABLE, + d_METRIC_TYPE, + d_scaling, + &(in[n * d_blocklength * d_D]), + &(out[n * d_blocklength])); } - template <class IN_T, class OUT_T> - sccc_decoder_combined_blk_impl<IN_T,OUT_T>::~sccc_decoder_combined_blk_impl() - { - } - - template <class IN_T, class OUT_T> - void - sccc_decoder_combined_blk_impl<IN_T,OUT_T>::set_scaling(float scaling) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_scaling = scaling; - } - - template <class IN_T, class OUT_T> - void - sccc_decoder_combined_blk_impl<IN_T,OUT_T>::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - int input_required = d_D * noutput_items ; - ninput_items_required[0] = input_required; - } - - //=========================================================== - - template <class IN_T, class OUT_T> - int - sccc_decoder_combined_blk_impl<IN_T,OUT_T>::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(this->d_setlock); - int nblocks = noutput_items / d_blocklength; - float (*p2min)(float, float) = NULL; - - if(d_SISO_TYPE == TRELLIS_MIN_SUM) - p2min = &min; - else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) - p2min = &min_star; - - const IN_T *in = (const IN_T*)input_items[0]; - OUT_T *out = (OUT_T*)output_items[0]; - - for(int n = 0; n < nblocks; n++) { - sccc_decoder_combined(d_FSMo, d_STo0, d_SToK, - d_FSMi, d_STi0, d_STiK, - d_INTERLEAVER, d_blocklength, d_repetitions, - p2min, - d_D,d_TABLE, - d_METRIC_TYPE, - d_scaling, - &(in[n*d_blocklength*d_D]), - &(out[n*d_blocklength])); - } - - this->consume_each(d_D * noutput_items); - return noutput_items; - } + this->consume_each(d_D * noutput_items); + return noutput_items; +} - template class sccc_decoder_combined_blk<float, std::uint8_t>; - template class sccc_decoder_combined_blk<float, std::int16_t>; - template class sccc_decoder_combined_blk<float, std::int32_t>; - template class sccc_decoder_combined_blk<gr_complex, std::uint8_t>; - template class sccc_decoder_combined_blk<gr_complex, std::int16_t>; - template class sccc_decoder_combined_blk<gr_complex, std::int32_t>; +template class sccc_decoder_combined_blk<float, std::uint8_t>; +template class sccc_decoder_combined_blk<float, std::int16_t>; +template class sccc_decoder_combined_blk<float, std::int32_t>; +template class sccc_decoder_combined_blk<gr_complex, std::uint8_t>; +template class sccc_decoder_combined_blk<gr_complex, std::int16_t>; +template class sccc_decoder_combined_blk<gr_complex, std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/sccc_decoder_combined_blk_impl.h b/gr-trellis/lib/sccc_decoder_combined_blk_impl.h index 8236c79a49..91a5fbd3da 100644 --- a/gr-trellis/lib/sccc_decoder_combined_blk_impl.h +++ b/gr-trellis/lib/sccc_decoder_combined_blk_impl.h @@ -26,67 +26,70 @@ #include <gnuradio/trellis/sccc_decoder_combined_blk.h> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T, class OUT_T> - class sccc_decoder_combined_blk_impl : public sccc_decoder_combined_blk<IN_T,OUT_T> - { - private: - fsm d_FSMo; - int d_STo0; - int d_SToK; - fsm d_FSMi; - int d_STi0; - int d_STiK; - interleaver d_INTERLEAVER; - int d_blocklength; - int d_repetitions; - siso_type_t d_SISO_TYPE; - int d_D; - std::vector<IN_T> d_TABLE; - digital::trellis_metric_type_t d_METRIC_TYPE; - float d_scaling; - std::vector<float> d_buffer; +template <class IN_T, class OUT_T> +class sccc_decoder_combined_blk_impl : public sccc_decoder_combined_blk<IN_T, OUT_T> +{ +private: + fsm d_FSMo; + int d_STo0; + int d_SToK; + fsm d_FSMi; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + int d_D; + std::vector<IN_T> d_TABLE; + digital::trellis_metric_type_t d_METRIC_TYPE; + float d_scaling; + std::vector<float> d_buffer; - public: - sccc_decoder_combined_blk_impl(const fsm &FSMo, int STo0, int SToK, - const fsm &FSMi, int STi0, int STiK, - const interleaver &INTERLEAVER, - int blocklength, - int repetitions, - siso_type_t SISO_TYPE, - int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t METRIC_TYPE, - float scaling); - ~sccc_decoder_combined_blk_impl(); +public: + sccc_decoder_combined_blk_impl(const fsm& FSMo, + int STo0, + int SToK, + const fsm& FSMi, + int STi0, + int STiK, + const interleaver& INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling); + ~sccc_decoder_combined_blk_impl(); - fsm FSMo() const { return d_FSMo; } - fsm FSMi() const { return d_FSMi; } - int STo0() const { return d_STo0; } - int SToK() const { return d_SToK; } - int STi0() const { return d_STi0; } - int STiK() const { return d_STiK; } - interleaver INTERLEAVER() const { return d_INTERLEAVER; } - int blocklength() const { return d_blocklength; } - int repetitions() const { return d_repetitions; } - int D() const { return d_D; } - std::vector<IN_T> TABLE() const { return d_TABLE; } - digital::trellis_metric_type_t METRIC_TYPE() const { return d_METRIC_TYPE; } - siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } - float scaling() const { return d_scaling; } - void set_scaling(float scaling); + fsm FSMo() const { return d_FSMo; } + fsm FSMi() const { return d_FSMi; } + int STo0() const { return d_STo0; } + int SToK() const { return d_SToK; } + int STi0() const { return d_STi0; } + int STiK() const { return d_STiK; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + int D() const { return d_D; } + std::vector<IN_T> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t METRIC_TYPE() const { return d_METRIC_TYPE; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + float scaling() const { return d_scaling; } + void set_scaling(float scaling); - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* SCCC_DECODER_COMBINED_BLK_IMPL_H */ diff --git a/gr-trellis/lib/sccc_encoder_impl.cc b/gr-trellis/lib/sccc_encoder_impl.cc index 9c3e1da2d5..8bff8dbe43 100644 --- a/gr-trellis/lib/sccc_encoder_impl.cc +++ b/gr-trellis/lib/sccc_encoder_impl.cc @@ -29,73 +29,78 @@ #include <iostream> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T, class OUT_T> - typename sccc_encoder<IN_T,OUT_T>::sptr - sccc_encoder<IN_T,OUT_T>::make(const fsm &FSMo, int STo, - const fsm &FSMi, int STi, - const interleaver &INTERLEAVER, - int blocklength) - { - return gnuradio::get_initial_sptr - (new sccc_encoder_impl<IN_T,OUT_T>(FSMo, STo, FSMi, STi, INTERLEAVER, blocklength)); - } +template <class IN_T, class OUT_T> +typename sccc_encoder<IN_T, OUT_T>::sptr +sccc_encoder<IN_T, OUT_T>::make(const fsm& FSMo, + int STo, + const fsm& FSMi, + int STi, + const interleaver& INTERLEAVER, + int blocklength) +{ + return gnuradio::get_initial_sptr(new sccc_encoder_impl<IN_T, OUT_T>( + FSMo, STo, FSMi, STi, INTERLEAVER, blocklength)); +} - template <class IN_T, class OUT_T> - sccc_encoder_impl<IN_T,OUT_T>::sccc_encoder_impl(const fsm &FSMo, int STo, - const fsm &FSMi, int STi, - const interleaver &INTERLEAVER, - int blocklength) +template <class IN_T, class OUT_T> +sccc_encoder_impl<IN_T, OUT_T>::sccc_encoder_impl(const fsm& FSMo, + int STo, + const fsm& FSMi, + int STi, + const interleaver& INTERLEAVER, + int blocklength) : sync_block("sccc_encoder<IN_T,OUT_T>", - io_signature::make(1, 1, sizeof(IN_T)), - io_signature::make(1, 1, sizeof(OUT_T))), - d_FSMo(FSMo), d_STo(STo), - d_FSMi(FSMi), d_STi(STi), + io_signature::make(1, 1, sizeof(IN_T)), + io_signature::make(1, 1, sizeof(OUT_T))), + d_FSMo(FSMo), + d_STo(STo), + d_FSMi(FSMi), + d_STi(STi), d_INTERLEAVER(INTERLEAVER), d_blocklength(blocklength) - { - this->set_output_multiple(d_blocklength); - d_buffer.resize(d_blocklength); - } +{ + this->set_output_multiple(d_blocklength); + d_buffer.resize(d_blocklength); +} - template <class IN_T, class OUT_T> - sccc_encoder_impl<IN_T,OUT_T>::~sccc_encoder_impl() - { - } +template <class IN_T, class OUT_T> +sccc_encoder_impl<IN_T, OUT_T>::~sccc_encoder_impl() +{ +} - template <class IN_T, class OUT_T> - int - sccc_encoder_impl<IN_T,OUT_T>::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - for(int b = 0; b < noutput_items/d_blocklength; b++) { - const IN_T *in = (const IN_T*)input_items[0]+b*d_blocklength; - OUT_T *out = (OUT_T*)output_items[0]+b*d_blocklength; +template <class IN_T, class OUT_T> +int sccc_encoder_impl<IN_T, OUT_T>::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + for (int b = 0; b < noutput_items / d_blocklength; b++) { + const IN_T* in = (const IN_T*)input_items[0] + b * d_blocklength; + OUT_T* out = (OUT_T*)output_items[0] + b * d_blocklength; - int STo_tmp = d_STo; - for(int i = 0; i < d_blocklength; i++) { - d_buffer[i] = d_FSMo.OS()[STo_tmp*d_FSMo.I()+in[i]]; - STo_tmp = (int) d_FSMo.NS()[STo_tmp*d_FSMo.I()+in[i]]; - } + int STo_tmp = d_STo; + for (int i = 0; i < d_blocklength; i++) { + d_buffer[i] = d_FSMo.OS()[STo_tmp * d_FSMo.I() + in[i]]; + STo_tmp = (int)d_FSMo.NS()[STo_tmp * d_FSMo.I() + in[i]]; + } - int STi_tmp = d_STi; - for(int i = 0; i < d_blocklength; i++) { - int k = d_INTERLEAVER.INTER()[i]; - out[i] = (OUT_T) d_FSMi.OS()[STi_tmp*d_FSMi.I()+d_buffer[k]]; - STi_tmp = (int) d_FSMi.NS()[STi_tmp*d_FSMi.I()+d_buffer[k]]; - } - } - return noutput_items; + int STi_tmp = d_STi; + for (int i = 0; i < d_blocklength; i++) { + int k = d_INTERLEAVER.INTER()[i]; + out[i] = (OUT_T)d_FSMi.OS()[STi_tmp * d_FSMi.I() + d_buffer[k]]; + STi_tmp = (int)d_FSMi.NS()[STi_tmp * d_FSMi.I() + d_buffer[k]]; + } } - template class sccc_encoder<std::uint8_t, std::uint8_t>; - template class sccc_encoder<std::uint8_t, std::int16_t>; - template class sccc_encoder<std::uint8_t, std::int32_t>; - template class sccc_encoder<std::int16_t, std::int16_t>; - template class sccc_encoder<std::int16_t, std::int32_t>; - template class sccc_encoder<std::int32_t, std::int32_t>; + return noutput_items; +} +template class sccc_encoder<std::uint8_t, std::uint8_t>; +template class sccc_encoder<std::uint8_t, std::int16_t>; +template class sccc_encoder<std::uint8_t, std::int32_t>; +template class sccc_encoder<std::int16_t, std::int16_t>; +template class sccc_encoder<std::int16_t, std::int32_t>; +template class sccc_encoder<std::int32_t, std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/sccc_encoder_impl.h b/gr-trellis/lib/sccc_encoder_impl.h index 40968906dc..f298b61c23 100644 --- a/gr-trellis/lib/sccc_encoder_impl.h +++ b/gr-trellis/lib/sccc_encoder_impl.h @@ -26,40 +26,42 @@ #include <gnuradio/trellis/sccc_encoder.h> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T, class OUT_T> - class sccc_encoder_impl : public sccc_encoder<IN_T,OUT_T> - { - private: - fsm d_FSMo; - int d_STo; - fsm d_FSMi; - int d_STi; - interleaver d_INTERLEAVER; - int d_blocklength; - std::vector<int> d_buffer; +template <class IN_T, class OUT_T> +class sccc_encoder_impl : public sccc_encoder<IN_T, OUT_T> +{ +private: + fsm d_FSMo; + int d_STo; + fsm d_FSMi; + int d_STi; + interleaver d_INTERLEAVER; + int d_blocklength; + std::vector<int> d_buffer; - public: - sccc_encoder_impl(const fsm &FSMo, int STo, - const fsm &FSMi, int STi, - const interleaver &INTERLEAVER, - int blocklength); - ~sccc_encoder_impl(); +public: + sccc_encoder_impl(const fsm& FSMo, + int STo, + const fsm& FSMi, + int STi, + const interleaver& INTERLEAVER, + int blocklength); + ~sccc_encoder_impl(); - fsm FSMo() const { return d_FSMo; } - int STo() const { return d_STo; } - fsm FSMi() const { return d_FSMi; } - int STi() const { return d_STi; } - interleaver INTERLEAVER() const { return d_INTERLEAVER; } - int blocklength() const { return d_blocklength; } + fsm FSMo() const { return d_FSMo; } + int STo() const { return d_STo; } + fsm FSMi() const { return d_FSMi; } + int STi() const { return d_STi; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* SCCC_ENCODER_IMPL_H */ diff --git a/gr-trellis/lib/siso_combined_f_impl.cc b/gr-trellis/lib/siso_combined_f_impl.cc index ff413b8699..d6decbbafd 100644 --- a/gr-trellis/lib/siso_combined_f_impl.cc +++ b/gr-trellis/lib/siso_combined_f_impl.cc @@ -31,219 +31,239 @@ #include <iostream> namespace gr { - namespace trellis { - - siso_combined_f::sptr - siso_combined_f::make(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t SISO_TYPE, - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE) - { - return gnuradio::get_initial_sptr - (new siso_combined_f_impl(FSM, K, S0, SK, POSTI, POSTO, - SISO_TYPE, D, TABLE, TYPE)); - } +namespace trellis { + +siso_combined_f::sptr siso_combined_f::make(const fsm& FSM, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + siso_type_t SISO_TYPE, + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t TYPE) +{ + return gnuradio::get_initial_sptr(new siso_combined_f_impl( + FSM, K, S0, SK, POSTI, POSTO, SISO_TYPE, D, TABLE, TYPE)); +} - void siso_combined_f_impl::recalculate() - { - int multiple; - if(d_POSTI && d_POSTO) - multiple = d_FSM.I()+d_FSM.O(); - else if(d_POSTI) +void siso_combined_f_impl::recalculate() +{ + int multiple; + if (d_POSTI && d_POSTO) + multiple = d_FSM.I() + d_FSM.O(); + else if (d_POSTI) multiple = d_FSM.I(); - else if(d_POSTO) + else if (d_POSTO) multiple = d_FSM.O(); - else - throw std::runtime_error ("Not both POSTI and POSTO can be false."); - - set_output_multiple(d_K*multiple); - - //what is the meaning of relative rate for a block with 2 inputs? - //set_relative_rate ((uint64_t) multiple, (uint64_t) d_FSM.I() ); - // it turns out that the above gives problems in the scheduler, so - // let's try (assumption O>I) - //set_relative_rate ((uint64_t) multiple, (uint64_t) d_FSM.O() ); - // I am tempted to automate like this - if(d_FSM.I() <= d_D) + else + throw std::runtime_error("Not both POSTI and POSTO can be false."); + + set_output_multiple(d_K * multiple); + + // what is the meaning of relative rate for a block with 2 inputs? + // set_relative_rate ((uint64_t) multiple, (uint64_t) d_FSM.I() ); + // it turns out that the above gives problems in the scheduler, so + // let's try (assumption O>I) + // set_relative_rate ((uint64_t) multiple, (uint64_t) d_FSM.O() ); + // I am tempted to automate like this + if (d_FSM.I() <= d_D) set_relative_rate((uint64_t)multiple, (uint64_t)d_D); - else + else set_relative_rate((uint64_t)multiple, (uint64_t)d_FSM.I()); - } - - - siso_combined_f_impl::siso_combined_f_impl(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t SISO_TYPE, - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE) - : block("siso_combined_f", - io_signature::make(1, -1, sizeof(float)), - io_signature::make(1, -1, sizeof(float))), - d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK), - d_POSTI(POSTI), d_POSTO(POSTO), - d_SISO_TYPE(SISO_TYPE), - d_D(D), d_TABLE(TABLE), d_TYPE(TYPE)//, - //d_alpha(FSM.S()*(K+1)), - //d_beta(FSM.S()*(K+1)) - { - recalculate(); - } +} - void siso_combined_f_impl::set_FSM(const fsm &FSM) - { - gr::thread::scoped_lock guard(d_setlock); - d_FSM=FSM; - recalculate(); - } - void siso_combined_f_impl::set_K(int K) - { - gr::thread::scoped_lock guard(d_setlock); - d_K=K; - recalculate(); - } +siso_combined_f_impl::siso_combined_f_impl(const fsm& FSM, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + siso_type_t SISO_TYPE, + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t TYPE) + : block("siso_combined_f", + io_signature::make(1, -1, sizeof(float)), + io_signature::make(1, -1, sizeof(float))), + d_FSM(FSM), + d_K(K), + d_S0(S0), + d_SK(SK), + d_POSTI(POSTI), + d_POSTO(POSTO), + d_SISO_TYPE(SISO_TYPE), + d_D(D), + d_TABLE(TABLE), + d_TYPE(TYPE) //, + // d_alpha(FSM.S()*(K+1)), +// d_beta(FSM.S()*(K+1)) +{ + recalculate(); +} - void siso_combined_f_impl::set_POSTI(bool POSTI) - { - gr::thread::scoped_lock guard(d_setlock); - d_POSTI = POSTI; - recalculate(); - } +void siso_combined_f_impl::set_FSM(const fsm& FSM) +{ + gr::thread::scoped_lock guard(d_setlock); + d_FSM = FSM; + recalculate(); +} - void siso_combined_f_impl::set_POSTO(bool POSTO) - { - gr::thread::scoped_lock guard(d_setlock); - d_POSTO = POSTO; - recalculate(); - } +void siso_combined_f_impl::set_K(int K) +{ + gr::thread::scoped_lock guard(d_setlock); + d_K = K; + recalculate(); +} - void siso_combined_f_impl::set_D(int D) - { - gr::thread::scoped_lock guard(d_setlock); - d_D=D; - recalculate(); - } +void siso_combined_f_impl::set_POSTI(bool POSTI) +{ + gr::thread::scoped_lock guard(d_setlock); + d_POSTI = POSTI; + recalculate(); +} - void siso_combined_f_impl::set_S0(int S0) - { - gr::thread::scoped_lock guard(d_setlock); - d_S0 = S0; - } +void siso_combined_f_impl::set_POSTO(bool POSTO) +{ + gr::thread::scoped_lock guard(d_setlock); + d_POSTO = POSTO; + recalculate(); +} - void siso_combined_f_impl::set_SK(int SK) - { - gr::thread::scoped_lock guard(d_setlock); - d_SK = SK; - } +void siso_combined_f_impl::set_D(int D) +{ + gr::thread::scoped_lock guard(d_setlock); + d_D = D; + recalculate(); +} - void siso_combined_f_impl::set_SISO_TYPE(trellis::siso_type_t type) - { - gr::thread::scoped_lock guard(d_setlock); - d_SISO_TYPE = type; - } +void siso_combined_f_impl::set_S0(int S0) +{ + gr::thread::scoped_lock guard(d_setlock); + d_S0 = S0; +} - void siso_combined_f_impl::set_TABLE(const std::vector<float> &table) - { - gr::thread::scoped_lock guard(d_setlock); - d_TABLE = table; - } +void siso_combined_f_impl::set_SK(int SK) +{ + gr::thread::scoped_lock guard(d_setlock); + d_SK = SK; +} - void siso_combined_f_impl::set_TYPE(digital::trellis_metric_type_t type) - { - gr::thread::scoped_lock guard(d_setlock); - d_TYPE = type; - } +void siso_combined_f_impl::set_SISO_TYPE(trellis::siso_type_t type) +{ + gr::thread::scoped_lock guard(d_setlock); + d_SISO_TYPE = type; +} + +void siso_combined_f_impl::set_TABLE(const std::vector<float>& table) +{ + gr::thread::scoped_lock guard(d_setlock); + d_TABLE = table; +} + +void siso_combined_f_impl::set_TYPE(digital::trellis_metric_type_t type) +{ + gr::thread::scoped_lock guard(d_setlock); + d_TYPE = type; +} + +siso_combined_f_impl::~siso_combined_f_impl() {} + +void siso_combined_f_impl::forecast(int noutput_items, + gr_vector_int& ninput_items_required) +{ + int multiple; + if (d_POSTI && d_POSTO) + multiple = d_FSM.I() + d_FSM.O(); + else if (d_POSTI) + multiple = d_FSM.I(); + else if (d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error("Not both POSTI and POSTO can be false."); + + // printf("forecast: Multiple = %d\n",multiple); + int input_required1 = d_FSM.I() * (noutput_items / multiple); + int input_required2 = d_D * (noutput_items / multiple); + // printf("forecast: Output requirements: %d\n",noutput_items); + // printf("forecast: Input requirements: %d %d\n",input_required1,input_required2); + unsigned ninputs = ninput_items_required.size(); - siso_combined_f_impl::~siso_combined_f_impl() - { + for (unsigned int i = 0; i < ninputs / 2; i++) { + ninput_items_required[2 * i] = input_required1; + ninput_items_required[2 * i + 1] = input_required2; } +} - void - siso_combined_f_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - int multiple; - if(d_POSTI && d_POSTO) - multiple = d_FSM.I()+d_FSM.O(); - else if(d_POSTI) - multiple = d_FSM.I(); - else if(d_POSTO) - multiple = d_FSM.O(); - else - throw std::runtime_error ("Not both POSTI and POSTO can be false."); - - //printf("forecast: Multiple = %d\n",multiple); - int input_required1 = d_FSM.I() * (noutput_items/multiple) ; - int input_required2 = d_D * (noutput_items/multiple) ; - //printf("forecast: Output requirements: %d\n",noutput_items); - //printf("forecast: Input requirements: %d %d\n",input_required1,input_required2); - unsigned ninputs = ninput_items_required.size(); - - for(unsigned int i = 0; i < ninputs/2; i++) { - ninput_items_required[2*i] = input_required1; - ninput_items_required[2*i+1] = input_required2; - } +int siso_combined_f_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(d_setlock); + int nstreams = output_items.size(); + // printf("general_work:Streams: %d\n",nstreams); + + int multiple; + if (d_POSTI && d_POSTO) + multiple = d_FSM.I() + d_FSM.O(); + else if (d_POSTI) + multiple = d_FSM.I(); + else if (d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error( + "siso_combined_f_impl:: Not both POSTI and POSTO can be false."); + + int nblocks = noutput_items / (d_K * multiple); + // printf("general_work:Blocks: %d\n",nblocks); + // for(int i=0;i<ninput_items.size();i++) + // printf("general_work:Input items available: %d\n",ninput_items[i]); + + float (*p2min)(float, float) = NULL; + if (d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if (d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + for (int m = 0; m < nstreams; m++) { + const float* in1 = (const float*)input_items[2 * m]; + const float* in2 = (const float*)input_items[2 * m + 1]; + float* out = (float*)output_items[m]; + for (int n = 0; n < nblocks; n++) { + siso_algorithm_combined(d_FSM.I(), + d_FSM.S(), + d_FSM.O(), + d_FSM.NS(), + d_FSM.OS(), + d_FSM.PS(), + d_FSM.PI(), + d_K, + d_S0, + d_SK, + d_POSTI, + d_POSTO, + p2min, + d_D, + d_TABLE, + d_TYPE, + &(in1[n * d_K * d_FSM.I()]), + &(in2[n * d_K * d_D]), + &(out[n * d_K * multiple]) //, + // d_alpha,d_beta + ); + } } - int - siso_combined_f_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(d_setlock); - int nstreams = output_items.size(); - //printf("general_work:Streams: %d\n",nstreams); - - int multiple; - if(d_POSTI && d_POSTO) - multiple = d_FSM.I()+d_FSM.O(); - else if(d_POSTI) - multiple = d_FSM.I(); - else if(d_POSTO) - multiple = d_FSM.O(); - else - throw std::runtime_error("siso_combined_f_impl:: Not both POSTI and POSTO can be false."); - - int nblocks = noutput_items / (d_K*multiple); - //printf("general_work:Blocks: %d\n",nblocks); - //for(int i=0;i<ninput_items.size();i++) - //printf("general_work:Input items available: %d\n",ninput_items[i]); - - float (*p2min)(float, float) = NULL; - if(d_SISO_TYPE == TRELLIS_MIN_SUM) - p2min = &min; - else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) - p2min = &min_star; - - for(int m=0;m<nstreams;m++) { - const float *in1 = (const float*)input_items[2*m]; - const float *in2 = (const float*)input_items[2*m+1]; - float *out = (float *) output_items[m]; - for(int n=0;n<nblocks;n++) { - siso_algorithm_combined(d_FSM.I(),d_FSM.S(),d_FSM.O(), - d_FSM.NS(),d_FSM.OS(),d_FSM.PS(),d_FSM.PI(), - d_K,d_S0,d_SK, - d_POSTI,d_POSTO, - p2min, - d_D,d_TABLE,d_TYPE, - &(in1[n*d_K*d_FSM.I()]),&(in2[n*d_K*d_D]), - &(out[n*d_K*multiple])//, - //d_alpha,d_beta - ); - } - } - - for(unsigned int i = 0; i < input_items.size()/2; i++) { - consume(2*i,d_FSM.I() * noutput_items / multiple ); - consume(2*i+1,d_D * noutput_items / multiple ); - } - - return noutput_items; + for (unsigned int i = 0; i < input_items.size() / 2; i++) { + consume(2 * i, d_FSM.I() * noutput_items / multiple); + consume(2 * i + 1, d_D * noutput_items / multiple); } - } /* namespace trellis */ + return noutput_items; +} + +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/siso_combined_f_impl.h b/gr-trellis/lib/siso_combined_f_impl.h index 93e9aa87d2..98b4420765 100644 --- a/gr-trellis/lib/siso_combined_f_impl.h +++ b/gr-trellis/lib/siso_combined_f_impl.h @@ -26,66 +26,69 @@ #include <gnuradio/trellis/siso_combined_f.h> namespace gr { - namespace trellis { +namespace trellis { - class siso_combined_f_impl : public siso_combined_f - { - private: - fsm d_FSM; - int d_K; - int d_S0; - int d_SK; - bool d_POSTI; - bool d_POSTO; - siso_type_t d_SISO_TYPE; - int d_D; - std::vector<float> d_TABLE; - digital::trellis_metric_type_t d_TYPE; - void recalculate(); - //std::vector<float> d_alpha; - //std::vector<float> d_beta; +class siso_combined_f_impl : public siso_combined_f +{ +private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + bool d_POSTI; + bool d_POSTO; + siso_type_t d_SISO_TYPE; + int d_D; + std::vector<float> d_TABLE; + digital::trellis_metric_type_t d_TYPE; + void recalculate(); + // std::vector<float> d_alpha; + // std::vector<float> d_beta; - public: - siso_combined_f_impl(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t d_SISO_TYPE, - int D, const std::vector<float> &TABLE, - digital::trellis_metric_type_t TYPE); - ~siso_combined_f_impl(); +public: + siso_combined_f_impl(const fsm& FSM, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + siso_type_t d_SISO_TYPE, + int D, + const std::vector<float>& TABLE, + digital::trellis_metric_type_t TYPE); + ~siso_combined_f_impl(); - fsm FSM() const { return d_FSM; } - int K() const { return d_K; } - int S0() const { return d_S0; } - int SK() const { return d_SK; } - bool POSTI() const { return d_POSTI; } - bool POSTO() const { return d_POSTO; } - siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } - int D() const { return d_D; } - std::vector<float> TABLE() const { return d_TABLE; } - digital::trellis_metric_type_t TYPE() const { return d_TYPE; } + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + bool POSTI() const { return d_POSTI; } + bool POSTO() const { return d_POSTO; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + int D() const { return d_D; } + std::vector<float> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t TYPE() const { return d_TYPE; } - void set_FSM(const fsm &FSM); - void set_K(int K); - void set_S0(int S0); - void set_SK(int SK); - void set_POSTI(bool POSTI); - void set_POSTO(bool POSTO); - void set_SISO_TYPE(trellis::siso_type_t type); - void set_D(int D); - void set_TABLE(const std::vector<float> &table); - void set_TYPE(digital::trellis_metric_type_t type); + void set_FSM(const fsm& FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); + void set_POSTI(bool POSTI); + void set_POSTO(bool POSTO); + void set_SISO_TYPE(trellis::siso_type_t type); + void set_D(int D); + void set_TABLE(const std::vector<float>& table); + void set_TYPE(digital::trellis_metric_type_t type); - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* INCLUDED_TRELLIS_SISO_COMBINED_F_IMPL_H */ diff --git a/gr-trellis/lib/siso_f_impl.cc b/gr-trellis/lib/siso_f_impl.cc index 14968a45a4..c4052fc28e 100644 --- a/gr-trellis/lib/siso_f_impl.cc +++ b/gr-trellis/lib/siso_f_impl.cc @@ -31,191 +31,194 @@ #include <iostream> namespace gr { - namespace trellis { - - siso_f::sptr - siso_f::make(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t SISO_TYPE) - { - return gnuradio::get_initial_sptr - (new siso_f_impl(FSM, K, S0, SK, POSTI, POSTO, SISO_TYPE)); - } - - - void siso_f_impl::recalculate() - { - int multiple; - if(d_POSTI && d_POSTO) - multiple = d_FSM.I()+d_FSM.O(); - else if(d_POSTI) +namespace trellis { + +siso_f::sptr siso_f::make( + const fsm& FSM, int K, int S0, int SK, bool POSTI, bool POSTO, siso_type_t SISO_TYPE) +{ + return gnuradio::get_initial_sptr( + new siso_f_impl(FSM, K, S0, SK, POSTI, POSTO, SISO_TYPE)); +} + + +void siso_f_impl::recalculate() +{ + int multiple; + if (d_POSTI && d_POSTO) + multiple = d_FSM.I() + d_FSM.O(); + else if (d_POSTI) multiple = d_FSM.I(); - else if(d_POSTO) + else if (d_POSTO) multiple = d_FSM.O(); - else - throw std::runtime_error ("Not both POSTI and POSTO can be false."); - - set_output_multiple (d_K*multiple); - - //what is the meaning of relative rate for a block with 2 inputs? - //set_relative_rate ( (uint64_t) multiple, (uint64_t) d_FSM.I() ); - // it turns out that the above gives problems in the scheduler, so - // let's try (assumption O>I) - //set_relative_rate ( (uint64_t) multiple, (uint64_t) d_FSM.O() ); - // I am tempted to automate like this - if(d_FSM.I() <= d_FSM.O()) - set_relative_rate((uint64_t)multiple, (uint64_t)d_FSM.O()); - else - set_relative_rate((uint64_t)multiple, (uint64_t)d_FSM.I()); - } - - siso_f_impl::siso_f_impl(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t SISO_TYPE) - : block("siso_f", - io_signature::make(1, -1, sizeof(float)), - io_signature::make(1, -1, sizeof(float))), - d_FSM(FSM), d_K(K), - d_S0(S0),d_SK(SK), - d_POSTI(POSTI), d_POSTO(POSTO), - d_SISO_TYPE(SISO_TYPE)//, - //d_alpha(FSM.S()*(K+1)), - //d_beta(FSM.S()*(K+1)) - { - recalculate(); - } - - void siso_f_impl::set_FSM(const fsm &FSM) - { - gr::thread::scoped_lock guard(d_setlock); - d_FSM=FSM; - recalculate(); - } - - void siso_f_impl::set_K(int K) - { - gr::thread::scoped_lock guard(d_setlock); - d_K=K; - recalculate(); - } - - void siso_f_impl::set_POSTI(bool POSTI) - { - gr::thread::scoped_lock guard(d_setlock); - d_POSTI = POSTI; - recalculate(); - } - - void siso_f_impl::set_POSTO(bool POSTO) - { - gr::thread::scoped_lock guard(d_setlock); - d_POSTO = POSTO; - recalculate(); - } - - void siso_f_impl::set_S0(int S0) - { - gr::thread::scoped_lock guard(d_setlock); - d_S0 = S0; - } - - void siso_f_impl::set_SK(int SK) - { - gr::thread::scoped_lock guard(d_setlock); - d_SK = SK; - } - - void siso_f_impl::set_SISO_TYPE(trellis::siso_type_t type) - { - gr::thread::scoped_lock guard(d_setlock); - d_SISO_TYPE = type; + else + throw std::runtime_error("Not both POSTI and POSTO can be false."); + + set_output_multiple(d_K * multiple); + + // what is the meaning of relative rate for a block with 2 inputs? + // set_relative_rate ( (uint64_t) multiple, (uint64_t) d_FSM.I() ); + // it turns out that the above gives problems in the scheduler, so + // let's try (assumption O>I) + // set_relative_rate ( (uint64_t) multiple, (uint64_t) d_FSM.O() ); + // I am tempted to automate like this + if (d_FSM.I() <= d_FSM.O()) + set_relative_rate((uint64_t)multiple, (uint64_t)d_FSM.O()); + else + set_relative_rate((uint64_t)multiple, (uint64_t)d_FSM.I()); +} + +siso_f_impl::siso_f_impl( + const fsm& FSM, int K, int S0, int SK, bool POSTI, bool POSTO, siso_type_t SISO_TYPE) + : block("siso_f", + io_signature::make(1, -1, sizeof(float)), + io_signature::make(1, -1, sizeof(float))), + d_FSM(FSM), + d_K(K), + d_S0(S0), + d_SK(SK), + d_POSTI(POSTI), + d_POSTO(POSTO), + d_SISO_TYPE(SISO_TYPE) //, + // d_alpha(FSM.S()*(K+1)), +// d_beta(FSM.S()*(K+1)) +{ + recalculate(); +} + +void siso_f_impl::set_FSM(const fsm& FSM) +{ + gr::thread::scoped_lock guard(d_setlock); + d_FSM = FSM; + recalculate(); +} + +void siso_f_impl::set_K(int K) +{ + gr::thread::scoped_lock guard(d_setlock); + d_K = K; + recalculate(); +} + +void siso_f_impl::set_POSTI(bool POSTI) +{ + gr::thread::scoped_lock guard(d_setlock); + d_POSTI = POSTI; + recalculate(); +} + +void siso_f_impl::set_POSTO(bool POSTO) +{ + gr::thread::scoped_lock guard(d_setlock); + d_POSTO = POSTO; + recalculate(); +} + +void siso_f_impl::set_S0(int S0) +{ + gr::thread::scoped_lock guard(d_setlock); + d_S0 = S0; +} + +void siso_f_impl::set_SK(int SK) +{ + gr::thread::scoped_lock guard(d_setlock); + d_SK = SK; +} + +void siso_f_impl::set_SISO_TYPE(trellis::siso_type_t type) +{ + gr::thread::scoped_lock guard(d_setlock); + d_SISO_TYPE = type; +} + +siso_f_impl::~siso_f_impl() {} + +void siso_f_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + int multiple; + if (d_POSTI && d_POSTO) + multiple = d_FSM.I() + d_FSM.O(); + else if (d_POSTI) + multiple = d_FSM.I(); + else if (d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error("Not both POSTI and POSTO can be false."); + + // printf("forecast: Multiple = %d\n",multiple); + int input_required1 = d_FSM.I() * (noutput_items / multiple); + int input_required2 = d_FSM.O() * (noutput_items / multiple); + // printf("forecast: Output requirements: %d\n",noutput_items); + // printf("forecast: Input requirements: %d %d\n",input_required1,input_required2); + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs / 2; i++) { + ninput_items_required[2 * i] = input_required1; + ninput_items_required[2 * i + 1] = input_required2; } - - siso_f_impl::~siso_f_impl() - { +} + +int siso_f_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(d_setlock); + int nstreams = output_items.size(); + // printf("general_work:Streams: %d\n",nstreams); + int multiple; + if (d_POSTI && d_POSTO) + multiple = d_FSM.I() + d_FSM.O(); + else if (d_POSTI) + multiple = d_FSM.I(); + else if (d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error("siso_f_impl: Not both POSTI and POSTO can be false.\n"); + + int nblocks = noutput_items / (d_K * multiple); + // printf("general_work:Blocks: %d\n",nblocks); + // for(int i=0;i<ninput_items.size();i++) + // printf("general_work:Input items available: %d\n",ninput_items[i]); + + float (*p2min)(float, float) = NULL; + if (d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if (d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + for (int m = 0; m < nstreams; m++) { + const float* in1 = (const float*)input_items[2 * m]; + const float* in2 = (const float*)input_items[2 * m + 1]; + float* out = (float*)output_items[m]; + for (int n = 0; n < nblocks; n++) { + siso_algorithm(d_FSM.I(), + d_FSM.S(), + d_FSM.O(), + d_FSM.NS(), + d_FSM.OS(), + d_FSM.PS(), + d_FSM.PI(), + d_K, + d_S0, + d_SK, + d_POSTI, + d_POSTO, + p2min, + &(in1[n * d_K * d_FSM.I()]), + &(in2[n * d_K * d_FSM.O()]), + &(out[n * d_K * multiple]) //, + // d_alpha,d_beta + ); + } } - void - siso_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - int multiple; - if(d_POSTI && d_POSTO) - multiple = d_FSM.I()+d_FSM.O(); - else if(d_POSTI) - multiple = d_FSM.I(); - else if(d_POSTO) - multiple = d_FSM.O(); - else - throw std::runtime_error ("Not both POSTI and POSTO can be false."); - - //printf("forecast: Multiple = %d\n",multiple); - int input_required1 = d_FSM.I() * (noutput_items/multiple) ; - int input_required2 = d_FSM.O() * (noutput_items/multiple) ; - //printf("forecast: Output requirements: %d\n",noutput_items); - //printf("forecast: Input requirements: %d %d\n",input_required1,input_required2); - unsigned ninputs = ninput_items_required.size(); - for(unsigned int i = 0; i < ninputs/2; i++) { - ninput_items_required[2*i] = input_required1; - ninput_items_required[2*i+1] = input_required2; - } + for (unsigned int i = 0; i < input_items.size() / 2; i++) { + consume(2 * i, d_FSM.I() * noutput_items / multiple); + consume(2 * i + 1, d_FSM.O() * noutput_items / multiple); } - int - siso_f_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(d_setlock); - int nstreams = output_items.size(); - //printf("general_work:Streams: %d\n",nstreams); - int multiple; - if(d_POSTI && d_POSTO) - multiple = d_FSM.I()+d_FSM.O(); - else if(d_POSTI) - multiple = d_FSM.I(); - else if(d_POSTO) - multiple = d_FSM.O(); - else - throw std::runtime_error("siso_f_impl: Not both POSTI and POSTO can be false.\n"); - - int nblocks = noutput_items / (d_K*multiple); - //printf("general_work:Blocks: %d\n",nblocks); - //for(int i=0;i<ninput_items.size();i++) - //printf("general_work:Input items available: %d\n",ninput_items[i]); - - float (*p2min)(float, float) = NULL; - if(d_SISO_TYPE == TRELLIS_MIN_SUM) - p2min = &min; - else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) - p2min = &min_star; - - for(int m = 0; m < nstreams; m++) { - const float *in1 = (const float*)input_items[2*m]; - const float *in2 = (const float*)input_items[2*m+1]; - float *out = (float*)output_items[m]; - for(int n = 0;n < nblocks; n++) { - siso_algorithm(d_FSM.I(),d_FSM.S(),d_FSM.O(), - d_FSM.NS(),d_FSM.OS(),d_FSM.PS(),d_FSM.PI(), - d_K,d_S0,d_SK, - d_POSTI,d_POSTO, - p2min, - &(in1[n*d_K*d_FSM.I()]),&(in2[n*d_K*d_FSM.O()]), - &(out[n*d_K*multiple])//, - //d_alpha,d_beta - ); - } - } - - for(unsigned int i = 0; i < input_items.size()/2; i++) { - consume(2*i,d_FSM.I() * noutput_items / multiple ); - consume(2*i+1,d_FSM.O() * noutput_items / multiple ); - } - - return noutput_items; - } + return noutput_items; +} - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/siso_f_impl.h b/gr-trellis/lib/siso_f_impl.h index f92616bf0a..92ac211bcf 100644 --- a/gr-trellis/lib/siso_f_impl.h +++ b/gr-trellis/lib/siso_f_impl.h @@ -30,55 +30,57 @@ #include <gnuradio/trellis/siso_f.h> namespace gr { - namespace trellis { +namespace trellis { - class siso_f_impl : public siso_f - { - private: - fsm d_FSM; - int d_K; - int d_S0; - int d_SK; - bool d_POSTI; - bool d_POSTO; - siso_type_t d_SISO_TYPE; - void recalculate(); - //std::vector<float> d_alpha; - //std::vector<float> d_beta; +class siso_f_impl : public siso_f +{ +private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + bool d_POSTI; + bool d_POSTO; + siso_type_t d_SISO_TYPE; + void recalculate(); + // std::vector<float> d_alpha; + // std::vector<float> d_beta; - public: - siso_f_impl(const fsm &FSM, int K, - int S0, int SK, - bool POSTI, bool POSTO, - siso_type_t d_SISO_TYPE); - ~siso_f_impl(); +public: + siso_f_impl(const fsm& FSM, + int K, + int S0, + int SK, + bool POSTI, + bool POSTO, + siso_type_t d_SISO_TYPE); + ~siso_f_impl(); - fsm FSM() const { return d_FSM; } - int K() const { return d_K; } - int S0() const { return d_S0; } - int SK() const { return d_SK; } - bool POSTI() const { return d_POSTI; } - bool POSTO() const { return d_POSTO; } - siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + bool POSTI() const { return d_POSTI; } + bool POSTO() const { return d_POSTO; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } - void set_FSM(const fsm &FSM); - void set_K(int K); - void set_S0(int S0); - void set_SK(int SK); - void set_POSTI(bool POSTI); - void set_POSTO(bool POSTO); - void set_SISO_TYPE(trellis::siso_type_t type); + void set_FSM(const fsm& FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); + void set_POSTI(bool POSTI); + void set_POSTO(bool POSTO); + void set_SISO_TYPE(trellis::siso_type_t type); - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* INCLUDED_TRELLIS_SISO_F_IMPL_H */ diff --git a/gr-trellis/lib/viterbi_combined_impl.cc b/gr-trellis/lib/viterbi_combined_impl.cc index 675af6aea5..a956adfd28 100644 --- a/gr-trellis/lib/viterbi_combined_impl.cc +++ b/gr-trellis/lib/viterbi_combined_impl.cc @@ -29,148 +29,165 @@ #include <iostream> namespace gr { - namespace trellis { - - template <class IN_T,class OUT_T> - typename viterbi_combined<IN_T,OUT_T>::sptr - viterbi_combined<IN_T,OUT_T>::make(const fsm &FSM, int K, - int S0, int SK, int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t TYPE) - { - return gnuradio::get_initial_sptr - (new viterbi_combined_impl<IN_T,OUT_T>(FSM, K, S0, SK, D, TABLE,TYPE)); - } - - template <class IN_T,class OUT_T> - viterbi_combined_impl<IN_T,OUT_T>::viterbi_combined_impl(const fsm &FSM, int K, - int S0, int SK, int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t TYPE) +namespace trellis { + +template <class IN_T, class OUT_T> +typename viterbi_combined<IN_T, OUT_T>::sptr +viterbi_combined<IN_T, OUT_T>::make(const fsm& FSM, + int K, + int S0, + int SK, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t TYPE) +{ + return gnuradio::get_initial_sptr( + new viterbi_combined_impl<IN_T, OUT_T>(FSM, K, S0, SK, D, TABLE, TYPE)); +} + +template <class IN_T, class OUT_T> +viterbi_combined_impl<IN_T, OUT_T>::viterbi_combined_impl( + const fsm& FSM, + int K, + int S0, + int SK, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t TYPE) : block("viterbi_combined<IN_T,OUT_T>", - io_signature::make(1, -1, sizeof(IN_T)), - io_signature::make(1, -1, sizeof(OUT_T))), - d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK), d_D(D), - d_TABLE(TABLE), d_TYPE(TYPE)//, - //d_trace(FSM.S()*K) - { - this->set_relative_rate(1, (uint64_t)d_D); - this->set_output_multiple(d_K); - } - - template <class IN_T,class OUT_T> - void - viterbi_combined_impl<IN_T,OUT_T>::set_K(int K) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_K = K; - this->set_output_multiple(d_K); - } - - template <class IN_T,class OUT_T> - void - viterbi_combined_impl<IN_T,OUT_T>::set_D(int D) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_D = D; - this->set_relative_rate(1, (uint64_t)d_D); + io_signature::make(1, -1, sizeof(IN_T)), + io_signature::make(1, -1, sizeof(OUT_T))), + d_FSM(FSM), + d_K(K), + d_S0(S0), + d_SK(SK), + d_D(D), + d_TABLE(TABLE), + d_TYPE(TYPE) //, + // d_trace(FSM.S()*K) +{ + this->set_relative_rate(1, (uint64_t)d_D); + this->set_output_multiple(d_K); +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::set_K(int K) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_K = K; + this->set_output_multiple(d_K); +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::set_D(int D) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_D = D; + this->set_relative_rate(1, (uint64_t)d_D); +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::set_FSM(const fsm& FSM) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_FSM = FSM; +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::set_S0(int S0) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_S0 = S0; +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::set_SK(int SK) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_SK = SK; +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::set_TYPE(digital::trellis_metric_type_t type) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_TYPE = type; +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::set_TABLE(const std::vector<IN_T>& table) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_TABLE = table; +} + +template <class IN_T, class OUT_T> +viterbi_combined_impl<IN_T, OUT_T>::~viterbi_combined_impl() +{ +} + +template <class IN_T, class OUT_T> +void viterbi_combined_impl<IN_T, OUT_T>::forecast(int noutput_items, + gr_vector_int& ninput_items_required) +{ + int input_required = d_D * noutput_items; + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; } - - template <class IN_T,class OUT_T> - void viterbi_combined_impl<IN_T,OUT_T>::set_FSM(const fsm &FSM) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_FSM = FSM; - } - - template <class IN_T,class OUT_T> - void viterbi_combined_impl<IN_T,OUT_T>::set_S0(int S0) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_S0 = S0; - } - - template <class IN_T,class OUT_T> - void viterbi_combined_impl<IN_T,OUT_T>::set_SK(int SK) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_SK = SK; - } - - template <class IN_T,class OUT_T> - void - viterbi_combined_impl<IN_T,OUT_T>::set_TYPE(digital::trellis_metric_type_t type) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_TYPE = type; - } - - template <class IN_T,class OUT_T> - void - viterbi_combined_impl<IN_T,OUT_T>::set_TABLE(const std::vector<IN_T> &table) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_TABLE = table; - } - - template <class IN_T,class OUT_T> - viterbi_combined_impl<IN_T,OUT_T>::~viterbi_combined_impl() - { - } - - template <class IN_T,class OUT_T> - void - viterbi_combined_impl<IN_T,OUT_T>::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - int input_required = d_D * noutput_items; - unsigned ninputs = ninput_items_required.size(); - for(unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = input_required; - } - } - - template <class IN_T,class OUT_T> - int - viterbi_combined_impl<IN_T,OUT_T>::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(this->d_setlock); - int nstreams = input_items.size(); - int nblocks = noutput_items / d_K; - - for(int m=0;m<nstreams;m++) { - const IN_T *in = (const IN_T*)input_items[m]; - OUT_T *out = (OUT_T*)output_items[m]; - - for(int n=0;n<nblocks;n++) { - viterbi_algorithm_combined(d_FSM.I(), d_FSM.S(), d_FSM.O(), - d_FSM.NS(), d_FSM.OS(), d_FSM.PS(), - d_FSM.PI(), d_K,d_S0, d_SK, d_D, - d_TABLE, d_TYPE, - &(in[n*d_K*d_D]), &(out[n*d_K])); - } - } - - this->consume_each(d_D * noutput_items); - return noutput_items; +} + +template <class IN_T, class OUT_T> +int viterbi_combined_impl<IN_T, OUT_T>::general_work( + int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(this->d_setlock); + int nstreams = input_items.size(); + int nblocks = noutput_items / d_K; + + for (int m = 0; m < nstreams; m++) { + const IN_T* in = (const IN_T*)input_items[m]; + OUT_T* out = (OUT_T*)output_items[m]; + + for (int n = 0; n < nblocks; n++) { + viterbi_algorithm_combined(d_FSM.I(), + d_FSM.S(), + d_FSM.O(), + d_FSM.NS(), + d_FSM.OS(), + d_FSM.PS(), + d_FSM.PI(), + d_K, + d_S0, + d_SK, + d_D, + d_TABLE, + d_TYPE, + &(in[n * d_K * d_D]), + &(out[n * d_K])); + } } - template class viterbi_combined<std::int16_t, std::uint8_t>; - template class viterbi_combined<std::int16_t, std::int16_t>; - template class viterbi_combined<std::int16_t, std::int32_t>; - template class viterbi_combined<std::int32_t, std::uint8_t>; - template class viterbi_combined<std::int32_t, std::int16_t>; - template class viterbi_combined<std::int32_t, std::int32_t>; - template class viterbi_combined<float, std::uint8_t>; - template class viterbi_combined<float, std::int16_t>; - template class viterbi_combined<float, std::int32_t>; - template class viterbi_combined<gr_complex, std::uint8_t>; - template class viterbi_combined<gr_complex, std::int16_t>; - template class viterbi_combined<gr_complex, std::int32_t>; - - - } /* namespace trellis */ + this->consume_each(d_D * noutput_items); + return noutput_items; +} + +template class viterbi_combined<std::int16_t, std::uint8_t>; +template class viterbi_combined<std::int16_t, std::int16_t>; +template class viterbi_combined<std::int16_t, std::int32_t>; +template class viterbi_combined<std::int32_t, std::uint8_t>; +template class viterbi_combined<std::int32_t, std::int16_t>; +template class viterbi_combined<std::int32_t, std::int32_t>; +template class viterbi_combined<float, std::uint8_t>; +template class viterbi_combined<float, std::int16_t>; +template class viterbi_combined<float, std::int32_t>; +template class viterbi_combined<gr_complex, std::uint8_t>; +template class viterbi_combined<gr_complex, std::int16_t>; +template class viterbi_combined<gr_complex, std::int32_t>; + + +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/viterbi_combined_impl.h b/gr-trellis/lib/viterbi_combined_impl.h index e83114673f..ea3aaeed8a 100644 --- a/gr-trellis/lib/viterbi_combined_impl.h +++ b/gr-trellis/lib/viterbi_combined_impl.h @@ -26,55 +26,57 @@ #include <gnuradio/trellis/viterbi_combined.h> namespace gr { - namespace trellis { +namespace trellis { - template <class IN_T,class OUT_T> - class viterbi_combined_impl : public viterbi_combined<IN_T,OUT_T> - { - private: - fsm d_FSM; - int d_K; - int d_S0; - int d_SK; - int d_D; - std::vector<IN_T> d_TABLE; - digital::trellis_metric_type_t d_TYPE; - //std::vector<int> d_trace; +template <class IN_T, class OUT_T> +class viterbi_combined_impl : public viterbi_combined<IN_T, OUT_T> +{ +private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + int d_D; + std::vector<IN_T> d_TABLE; + digital::trellis_metric_type_t d_TYPE; + // std::vector<int> d_trace; - public: - viterbi_combined_impl(const fsm &FSM, int K, - int S0, int SK, int D, - const std::vector<IN_T> &TABLE, - digital::trellis_metric_type_t TYPE); - ~viterbi_combined_impl(); +public: + viterbi_combined_impl(const fsm& FSM, + int K, + int S0, + int SK, + int D, + const std::vector<IN_T>& TABLE, + digital::trellis_metric_type_t TYPE); + ~viterbi_combined_impl(); - fsm FSM() const { return d_FSM; } - int K() const { return d_K; } - int S0() const { return d_S0; } - int SK() const { return d_SK; } - int D() const { return d_D; } - std::vector<IN_T> TABLE() const { return d_TABLE; } - digital::trellis_metric_type_t TYPE() const { return d_TYPE; } - //std::vector<int> trace() const { return d_trace; } + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + int D() const { return d_D; } + std::vector<IN_T> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t TYPE() const { return d_TYPE; } + // std::vector<int> trace() const { return d_trace; } - void set_FSM(const fsm &FSM); - void set_K(int K); - void set_S0(int S0); - void set_SK(int SK); - void set_D(int D); - void set_TABLE(const std::vector<IN_T> &table); - void set_TYPE(digital::trellis_metric_type_t type); + void set_FSM(const fsm& FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); + void set_D(int D); + void set_TABLE(const std::vector<IN_T>& table); + void set_TYPE(digital::trellis_metric_type_t type); - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int& ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* VITERBI_COMBINED_IMPL_H */ diff --git a/gr-trellis/lib/viterbi_impl.cc b/gr-trellis/lib/viterbi_impl.cc index 745109997f..69ac65c872 100644 --- a/gr-trellis/lib/viterbi_impl.cc +++ b/gr-trellis/lib/viterbi_impl.cc @@ -30,106 +30,110 @@ #include <iostream> namespace gr { - namespace trellis { - - template <class T> - typename viterbi<T>::sptr - viterbi<T>::make(const fsm &FSM, int K, - int S0, int SK) - { - return gnuradio::get_initial_sptr - (new viterbi_impl<T>(FSM, K, S0, SK)); - } - - template <class T> - viterbi_impl<T>::viterbi_impl(const fsm &FSM, int K, - int S0, int SK) - : block("viterbi", - io_signature::make(1, -1, sizeof(float)), - io_signature::make(1, -1, sizeof(T))), - d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK)//, - //d_trace(FSM.S()*K) - { - this->set_relative_rate(1, (uint64_t)d_FSM.O()); - this->set_output_multiple(d_K); - } - - template <class T> - void viterbi_impl<T>::set_FSM(const fsm &FSM) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_FSM = FSM; - this->set_relative_rate(1, (uint64_t)d_FSM.O()); - } - - template <class T> - void viterbi_impl<T>::set_K(int K) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_K = K; - this->set_output_multiple(d_K); - } - - template <class T> - void viterbi_impl<T>::set_S0(int S0) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_S0 = S0; - } +namespace trellis { - template <class T> - void viterbi_impl<T>::set_SK(int SK) - { - gr::thread::scoped_lock guard(this->d_setlock); - d_SK = SK; - } +template <class T> +typename viterbi<T>::sptr viterbi<T>::make(const fsm& FSM, int K, int S0, int SK) +{ + return gnuradio::get_initial_sptr(new viterbi_impl<T>(FSM, K, S0, SK)); +} - template <class T> - viterbi_impl<T>::~viterbi_impl() - { +template <class T> +viterbi_impl<T>::viterbi_impl(const fsm& FSM, int K, int S0, int SK) + : block("viterbi", + io_signature::make(1, -1, sizeof(float)), + io_signature::make(1, -1, sizeof(T))), + d_FSM(FSM), + d_K(K), + d_S0(S0), + d_SK(SK) //, + // d_trace(FSM.S()*K) +{ + this->set_relative_rate(1, (uint64_t)d_FSM.O()); + this->set_output_multiple(d_K); +} + +template <class T> +void viterbi_impl<T>::set_FSM(const fsm& FSM) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_FSM = FSM; + this->set_relative_rate(1, (uint64_t)d_FSM.O()); +} + +template <class T> +void viterbi_impl<T>::set_K(int K) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_K = K; + this->set_output_multiple(d_K); +} + +template <class T> +void viterbi_impl<T>::set_S0(int S0) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_S0 = S0; +} + +template <class T> +void viterbi_impl<T>::set_SK(int SK) +{ + gr::thread::scoped_lock guard(this->d_setlock); + d_SK = SK; +} + +template <class T> +viterbi_impl<T>::~viterbi_impl() +{ +} + +template <class T> +void viterbi_impl<T>::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + int input_required = d_FSM.O() * noutput_items; + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; } - - template <class T> - void - viterbi_impl<T>::forecast(int noutput_items, - gr_vector_int &ninput_items_required) - { - int input_required = d_FSM.O() * noutput_items; - unsigned ninputs = ninput_items_required.size(); - for(unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = input_required; - } +} + +template <class T> +int viterbi_impl<T>::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + gr::thread::scoped_lock guard(this->d_setlock); + int nstreams = input_items.size(); + int nblocks = noutput_items / d_K; + + for (int m = 0; m < nstreams; m++) { + const float* in = (const float*)input_items[m]; + T* out = (T*)output_items[m]; + + for (int n = 0; n < nblocks; n++) { + viterbi_algorithm(d_FSM.I(), + d_FSM.S(), + d_FSM.O(), + d_FSM.NS(), + d_FSM.OS(), + d_FSM.PS(), + d_FSM.PI(), + d_K, + d_S0, + d_SK, + &(in[n * d_K * d_FSM.O()]), + &(out[n * d_K])); + } } - template <class T> - int - viterbi_impl<T>::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - gr::thread::scoped_lock guard(this->d_setlock); - int nstreams = input_items.size(); - int nblocks = noutput_items / d_K; - - for(int m = 0; m < nstreams; m++) { - const float *in = (const float*)input_items[m]; - T *out = (T*)output_items[m]; - - for(int n = 0; n < nblocks; n++) { - viterbi_algorithm(d_FSM.I(), d_FSM.S(), d_FSM.O(), - d_FSM.NS(), d_FSM.OS(), d_FSM.PS(), - d_FSM.PI(), d_K,d_S0, d_SK, - &(in[n*d_K*d_FSM.O()]), &(out[n*d_K])); - } - } - - this->consume_each(d_FSM.O() * noutput_items); - return noutput_items; - } + this->consume_each(d_FSM.O() * noutput_items); + return noutput_items; +} template class viterbi<std::uint8_t>; template class viterbi<std::int16_t>; template class viterbi<std::int32_t>; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ diff --git a/gr-trellis/lib/viterbi_impl.h b/gr-trellis/lib/viterbi_impl.h index c9f40a0b79..a8e2c23685 100644 --- a/gr-trellis/lib/viterbi_impl.h +++ b/gr-trellis/lib/viterbi_impl.h @@ -27,43 +27,41 @@ #include <gnuradio/trellis/viterbi.h> namespace gr { - namespace trellis { +namespace trellis { -template<class T> - class viterbi_impl : public viterbi<T> - { - private: - fsm d_FSM; - int d_K; - int d_S0; - int d_SK; - //std::vector<int> d_trace; +template <class T> +class viterbi_impl : public viterbi<T> +{ +private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + // std::vector<int> d_trace; - public: - viterbi_impl(const fsm &FSM, int K, - int S0, int SK); - ~viterbi_impl(); +public: + viterbi_impl(const fsm& FSM, int K, int S0, int SK); + ~viterbi_impl(); - fsm FSM() const { return d_FSM; } - int K() const { return d_K; } - int S0() const { return d_S0; } - int SK() const { return d_SK; } + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } - void set_FSM(const fsm &FSM); - void set_K(int K); - void set_S0(int S0); - void set_SK(int SK); - //std::vector<int> trace () const { return d_trace; } + void set_FSM(const fsm& FSM); + void set_K(int K); + void set_S0(int S0); + void set_SK(int SK); + // std::vector<int> trace () const { return d_trace; } - void forecast(int noutput_items, - gr_vector_int &ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + void forecast(int noutput_items, gr_vector_int& ninput_items_required); + int general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; - } /* namespace trellis */ +} /* namespace trellis */ } /* namespace gr */ #endif /* VITERBI_IMPL_H */ |