3
* Copyright 2004 Free Software Foundation, Inc.
5
* This file is part of GNU Radio
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)
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.
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.
27
#include "core_algorithms.h"
28
#include "calc_metric.h"
30
static const float INF = 1.0e9;
32
float min(float a, float b)
34
return a <= b ? a : b;
37
float min_star(float a, float b)
39
return (a <= b ? a : b)-log(1+exp(a <= b ? a-b : b-a));
46
void viterbi_algorithm(int I, int S, int O,
47
const std::vector<int> &NS,
48
const std::vector<int> &OS,
49
const std::vector< std::vector<int> > &PS,
50
const std::vector< std::vector<int> > &PI,
53
const float *in, T *out)//,
54
//std::vector<int> &trace)
56
std::vector<int> trace(S*K);
57
std::vector<float> alpha(S*2);
64
if(S0<0) { // initial state not specified
65
for(int i=0;i<S;i++) alpha[0*S+i]=0;
68
for(int i=0;i<S;i++) alpha[0*S+i]=INF;
73
for(int k=0;k<K;k++) {
75
for(int j=0;j<S;j++) { // for each next state do ACS
78
for(unsigned int i=0;i<PS[j].size();i++) {
80
if((mm=alpha[alphai*S+PS[j][i]]+in[k*O+OS[PS[j][i]*I+PI[j][i]]])<minm)
84
alpha[((alphai+1)%2)*S+j]=minm;
85
if(minm<norm) norm=minm;
88
alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode
92
if(SK<0) { // final state not specified
96
if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i;
103
for(int k=K-1;k>=0;k--) { // traceback
104
int i0=trace[k*S+st];
105
out[k]= (T) PI[st][i0];
113
void viterbi_algorithm<unsigned char>(int I, int S, int O,
114
const std::vector<int> &NS,
115
const std::vector<int> &OS,
116
const std::vector< std::vector<int> > &PS,
117
const std::vector< std::vector<int> > &PI,
120
const float *in, unsigned char *out);
124
void viterbi_algorithm<short>(int I, int S, int O,
125
const std::vector<int> &NS,
126
const std::vector<int> &OS,
127
const std::vector< std::vector<int> > &PS,
128
const std::vector< std::vector<int> > &PI,
131
const float *in, short *out);
134
void viterbi_algorithm<int>(int I, int S, int O,
135
const std::vector<int> &NS,
136
const std::vector<int> &OS,
137
const std::vector< std::vector<int> > &PS,
138
const std::vector< std::vector<int> > &PI,
141
const float *in, int *out);
145
//==============================================
147
template <class Ti, class To>
148
void viterbi_algorithm_combined(int I, int S, int O,
149
const std::vector<int> &NS,
150
const std::vector<int> &OS,
151
const std::vector< std::vector<int> > &PS,
152
const std::vector< std::vector<int> > &PI,
156
const std::vector<Ti> &TABLE,
157
trellis_metric_type_t TYPE,
158
const Ti *in, To *out
161
std::vector<int> trace(S*K);
162
std::vector<float> alpha(S*2);
163
float *metric = new float[O];
169
if(S0<0) { // initial state not specified
170
for(int i=0;i<S;i++) alpha[0*S+i]=0;
173
for(int i=0;i<S;i++) alpha[0*S+i]=INF;
178
for(int k=0;k<K;k++) {
179
calc_metric(O, D, TABLE, &(in[k*D]), metric,TYPE); // calc metrics
181
for(int j=0;j<S;j++) { // for each next state do ACS
184
for(unsigned int i=0;i<PS[j].size();i++) {
186
if((mm=alpha[alphai*S+PS[j][i]]+metric[OS[PS[j][i]*I+PI[j][i]]])<minm)
190
alpha[((alphai+1)%2)*S+j]=minm;
191
if(minm<norm) norm=minm;
194
alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode
198
if(SK<0) { // final state not specified
202
if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i;
209
for(int k=K-1;k>=0;k--) { // traceback
210
int i0=trace[k*S+st];
211
out[k]= (To) PI[st][i0];
225
void viterbi_algorithm_combined<short,unsigned char>(int I, int S, int O,
226
const std::vector<int> &NS,
227
const std::vector<int> &OS,
228
const std::vector< std::vector<int> > &PS,
229
const std::vector< std::vector<int> > &PI,
233
const std::vector<short> &TABLE,
234
trellis_metric_type_t TYPE,
235
const short *in, unsigned char *out
239
void viterbi_algorithm_combined<int,unsigned char>(int I, int S, int O,
240
const std::vector<int> &NS,
241
const std::vector<int> &OS,
242
const std::vector< std::vector<int> > &PS,
243
const std::vector< std::vector<int> > &PI,
247
const std::vector<int> &TABLE,
248
trellis_metric_type_t TYPE,
249
const int *in, unsigned char *out
253
void viterbi_algorithm_combined<float,unsigned char>(int I, int S, int O,
254
const std::vector<int> &NS,
255
const std::vector<int> &OS,
256
const std::vector< std::vector<int> > &PS,
257
const std::vector< std::vector<int> > &PI,
261
const std::vector<float> &TABLE,
262
trellis_metric_type_t TYPE,
263
const float *in, unsigned char *out
267
void viterbi_algorithm_combined<gr_complex,unsigned char>(int I, int S, int O,
268
const std::vector<int> &NS,
269
const std::vector<int> &OS,
270
const std::vector< std::vector<int> > &PS,
271
const std::vector< std::vector<int> > &PI,
275
const std::vector<gr_complex> &TABLE,
276
trellis_metric_type_t TYPE,
277
const gr_complex *in, unsigned char *out
283
void viterbi_algorithm_combined<short,short>(int I, int S, int O,
284
const std::vector<int> &NS,
285
const std::vector<int> &OS,
286
const std::vector< std::vector<int> > &PS,
287
const std::vector< std::vector<int> > &PI,
291
const std::vector<short> &TABLE,
292
trellis_metric_type_t TYPE,
293
const short *in, short *out
297
void viterbi_algorithm_combined<int,short>(int I, int S, int O,
298
const std::vector<int> &NS,
299
const std::vector<int> &OS,
300
const std::vector< std::vector<int> > &PS,
301
const std::vector< std::vector<int> > &PI,
305
const std::vector<int> &TABLE,
306
trellis_metric_type_t TYPE,
307
const int *in, short *out
311
void viterbi_algorithm_combined<float,short>(int I, int S, int O,
312
const std::vector<int> &NS,
313
const std::vector<int> &OS,
314
const std::vector< std::vector<int> > &PS,
315
const std::vector< std::vector<int> > &PI,
319
const std::vector<float> &TABLE,
320
trellis_metric_type_t TYPE,
321
const float *in, short *out
325
void viterbi_algorithm_combined<gr_complex,short>(int I, int S, int O,
326
const std::vector<int> &NS,
327
const std::vector<int> &OS,
328
const std::vector< std::vector<int> > &PS,
329
const std::vector< std::vector<int> > &PI,
333
const std::vector<gr_complex> &TABLE,
334
trellis_metric_type_t TYPE,
335
const gr_complex *in, short *out
341
void viterbi_algorithm_combined<short,int>(int I, int S, int O,
342
const std::vector<int> &NS,
343
const std::vector<int> &OS,
344
const std::vector< std::vector<int> > &PS,
345
const std::vector< std::vector<int> > &PI,
349
const std::vector<short> &TABLE,
350
trellis_metric_type_t TYPE,
351
const short *in, int *out
355
void viterbi_algorithm_combined<int,int>(int I, int S, int O,
356
const std::vector<int> &NS,
357
const std::vector<int> &OS,
358
const std::vector< std::vector<int> > &PS,
359
const std::vector< std::vector<int> > &PI,
363
const std::vector<int> &TABLE,
364
trellis_metric_type_t TYPE,
365
const int *in, int *out
369
void viterbi_algorithm_combined<float,int>(int I, int S, int O,
370
const std::vector<int> &NS,
371
const std::vector<int> &OS,
372
const std::vector< std::vector<int> > &PS,
373
const std::vector< std::vector<int> > &PI,
377
const std::vector<float> &TABLE,
378
trellis_metric_type_t TYPE,
379
const float *in, int *out
383
void viterbi_algorithm_combined<gr_complex,int>(int I, int S, int O,
384
const std::vector<int> &NS,
385
const std::vector<int> &OS,
386
const std::vector< std::vector<int> > &PS,
387
const std::vector< std::vector<int> > &PI,
391
const std::vector<gr_complex> &TABLE,
392
trellis_metric_type_t TYPE,
393
const gr_complex *in, int *out
415
//===============================================
418
void siso_algorithm(int I, int S, int O,
419
const std::vector<int> &NS,
420
const std::vector<int> &OS,
421
const std::vector< std::vector<int> > &PS,
422
const std::vector< std::vector<int> > &PI,
425
bool POSTI, bool POSTO,
426
float (*p2mymin)(float,float),
427
const float *priori, const float *prioro, float *post//,
428
//std::vector<float> &alpha,
429
//std::vector<float> &beta
433
std::vector<float> alpha(S*(K+1));
434
std::vector<float> beta(S*(K+1));
437
if(S0<0) { // initial state not specified
438
for(int i=0;i<S;i++) alpha[0*S+i]=0;
441
for(int i=0;i<S;i++) alpha[0*S+i]=INF;
445
for(int k=0;k<K;k++) { // forward recursion
447
for(int j=0;j<S;j++) {
449
for(unsigned int i=0;i<PS[j].size();i++) {
451
mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]];
452
minm=(*p2mymin)(minm,mm);
454
alpha[(k+1)*S+j]=minm;
455
if(minm<norm) norm=minm;
458
alpha[(k+1)*S+j]-=norm; // normalize total metrics so they do not explode
461
if(SK<0) { // final state not specified
462
for(int i=0;i<S;i++) beta[K*S+i]=0;
465
for(int i=0;i<S;i++) beta[K*S+i]=INF;
469
for(int k=K-1;k>=0;k--) { // backward recursion
471
for(int j=0;j<S;j++) {
473
for(int i=0;i<I;i++) {
475
mm=beta[(k+1)*S+NS[i0]]+priori[k*I+i]+prioro[k*O+OS[i0]];
476
minm=(*p2mymin)(minm,mm);
479
if(minm<norm) norm=minm;
482
beta[k*S+j]-=norm; // normalize total metrics so they do not explode
488
for(int k=0;k<K;k++) { // input combining
490
for(int i=0;i<I;i++) {
492
for(int j=0;j<S;j++) {
493
mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]];
494
minm=(*p2mymin)(minm,mm);
496
post[k*(I+O)+i]=minm;
497
if(minm<norm) norm=minm;
500
post[k*(I+O)+i]-=norm; // normalize metrics
504
for(int k=0;k<K;k++) { // output combining
506
for(int n=0;n<O;n++) {
508
for(int j=0;j<S;j++) {
509
for(int i=0;i<I;i++) {
510
mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF);
511
minm=(*p2mymin)(minm,mm);
514
post[k*(I+O)+I+n]=minm;
515
if(minm<norm) norm=minm;
518
post[k*(I+O)+I+n]-=norm; // normalize metrics
523
for(int k=0;k<K;k++) { // input combining
525
for(int i=0;i<I;i++) {
527
for(int j=0;j<S;j++) {
528
mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]];
529
minm=(*p2mymin)(minm,mm);
532
if(minm<norm) norm=minm;
535
post[k*I+i]-=norm; // normalize metrics
540
for(int k=0;k<K;k++) { // output combining
542
for(int n=0;n<O;n++) {
544
for(int j=0;j<S;j++) {
545
for(int i=0;i<I;i++) {
546
mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF);
547
minm=(*p2mymin)(minm,mm);
551
if(minm<norm) norm=minm;
554
post[k*O+n]-=norm; // normalize metrics
558
throw std::runtime_error ("Not both POSTI and POSTO can be false.");
563
//===========================================================
566
void siso_algorithm_combined(int I, int S, int O,
567
const std::vector<int> &NS,
568
const std::vector<int> &OS,
569
const std::vector< std::vector<int> > &PS,
570
const std::vector< std::vector<int> > &PI,
573
bool POSTI, bool POSTO,
574
float (*p2mymin)(float,float),
576
const std::vector<T> &TABLE,
577
trellis_metric_type_t TYPE,
578
const float *priori, const T *observations, float *post
582
std::vector<float> alpha(S*(K+1));
583
std::vector<float> beta(S*(K+1));
584
float *prioro = new float[O*K];
587
if(S0<0) { // initial state not specified
588
for(int i=0;i<S;i++) alpha[0*S+i]=0;
591
for(int i=0;i<S;i++) alpha[0*S+i]=INF;
595
for(int k=0;k<K;k++) { // forward recursion
596
calc_metric(O, D, TABLE, &(observations[k*D]), &(prioro[k*O]),TYPE); // calc metrics
598
for(int j=0;j<S;j++) {
600
for(unsigned int i=0;i<PS[j].size();i++) {
602
mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]];
603
minm=(*p2mymin)(minm,mm);
605
alpha[(k+1)*S+j]=minm;
606
if(minm<norm) norm=minm;
609
alpha[(k+1)*S+j]-=norm; // normalize total metrics so they do not explode
612
if(SK<0) { // final state not specified
613
for(int i=0;i<S;i++) beta[K*S+i]=0;
616
for(int i=0;i<S;i++) beta[K*S+i]=INF;
620
for(int k=K-1;k>=0;k--) { // backward recursion
622
for(int j=0;j<S;j++) {
624
for(int i=0;i<I;i++) {
626
mm=beta[(k+1)*S+NS[i0]]+priori[k*I+i]+prioro[k*O+OS[i0]];
627
minm=(*p2mymin)(minm,mm);
630
if(minm<norm) norm=minm;
633
beta[k*S+j]-=norm; // normalize total metrics so they do not explode
639
for(int k=0;k<K;k++) { // input combining
641
for(int i=0;i<I;i++) {
643
for(int j=0;j<S;j++) {
644
mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]];
645
minm=(*p2mymin)(minm,mm);
647
post[k*(I+O)+i]=minm;
648
if(minm<norm) norm=minm;
651
post[k*(I+O)+i]-=norm; // normalize metrics
655
for(int k=0;k<K;k++) { // output combining
657
for(int n=0;n<O;n++) {
659
for(int j=0;j<S;j++) {
660
for(int i=0;i<I;i++) {
661
mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF);
662
minm=(*p2mymin)(minm,mm);
665
post[k*(I+O)+I+n]=minm;
666
if(minm<norm) norm=minm;
669
post[k*(I+O)+I+n]-=norm; // normalize metrics
674
for(int k=0;k<K;k++) { // input combining
676
for(int i=0;i<I;i++) {
678
for(int j=0;j<S;j++) {
679
mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]];
680
minm=(*p2mymin)(minm,mm);
683
if(minm<norm) norm=minm;
686
post[k*I+i]-=norm; // normalize metrics
691
for(int k=0;k<K;k++) { // output combining
693
for(int n=0;n<O;n++) {
695
for(int j=0;j<S;j++) {
696
for(int i=0;i<I;i++) {
697
mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF);
698
minm=(*p2mymin)(minm,mm);
702
if(minm<norm) norm=minm;
705
post[k*O+n]-=norm; // normalize metrics
709
throw std::runtime_error ("Not both POSTI and POSTO can be false.");
718
void siso_algorithm_combined<short>(int I, int S, int O,
719
const std::vector<int> &NS,
720
const std::vector<int> &OS,
721
const std::vector< std::vector<int> > &PS,
722
const std::vector< std::vector<int> > &PI,
725
bool POSTI, bool POSTO,
726
float (*p2mymin)(float,float),
728
const std::vector<short> &TABLE,
729
trellis_metric_type_t TYPE,
730
const float *priori, const short *observations, float *post
734
void siso_algorithm_combined<int>(int I, int S, int O,
735
const std::vector<int> &NS,
736
const std::vector<int> &OS,
737
const std::vector< std::vector<int> > &PS,
738
const std::vector< std::vector<int> > &PI,
741
bool POSTI, bool POSTO,
742
float (*p2mymin)(float,float),
744
const std::vector<int> &TABLE,
745
trellis_metric_type_t TYPE,
746
const float *priori, const int *observations, float *post
750
void siso_algorithm_combined<float>(int I, int S, int O,
751
const std::vector<int> &NS,
752
const std::vector<int> &OS,
753
const std::vector< std::vector<int> > &PS,
754
const std::vector< std::vector<int> > &PI,
757
bool POSTI, bool POSTO,
758
float (*p2mymin)(float,float),
760
const std::vector<float> &TABLE,
761
trellis_metric_type_t TYPE,
762
const float *priori, const float *observations, float *post
766
void siso_algorithm_combined<gr_complex>(int I, int S, int O,
767
const std::vector<int> &NS,
768
const std::vector<int> &OS,
769
const std::vector< std::vector<int> > &PS,
770
const std::vector< std::vector<int> > &PI,
773
bool POSTI, bool POSTO,
774
float (*p2mymin)(float,float),
776
const std::vector<gr_complex> &TABLE,
777
trellis_metric_type_t TYPE,
778
const float *priori, const gr_complex *observations, float *post
781
//=========================================================
783
template<class Ti, class To>
784
void sccc_decoder_combined(
785
const fsm &FSMo, int STo0, int SToK,
786
const fsm &FSMi, int STi0, int STiK,
787
const interleaver &INTERLEAVER, int blocklength, int iterations,
788
float (*p2mymin)(float,float),
789
int D, const std::vector<Ti> &TABLE,
790
trellis_metric_type_t METRIC_TYPE,
792
const Ti *observations, To *data
796
//allocate space for priori, prioro and posti of inner FSM
797
std::vector<float> ipriori(blocklength*FSMi.I(),0.0);
798
std::vector<float> iprioro(blocklength*FSMi.O());
799
std::vector<float> iposti(blocklength*FSMi.I());
801
//allocate space for priori, prioro and posto of outer FSM
802
std::vector<float> opriori(blocklength*FSMo.I(),0.0);
803
std::vector<float> oprioro(blocklength*FSMo.O());
804
std::vector<float> oposti(blocklength*FSMo.I());
805
std::vector<float> oposto(blocklength*FSMo.O());
807
// turn observations to neg-log-priors
808
for(int k=0;k<blocklength;k++) {
809
calc_metric(FSMi.O(), D, TABLE, &(observations[k*D]), &(iprioro[k*FSMi.O()]),METRIC_TYPE);
810
iprioro[k*FSMi.O()] *= scaling;
813
for(int rep=0;rep<iterations;rep++) {
815
siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(),
816
FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(),
821
&(ipriori[0]), &(iprioro[0]), &(iposti[0])
824
//interleave soft info inner -> outer
825
for(int k=0;k<blocklength;k++) {
826
int ki = INTERLEAVER.DEINTER()[k];
827
//for(int i=0;i<FSMi.I();i++) {
828
//oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i];
830
memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float));
835
if(rep<iterations-1) { // do not produce posti
836
siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(),
837
FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(),
842
&(opriori[0]), &(oprioro[0]), &(oposto[0])
845
//interleave soft info outer --> inner
846
for(int k=0;k<blocklength;k++) {
847
int ki = INTERLEAVER.DEINTER()[k];
848
//for(int i=0;i<FSMi.I();i++) {
849
//ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i];
851
memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float));
854
else // produce posti but not posto
856
siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(),
857
FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(),
862
&(opriori[0]), &(oprioro[0]), &(oposti[0])
866
viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(),
867
FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(),
877
// generate hard decisions
878
for(int k=0;k<blocklength;k++) {
881
for(int i=0;i<FSMo.I();i++) {
882
if(oposti[k*FSMo.I()+i]<min) {
883
min=oposti[k*FSMo.I()+i];
897
void sccc_decoder_combined<float,unsigned char>(
898
const fsm &FSMo, int STo0, int SToK,
899
const fsm &FSMi, int STi0, int STiK,
900
const interleaver &INTERLEAVER, int blocklength, int iterations,
901
float (*p2mymin)(float,float),
902
int D, const std::vector<float> &TABLE,
903
trellis_metric_type_t METRIC_TYPE,
905
const float *observations, unsigned char *data
909
void sccc_decoder_combined<float,short>(
910
const fsm &FSMo, int STo0, int SToK,
911
const fsm &FSMi, int STi0, int STiK,
912
const interleaver &INTERLEAVER, int blocklength, int iterations,
913
float (*p2mymin)(float,float),
914
int D, const std::vector<float> &TABLE,
915
trellis_metric_type_t METRIC_TYPE,
917
const float *observations, short *data
921
void sccc_decoder_combined<float,int>(
922
const fsm &FSMo, int STo0, int SToK,
923
const fsm &FSMi, int STi0, int STiK,
924
const interleaver &INTERLEAVER, int blocklength, int iterations,
925
float (*p2mymin)(float,float),
926
int D, const std::vector<float> &TABLE,
927
trellis_metric_type_t METRIC_TYPE,
929
const float *observations, int *data
933
void sccc_decoder_combined<gr_complex,unsigned char>(
934
const fsm &FSMo, int STo0, int SToK,
935
const fsm &FSMi, int STi0, int STiK,
936
const interleaver &INTERLEAVER, int blocklength, int iterations,
937
float (*p2mymin)(float,float),
938
int D, const std::vector<gr_complex> &TABLE,
939
trellis_metric_type_t METRIC_TYPE,
941
const gr_complex *observations, unsigned char *data
945
void sccc_decoder_combined<gr_complex,short>(
946
const fsm &FSMo, int STo0, int SToK,
947
const fsm &FSMi, int STi0, int STiK,
948
const interleaver &INTERLEAVER, int blocklength, int iterations,
949
float (*p2mymin)(float,float),
950
int D, const std::vector<gr_complex> &TABLE,
951
trellis_metric_type_t METRIC_TYPE,
953
const gr_complex *observations, short *data
957
void sccc_decoder_combined<gr_complex,int>(
958
const fsm &FSMo, int STo0, int SToK,
959
const fsm &FSMi, int STi0, int STiK,
960
const interleaver &INTERLEAVER, int blocklength, int iterations,
961
float (*p2mymin)(float,float),
962
int D, const std::vector<gr_complex> &TABLE,
963
trellis_metric_type_t METRIC_TYPE,
965
const gr_complex *observations, int *data
970
//=========================================================
974
const fsm &FSMo, int STo0, int SToK,
975
const fsm &FSMi, int STi0, int STiK,
976
const interleaver &INTERLEAVER, int blocklength, int iterations,
977
float (*p2mymin)(float,float),
978
const float *iprioro, T *data
981
//allocate space for priori, and posti of inner FSM
982
std::vector<float> ipriori(blocklength*FSMi.I(),0.0);
983
std::vector<float> iposti(blocklength*FSMi.I());
985
//allocate space for priori, prioro and posto of outer FSM
986
std::vector<float> opriori(blocklength*FSMo.I(),0.0);
987
std::vector<float> oprioro(blocklength*FSMo.O());
988
std::vector<float> oposti(blocklength*FSMo.I());
989
std::vector<float> oposto(blocklength*FSMo.O());
991
for(int rep=0;rep<iterations;rep++) {
993
siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(),
994
FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(),
999
&(ipriori[0]), &(iprioro[0]), &(iposti[0])
1002
//interleave soft info inner -> outer
1003
for(int k=0;k<blocklength;k++) {
1004
int ki = INTERLEAVER.DEINTER()[k];
1005
//for(int i=0;i<FSMi.I();i++) {
1006
//oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i];
1008
memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float));
1013
if(rep<iterations-1) { // do not produce posti
1014
siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(),
1015
FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(),
1020
&(opriori[0]), &(oprioro[0]), &(oposto[0])
1023
//interleave soft info outer --> inner
1024
for(int k=0;k<blocklength;k++) {
1025
int ki = INTERLEAVER.DEINTER()[k];
1026
//for(int i=0;i<FSMi.I();i++) {
1027
//ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i];
1029
memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float));
1032
else {// produce posti but not posto
1034
siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(),
1035
FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(),
1040
&(opriori[0]), &(oprioro[0]), &(oposti[0])
1044
viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(),
1045
FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(),
1055
// generate hard decisions
1056
for(int k=0;k<blocklength;k++) {
1059
for(int i=0;i<FSMo.I();i++) {
1060
if(oposti[k*FSMo.I()+i]<min) {
1061
min=oposti[k*FSMo.I()+i];
1075
void sccc_decoder<unsigned char>(
1076
const fsm &FSMo, int STo0, int SToK,
1077
const fsm &FSMi, int STi0, int STiK,
1078
const interleaver &INTERLEAVER, int blocklength, int iterations,
1079
float (*p2mymin)(float,float),
1080
const float *iprioro, unsigned char *data
1084
void sccc_decoder<short>(
1085
const fsm &FSMo, int STo0, int SToK,
1086
const fsm &FSMi, int STi0, int STiK,
1087
const interleaver &INTERLEAVER, int blocklength, int iterations,
1088
float (*p2mymin)(float,float),
1089
const float *iprioro, short *data
1093
void sccc_decoder<int>(
1094
const fsm &FSMo, int STo0, int SToK,
1095
const fsm &FSMi, int STi0, int STiK,
1096
const interleaver &INTERLEAVER, int blocklength, int iterations,
1097
float (*p2mymin)(float,float),
1098
const float *iprioro, int *data
1102
//====================================================
1106
const fsm &FSM1, int ST10, int ST1K,
1107
const fsm &FSM2, int ST20, int ST2K,
1108
const interleaver &INTERLEAVER, int blocklength, int iterations,
1109
float (*p2mymin)(float,float),
1110
const float *cprioro, T *data
1114
//allocate space for priori, prioro and posti of FSM1
1115
std::vector<float> priori1(blocklength*FSM1.I(),0.0);
1116
std::vector<float> prioro1(blocklength*FSM1.O());
1117
std::vector<float> posti1(blocklength*FSM1.I());
1119
//allocate space for priori, prioro and posti of FSM2
1120
std::vector<float> priori2(blocklength*FSM2.I(),0.0);
1121
std::vector<float> prioro2(blocklength*FSM2.O());
1122
std::vector<float> posti2(blocklength*FSM2.I());
1124
//generate prioro1,2 (metrics are not updated per iteration: this is not the best you can do...)
1125
for (int k=0;k<blocklength;k++) {
1126
//std::cout << k << std::endl;
1127
for(int i=0;i<FSM1.O();i++) {
1128
float x=cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+0];
1129
for(int j=1;j<FSM2.O();j++)
1130
x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+j]);
1131
prioro1[k*FSM1.O()+i]=x;
1132
//std::cout << prioro1[k*FSM1.O()+i] << ", ";
1134
//std::cout << std::endl;
1135
for(int i=0;i<FSM2.O();i++) {
1136
float x=cprioro[k*FSM1.O()*FSM2.O()+0*FSM1.O()+i];
1137
for(int j=1;j<FSM1.O();j++)
1138
x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+j*FSM1.O()+i]);
1139
prioro2[k*FSM2.O()+i]=x;
1143
for(int rep=0;rep<iterations;rep++) {
1145
siso_algorithm(FSM1.I(),FSM1.S(),FSM1.O(),
1146
FSM1.NS(), FSM1.OS(), FSM1.PS(), FSM1.PI(),
1151
&(priori1[0]), &(prioro1[0]), &(posti1[0])
1154
//for(int k=0;k<blocklength;k++){
1155
//for(int i=0;i<FSM1.I();i++)
1156
//std::cout << posti1[k*FSM1.I()+i] << ", ";
1157
//std::cout << std::endl;
1160
//interleave soft info 1 -> 2
1161
for(int k=0;k<blocklength;k++) {
1162
int ki = INTERLEAVER.INTER()[k];
1163
//for(int i=0;i<FSMi.I();i++) {
1164
//oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i];
1166
memcpy(&(priori2[k*FSM2.I()]),&(posti1[ki*FSM1.I()]),FSM1.I()*sizeof(float));
1170
siso_algorithm(FSM2.I(),FSM2.S(),FSM2.O(),
1171
FSM2.NS(), FSM2.OS(), FSM2.PS(), FSM2.PI(),
1176
&(priori2[0]), &(prioro2[0]), &(posti2[0])
1179
//interleave soft info 2 --> 1
1180
for(int k=0;k<blocklength;k++) {
1181
int ki = INTERLEAVER.INTER()[k];
1182
//for(int i=0;i<FSMi.I();i++) {
1183
//ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i];
1185
memcpy(&(priori1[ki*FSM1.I()]),&(posti2[k*FSM2.I()]),FSM1.I()*sizeof(float));
1190
// generate hard decisions
1191
for(int k=0;k<blocklength;k++) {
1192
for(int i=0;i<FSM1.I();i++)
1193
posti1[k*FSM1.I()+i] = (*p2mymin)(priori1[k*FSM1.I()+i],posti1[k*FSM1.I()+i]);
1196
for(int i=0;i<FSM1.I();i++) {
1197
if(posti1[k*FSM1.I()+i]<min) {
1198
min=posti1[k*FSM1.I()+i];
1203
//std::cout << data[k] << ", "<< std::endl;
1205
//std::cout << std::endl;
1212
void pccc_decoder<unsigned char>(
1213
const fsm &FSM1, int ST10, int ST1K,
1214
const fsm &FSM2, int ST20, int ST2K,
1215
const interleaver &INTERLEAVER, int blocklength, int iterations,
1216
float (*p2mymin)(float,float),
1217
const float *cprioro, unsigned char *data
1221
void pccc_decoder<short>(
1222
const fsm &FSM1, int ST10, int ST1K,
1223
const fsm &FSM2, int ST20, int ST2K,
1224
const interleaver &INTERLEAVER, int blocklength, int iterations,
1225
float (*p2mymin)(float,float),
1226
const float *cprioro, short *data
1230
void pccc_decoder<int>(
1231
const fsm &FSM1, int ST10, int ST1K,
1232
const fsm &FSM2, int ST20, int ST2K,
1233
const interleaver &INTERLEAVER, int blocklength, int iterations,
1234
float (*p2mymin)(float,float),
1235
const float *cprioro, int *data
1243
template<class Ti, class To>
1244
void pccc_decoder_combined(
1245
const fsm &FSM1, int ST10, int ST1K,
1246
const fsm &FSM2, int ST20, int ST2K,
1247
const interleaver &INTERLEAVER, int blocklength, int iterations,
1248
float (*p2mymin)(float,float),
1249
int D, const std::vector<Ti> &TABLE,
1250
trellis_metric_type_t METRIC_TYPE,
1252
const Ti *observations, To *data
1256
//allocate space for cprioro
1257
std::vector<float> cprioro(blocklength*FSM1.O()*FSM2.O(),0.0);
1259
//allocate space for priori, prioro and posti of FSM1
1260
std::vector<float> priori1(blocklength*FSM1.I(),0.0);
1261
std::vector<float> prioro1(blocklength*FSM1.O());
1262
std::vector<float> posti1(blocklength*FSM1.I());
1264
//allocate space for priori, prioro and posti of FSM2
1265
std::vector<float> priori2(blocklength*FSM2.I(),0.0);
1266
std::vector<float> prioro2(blocklength*FSM2.O());
1267
std::vector<float> posti2(blocklength*FSM2.I());
1269
// turn observations to neg-log-priors for cprioiro
1270
int O=FSM1.O()*FSM2.O();
1271
for(int k=0;k<blocklength;k++) {
1272
calc_metric(O, D, TABLE, &(observations[k*D]), &(cprioro[k*O]),METRIC_TYPE);
1273
cprioro[k*O] *= scaling;
1276
//generate prioro1,2 (metrics are not updated per iteration: this is not the best you can do...)
1277
for (int k=0;k<blocklength;k++) {
1278
//std::cout << k << std::endl;
1279
for(int i=0;i<FSM1.O();i++) {
1280
float x=cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+0];
1281
for(int j=1;j<FSM2.O();j++)
1282
x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+j]);
1283
prioro1[k*FSM1.O()+i]=x;
1284
//std::cout << prioro1[k*FSM1.O()+i] << ", ";
1286
//std::cout << std::endl;
1287
for(int i=0;i<FSM2.O();i++) {
1288
float x=cprioro[k*FSM1.O()*FSM2.O()+0*FSM1.O()+i];
1289
for(int j=1;j<FSM1.O();j++)
1290
x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+j*FSM1.O()+i]);
1291
prioro2[k*FSM2.O()+i]=x;
1295
for(int rep=0;rep<iterations;rep++) {
1297
siso_algorithm(FSM1.I(),FSM1.S(),FSM1.O(),
1298
FSM1.NS(), FSM1.OS(), FSM1.PS(), FSM1.PI(),
1303
&(priori1[0]), &(prioro1[0]), &(posti1[0])
1306
//for(int k=0;k<blocklength;k++){
1307
//for(int i=0;i<FSM1.I();i++)
1308
//std::cout << posti1[k*FSM1.I()+i] << ", ";
1309
//std::cout << std::endl;
1312
//interleave soft info 1 -> 2
1313
for(int k=0;k<blocklength;k++) {
1314
int ki = INTERLEAVER.INTER()[k];
1315
//for(int i=0;i<FSMi.I();i++) {
1316
//oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i];
1318
memcpy(&(priori2[k*FSM2.I()]),&(posti1[ki*FSM1.I()]),FSM1.I()*sizeof(float));
1322
siso_algorithm(FSM2.I(),FSM2.S(),FSM2.O(),
1323
FSM2.NS(), FSM2.OS(), FSM2.PS(), FSM2.PI(),
1328
&(priori2[0]), &(prioro2[0]), &(posti2[0])
1331
//interleave soft info 2 --> 1
1332
for(int k=0;k<blocklength;k++) {
1333
int ki = INTERLEAVER.INTER()[k];
1334
//for(int i=0;i<FSMi.I();i++) {
1335
//ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i];
1337
memcpy(&(priori1[ki*FSM1.I()]),&(posti2[k*FSM2.I()]),FSM1.I()*sizeof(float));
1342
// generate hard decisions
1343
for(int k=0;k<blocklength;k++) {
1344
for(int i=0;i<FSM1.I();i++)
1345
posti1[k*FSM1.I()+i] = (*p2mymin)(priori1[k*FSM1.I()+i],posti1[k*FSM1.I()+i]);
1348
for(int i=0;i<FSM1.I();i++) {
1349
if(posti1[k*FSM1.I()+i]<min) {
1350
min=posti1[k*FSM1.I()+i];
1355
//std::cout << data[k] << ", "<< std::endl;
1357
//std::cout << std::endl;
1363
void pccc_decoder_combined(
1364
const fsm &FSM1, int ST10, int ST1K,
1365
const fsm &FSM2, int ST20, int ST2K,
1366
const interleaver &INTERLEAVER, int blocklength, int iterations,
1367
float (*p2mymin)(float,float),
1368
int D, const std::vector<float> &TABLE,
1369
trellis_metric_type_t METRIC_TYPE,
1371
const float *observations, unsigned char *data
1376
void pccc_decoder_combined(
1377
const fsm &FSM1, int ST10, int ST1K,
1378
const fsm &FSM2, int ST20, int ST2K,
1379
const interleaver &INTERLEAVER, int blocklength, int iterations,
1380
float (*p2mymin)(float,float),
1381
int D, const std::vector<float> &TABLE,
1382
trellis_metric_type_t METRIC_TYPE,
1384
const float *observations, short *data
1389
void pccc_decoder_combined(
1390
const fsm &FSM1, int ST10, int ST1K,
1391
const fsm &FSM2, int ST20, int ST2K,
1392
const interleaver &INTERLEAVER, int blocklength, int iterations,
1393
float (*p2mymin)(float,float),
1394
int D, const std::vector<float> &TABLE,
1395
trellis_metric_type_t METRIC_TYPE,
1397
const float *observations, int *data
1402
void pccc_decoder_combined(
1403
const fsm &FSM1, int ST10, int ST1K,
1404
const fsm &FSM2, int ST20, int ST2K,
1405
const interleaver &INTERLEAVER, int blocklength, int iterations,
1406
float (*p2mymin)(float,float),
1407
int D, const std::vector<gr_complex> &TABLE,
1408
trellis_metric_type_t METRIC_TYPE,
1410
const gr_complex *observations, unsigned char *data
1415
void pccc_decoder_combined(
1416
const fsm &FSM1, int ST10, int ST1K,
1417
const fsm &FSM2, int ST20, int ST2K,
1418
const interleaver &INTERLEAVER, int blocklength, int iterations,
1419
float (*p2mymin)(float,float),
1420
int D, const std::vector<gr_complex> &TABLE,
1421
trellis_metric_type_t METRIC_TYPE,
1423
const gr_complex *observations, short *data
1428
void pccc_decoder_combined(
1429
const fsm &FSM1, int ST10, int ST1K,
1430
const fsm &FSM2, int ST20, int ST2K,
1431
const interleaver &INTERLEAVER, int blocklength, int iterations,
1432
float (*p2mymin)(float,float),
1433
int D, const std::vector<gr_complex> &TABLE,
1434
trellis_metric_type_t METRIC_TYPE,
1436
const gr_complex *observations, int *data