Imported Upstream version 3.0.4
[debian/gnuradio] / gr-trellis / src / lib / trellis_viterbi_combined_b.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <trellis_viterbi_combined_b.h>
28 #include <gr_io_signature.h>
29 #include <assert.h>
30 #include <iostream>
31   
32 static const float INF = 1.0e9;
33
34 trellis_viterbi_combined_b_sptr 
35 trellis_make_viterbi_combined_b (
36     const fsm &FSM,
37     int K,
38     int S0,
39     int SK,
40     int D,
41     const std::vector<float> &TABLE,
42     trellis_metric_type_t TYPE)
43 {
44   return trellis_viterbi_combined_b_sptr (new trellis_viterbi_combined_b (FSM,K,S0,SK,D,TABLE,TYPE));
45 }
46
47 trellis_viterbi_combined_b::trellis_viterbi_combined_b (
48     const fsm &FSM,
49     int K,
50     int S0,
51     int SK,
52     int D,
53     const std::vector<float> &TABLE,
54     trellis_metric_type_t TYPE)
55   : gr_block ("viterbi_combined_b",
56                           gr_make_io_signature (1, -1, sizeof (float)),
57                           gr_make_io_signature (1, -1, sizeof (unsigned char))),  
58   d_FSM (FSM),
59   d_K (K),
60   d_S0 (S0),
61   d_SK (SK),
62   d_D (D),
63   d_TABLE (TABLE),
64   d_TYPE (TYPE)//,
65   //d_trace(FSM.S()*K)
66 {
67     set_relative_rate (1.0 / ((double) d_D));
68     set_output_multiple (d_K);
69 }
70
71
72 void
73 trellis_viterbi_combined_b::forecast (int noutput_items, gr_vector_int &ninput_items_required)
74 {
75   assert (noutput_items % d_K == 0);
76   int input_required =  d_D * noutput_items ;
77   unsigned ninputs = ninput_items_required.size();
78   for (unsigned int i = 0; i < ninputs; i++) {
79     ninput_items_required[i] = input_required;
80   }
81 }
82
83
84
85
86 void viterbi_algorithm_combined(int I, int S, int O, 
87              const std::vector<int> &NS,
88              const std::vector<int> &OS,
89              const std::vector<int> &PS,
90              const std::vector<int> &PI,
91              int K,
92              int S0,int SK,
93              int D,
94              const std::vector<float> &TABLE,
95              trellis_metric_type_t TYPE,
96              const float *in, unsigned char *out)//,
97              //std::vector<int> &trace) 
98 {
99   std::vector<int> trace(S*K);
100   std::vector<float> alpha(S*2);
101   float *metric = new float[O];
102   int alphai;
103   float norm,mm,minm;
104   int minmi;
105   int st;
106
107   if(S0<0) { // initial state not specified
108       for(int i=0;i<S;i++) alpha[0*S+i]=0;
109   }
110   else {
111       for(int i=0;i<S;i++) alpha[0*S+i]=INF;
112       alpha[0*S+S0]=0.0;
113   }
114
115   alphai=0;
116   for(int k=0;k<K;k++) {
117       calc_metric(O, D, TABLE, &(in[k*D]), metric,TYPE); // calc metrics
118       norm=INF;
119       for(int j=0;j<S;j++) { // for each next state do ACS
120           minm=INF;
121           minmi=0;
122           for(int i=0;i<I;i++) {
123               int i0 = j*I+i;
124               if((mm=alpha[alphai*S+PS[i0]]+metric[OS[PS[i0]*I+PI[i0]]])<minm)
125                   minm=mm,minmi=i;
126           }
127           trace[k*S+j]=minmi;
128           alpha[((alphai+1)%2)*S+j]=minm;
129           if(minm<norm) norm=minm;
130       }
131       for(int j=0;j<S;j++) 
132           alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode
133       alphai=(alphai+1)%2;
134   }
135
136   if(SK<0) { // final state not specified
137       minm=INF;
138       minmi=0;
139       for(int i=0;i<S;i++)
140           if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i;
141       st=minmi;
142   }
143   else {
144       st=SK;
145   }
146
147   for(int k=K-1;k>=0;k--) { // traceback
148       int i0=st*I+trace[k*S+st];
149       out[k]= (unsigned char) PI[i0];
150       st=PS[i0];
151   }
152   
153   delete [] metric;
154
155 }
156
157
158
159
160
161
162 int
163 trellis_viterbi_combined_b::general_work (int noutput_items,
164                         gr_vector_int &ninput_items,
165                         gr_vector_const_void_star &input_items,
166                         gr_vector_void_star &output_items)
167 {
168   assert (input_items.size() == output_items.size());
169   int nstreams = input_items.size();
170   assert (noutput_items % d_K == 0);
171   int nblocks = noutput_items / d_K;
172
173   for (int m=0;m<nstreams;m++) {
174     const float *in = (const float *) input_items[m];
175     unsigned char *out = (unsigned char *) output_items[m];
176     for (int n=0;n<nblocks;n++) {
177       viterbi_algorithm_combined(d_FSM.I(),d_FSM.S(),d_FSM.O(),d_FSM.NS(),d_FSM.OS(),d_FSM.PS(),d_FSM.PI(),d_K,d_S0,d_SK,d_D,d_TABLE,d_TYPE,&(in[n*d_K*d_D]),&(out[n*d_K]));//,d_trace);
178     }
179   }
180
181   consume_each (d_D * noutput_items );
182   return noutput_items;
183 }