From f7bbf2c1d8d780294f3e016aff239ca35eb6516e Mon Sep 17 00:00:00 2001
From: Marcus Müller <mmueller@gnuradio.org>
Date: Wed, 7 Aug 2019 21:45:12 +0200
Subject: Tree: clang-format without the include sorting

---
 gr-trellis/lib/core_algorithms.cc | 3001 +++++++++++++++++++++----------------
 1 file changed, 1692 insertions(+), 1309 deletions(-)

(limited to 'gr-trellis/lib/core_algorithms.cc')

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 */
-- 
cgit v1.2.3