summaryrefslogtreecommitdiff
path: root/gr-trellis/lib/core_algorithms.cc
diff options
context:
space:
mode:
authorMarcus Müller <mmueller@gnuradio.org>2019-08-07 21:45:12 +0200
committerMarcus Müller <marcus@hostalia.de>2019-08-09 23:04:28 +0200
commitf7bbf2c1d8d780294f3e016aff239ca35eb6516e (patch)
treee09ab6112e02b2215b2d59ac24d3d6ea2edac745 /gr-trellis/lib/core_algorithms.cc
parent78431dc6941e3acc67c858277dfe4a0ed583643c (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.cc3001
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 */