diff options
author | Marcus Müller <mmueller@gnuradio.org> | 2019-08-07 21:45:12 +0200 |
---|---|---|
committer | Marcus Müller <marcus@hostalia.de> | 2019-08-09 23:04:28 +0200 |
commit | f7bbf2c1d8d780294f3e016aff239ca35eb6516e (patch) | |
tree | e09ab6112e02b2215b2d59ac24d3d6ea2edac745 /gr-trellis/lib/core_algorithms.cc | |
parent | 78431dc6941e3acc67c858277dfe4a0ed583643c (diff) |
Tree: clang-format without the include sorting
Diffstat (limited to 'gr-trellis/lib/core_algorithms.cc')
-rw-r--r-- | gr-trellis/lib/core_algorithms.cc | 3001 |
1 files changed, 1692 insertions, 1309 deletions
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 */ |