Merged anastas/wip changes r3156:3218 into trunk.
[debian/gnuradio] / gr-trellis / src / lib / trellis_viterbi_combined_X.cc.t
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 2, 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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <@NAME@.h>
28 #include <gr_io_signature.h>
29 #include <assert.h>
30 #include <iostream>
31   
32 static const float INF = 1.0e9;
33
34 @SPTR_NAME@ 
35 trellis_make_@BASE_NAME@ (
36     const fsm &FSM,
37     const int D,
38     const std::vector<float> &TABLE,
39     const int K,
40     const int S0,
41     const int SK,
42     const trellis_metric_type_t TYPE)
43 {
44   return @SPTR_NAME@ (new @NAME@ (FSM,D,TABLE,K,S0,SK,TYPE));
45 }
46
47 @NAME@::@NAME@ (
48     const fsm &FSM,
49     const int D,
50     const std::vector<float> &TABLE,
51     const int K,
52     const int S0,
53     const int SK,
54     const trellis_metric_type_t TYPE)
55   : gr_block ("@BASE_NAME@",
56                           gr_make_io_signature (1, -1, sizeof (float)),
57                           gr_make_io_signature (1, -1, sizeof (@TYPE@))),  
58   d_FSM (FSM),
59   d_D (D),
60   d_TABLE (TABLE),
61   d_K (K),
62   d_S0 (S0),
63   d_SK (SK),
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 @NAME@::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(const int I, const int S, const 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              const int D,
92              const std::vector<float> &TABLE,
93              const int K,
94              const int S0,const int SK,
95              const trellis_metric_type_t TYPE,
96              const float *in, @TYPE@ *out,
97              std::vector<int> &trace) 
98 {
99   std::vector<float> alpha(S*2);
100   float *metric = new float[O];
101   int alphai;
102   float norm,mm,minm;
103   int minmi;
104   int st;
105
106   if(S0<0) { // initial state not specified
107       for(int i=0;i<S;i++) alpha[0*S+i]=0;
108   }
109   else {
110       for(int i=0;i<S;i++) alpha[0*S+i]=INF;
111       alpha[0*S+S0]=0.0;
112   }
113
114   alphai=0;
115   for(int k=0;k<K;k++) {
116       calc_metric_f(O, D, TABLE, &(in[k*D]), metric,TYPE); // calc metrics
117       norm=INF;
118       for(int j=0;j<S;j++) { // for each next state do ACS
119           minm=INF;
120           minmi=0;
121           for(int i=0;i<I;i++) {
122               int i0 = j*I+i;
123               if((mm=alpha[alphai*S+PS[i0]]+metric[OS[PS[i0]*I+PI[i0]]])<minm)
124                   minm=mm,minmi=i;
125           }
126           trace[k*S+j]=minmi;
127           alpha[((alphai+1)%2)*S+j]=minm;
128           if(minm<norm) norm=minm;
129       }
130       for(int j=0;j<S;j++) 
131           alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode
132       alphai=(alphai+1)%2;
133   }
134
135   if(SK<0) { // final state not specified
136       minm=INF;
137       minmi=0;
138       for(int i=0;i<S;i++)
139           if((mm=trace[(K-1)*S+i])<minm) minm=mm,minmi=i;
140       st=minmi;
141   }
142   else {
143       st=SK;
144   }
145
146   for(int k=K-1;k>=0;k--) { // traceback
147       int i0=st*I+trace[k*S+st];
148       out[k]= (@TYPE@) PI[i0];
149       st=PS[i0];
150   }
151   
152   delete [] metric;
153
154 }
155
156
157
158
159
160
161 int
162 @NAME@::general_work (int noutput_items,
163                         gr_vector_int &ninput_items,
164                         gr_vector_const_void_star &input_items,
165                         gr_vector_void_star &output_items)
166 {
167   assert (input_items.size() == output_items.size());
168   int nstreams = input_items.size();
169   assert (noutput_items % d_K == 0);
170   int nblocks = noutput_items / d_K;
171
172   for (int m=0;m<nstreams;m++) {
173     const float *in = (const float *) input_items[m];
174     @TYPE@ *out = (@TYPE@ *) output_items[m];
175     for (int n=0;n<nblocks;n++) {
176       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_D,d_TABLE,d_K,d_S0,d_SK,d_TYPE,&(in[n*d_K*d_D]),&(out[n*d_K]),d_trace);
177     }
178   }
179
180   consume_each (d_D * noutput_items );
181   return noutput_items;
182 }