IT++ Logo
punct_convcode.cpp
Go to the documentation of this file.
1 
30 
31 
32 namespace itpp
33 {
34 
35 // --------------------- Punctured_Conv_Code --------------------------------
36 
37 //------- Protected functions -----------------------
38 int Punctured_Convolutional_Code::weight(int state, int input, int time)
39 {
40  int i, j, temp, out, w = 0, shiftreg = state;
41 
42  shiftreg = shiftreg | (int(input) << m);
43  for (j = 0; j < n; j++) {
44  if (puncture_matrix(j, time) == bin(1)) {
45  out = 0;
46  temp = shiftreg & gen_pol(j);
47  for (i = 0; i < K; i++) {
48  out ^= (temp & 1);
49  temp = temp >> 1;
50  }
51  w += out;
52  }
53  }
54  return w;
55 }
56 
57 int Punctured_Convolutional_Code::weight_reverse(int state, int input, int time)
58 {
59  int i, j, temp, out, w = 0, shiftreg = state;
60 
61  shiftreg = shiftreg | (int(input) << m);
62  for (j = 0; j < n; j++) {
63  if (puncture_matrix(j, Period - 1 - time) == bin(1)) {
64  out = 0;
65  temp = shiftreg & gen_pol_rev(j);
66  for (i = 0; i < K; i++) {
67  out ^= (temp & 1);
68  temp = temp >> 1;
69  }
70  w += out;
71  }
72  }
73  return w;
74 }
75 
76 void Punctured_Convolutional_Code::weight(int state, int &w0, int &w1, int time)
77 {
78  int i, j, temp, out, shiftreg = state;
79  w0 = 0;
80  w1 = 0;
81 
82  shiftreg = shiftreg | (1 << m);
83  for (j = 0; j < n; j++) {
84  if (puncture_matrix(j, time) == bin(1)) {
85  out = 0;
86  temp = shiftreg & gen_pol(j);
87  for (i = 0; i < m; i++) {
88  out ^= (temp & 1);
89  temp = temp >> 1;
90  }
91  w0 += out;
92  w1 += out ^(temp & 1);
93  }
94  }
95 }
96 
97 void Punctured_Convolutional_Code::weight_reverse(int state, int &w0, int &w1, int time)
98 {
99  int i, j, temp, out, shiftreg = state;
100  w0 = 0;
101  w1 = 0;
102 
103  shiftreg = shiftreg | (1 << m);
104  for (j = 0; j < n; j++) {
105  if (puncture_matrix(j, Period - 1 - time) == bin(1)) {
106  out = 0;
107  temp = shiftreg & gen_pol_rev(j);
108  for (i = 0; i < m; i++) {
109  out ^= (temp & 1);
110  temp = temp >> 1;
111  }
112  w0 += out;
113  w1 += out ^(temp & 1);
114  }
115  }
116 }
117 
118 //------- Public functions -----------------------
119 
121 {
122  it_error_if((pmatrix.rows() != n) || (pmatrix.cols() == 0), "Wrong size of puncture matrix");
123  puncture_matrix = pmatrix;
124  Period = puncture_matrix.cols();
125 
126  int p, j;
127  total = 0;
128 
129  for (j = 0; j < n; j++) {
130  for (p = 0; p < Period; p++)
131  total = total + (int)(puncture_matrix(j, p));
132  }
133  rate = (double)Period / total;
134 }
135 
136 void Punctured_Convolutional_Code::encode(const bvec &input, bvec &output)
137 {
138  switch (cc_method) {
139  case Trunc:
140  encode_trunc(input, output);
141  break;
142  case Tail:
143  encode_tail(input, output);
144  break;
145  case Tailbite:
146  encode_tailbite(input, output);
147  break;
148  default:
149  encode_tail(input, output);
150  break;
151  };
152 }
153 
154 void Punctured_Convolutional_Code::encode_trunc(const bvec &input, bvec &output)
155 {
156  Convolutional_Code::encode_trunc(input, output);
157 
158  int nn = 0, i, p = 0, j;
159 
160  for (i = 0; i < int(output.size() / n); i++) {
161  for (j = 0; j < n; j++) {
162  if (puncture_matrix(j, p) == bin(1)) {
163  output(nn) = output(i * n + j);
164  nn++;
165  }
166  }
167  p = (p + 1) % Period;
168  }
169  output.set_size(nn, true);
170 }
171 
172 void Punctured_Convolutional_Code::encode_tail(const bvec &input, bvec &output)
173 {
174  Convolutional_Code::encode_tail(input, output);
175 
176  int nn = 0, i, p = 0, j;
177 
178  for (i = 0; i < int(output.size() / n); i++) {
179  for (j = 0; j < n; j++) {
180  if (puncture_matrix(j, p) == bin(1)) {
181  output(nn) = output(i * n + j);
182  nn++;
183  }
184  }
185  p = (p + 1) % Period;
186  }
187  output.set_size(nn, true);
188 }
189 
190 void Punctured_Convolutional_Code::encode_tailbite(const bvec &input, bvec &output)
191 {
193 
194  int nn = 0, i, p = 0, j;
195 
196  for (i = 0; i < int(output.size() / n); i++) {
197  for (j = 0; j < n; j++) {
198  if (puncture_matrix(j, p) == bin(1)) {
199  output(nn) = output(i * n + j);
200  nn++;
201  }
202  }
203  p = (p + 1) % Period;
204  }
205  output.set_size(nn, true);
206 }
207 
208 
209 // --------------- Hard-decision decoding is not implemented --------------------------------
210 void Punctured_Convolutional_Code::decode(const bvec &, bvec &)
211 {
212  it_error("Punctured_Convolutional_Code::decode(bvec, bvec); hard-decision decoding is not implemented");
213 }
214 
216 {
217  it_error("Punctured_Convolutional_Code::decode(bvec, bvec); hard-decision decoding is not implemented");
218  return bvec();
219 }
220 
221 /*
222  Decode a block of encoded data using specified method
223 */
224 void Punctured_Convolutional_Code::decode(const vec &received_signal, bvec &output)
225 {
226  switch (cc_method) {
227  case Trunc:
228  decode_trunc(received_signal, output);
229  break;
230  case Tail:
231  decode_tail(received_signal, output);
232  break;
233  case Tailbite:
234  decode_tailbite(received_signal, output);
235  break;
236  default:
237  decode_tail(received_signal, output);
238  break;
239  };
240 }
241 
242 
243 // Viterbi decoder using TruncLength (=5*K if not specified)
244 void Punctured_Convolutional_Code::decode_trunc(const vec &received_signal, bvec &output)
245 {
246  int nn = 0, i = 0, p = received_signal.size() / total, j;
247 
248  int temp_size = p * Period * n;
249  // number of punctured bits in a fraction of the puncture matrix
250  // correcponding to the end of the received_signal vector
251  p = received_signal.size() - p * total;
252  // precise calculation of the number of unpunctured bits
253  // (in the above fraction of the puncture matrix)
254  while (p > 0) {
255  for (j = 0; j < n; j++) {
256  if (puncture_matrix(j, nn) == bin(1))
257  p--;
258  }
259  nn++;
260  }
261  temp_size += n * nn;
262  if (p != 0) {
263  it_warning("Punctured_Convolutional_Code::decode(): Improper length of "
264  "the received punctured block, dummy bits have been added");
265  }
266 
267  vec temp(temp_size);
268  nn = 0;
269  j = 0;
270  p = 0;
271 
272  while (nn < temp.size()) {
273  if ((puncture_matrix(j, p) == bin(1)) && (i < received_signal.size())) {
274  temp(nn) = received_signal(i);
275  i++;
276  }
277  else { // insert dummy symbols with the same contribution for 0 and 1
278  temp(nn) = 0;
279  }
280 
281  nn++;
282  j++;
283 
284  if (j == n) {
285  j = 0;
286  p = (p + 1) % Period;
287  }
288  } // while
289 
290  Convolutional_Code::decode_trunc(temp, output);
291 }
292 
293 // Viterbi decoder using TruncLength (=5*K if not specified)
294 void Punctured_Convolutional_Code::decode_tail(const vec &received_signal, bvec &output)
295 {
296  int nn = 0, i = 0, p = received_signal.size() / total, j;
297 
298  int temp_size = p * Period * n;
299  // number of punctured bits in a fraction of the puncture matrix
300  // correcponding to the end of the received_signal vector
301  p = received_signal.size() - p * total;
302  // precise calculation of the number of unpunctured bits
303  // (in the above fraction of the puncture matrix)
304  while (p > 0) {
305  for (j = 0; j < n; j++) {
306  if (puncture_matrix(j, nn) == bin(1))
307  p--;
308  }
309  nn++;
310  }
311  temp_size += n * nn;
312  if (p != 0) {
313  it_warning("Punctured_Convolutional_Code::decode_tail(): Improper length "
314  "of the received punctured block, dummy bits have been added");
315  }
316 
317  vec temp(temp_size);
318 
319  nn = 0;
320  j = 0;
321  p = 0;
322 
323  while (nn < temp.size()) {
324  if ((puncture_matrix(j, p) == bin(1)) && (i < received_signal.size())) {
325  temp(nn) = received_signal(i);
326  i++;
327  }
328  else { // insert dummy symbols with same contribution for 0 and 1
329  temp(nn) = 0;
330  }
331 
332  nn++;
333  j++;
334 
335  if (j == n) {
336  j = 0;
337  p = (p + 1) % Period;
338  }
339  } // while
340 
341  Convolutional_Code::decode_tail(temp, output);
342 }
343 
344 // Decode a block of encoded data where encode_tailbite has been used. Tries all start states.
345 void Punctured_Convolutional_Code::decode_tailbite(const vec &received_signal, bvec &output)
346 {
347  int nn = 0, i = 0, p = received_signal.size() / total, j;
348 
349  int temp_size = p * Period * n;
350  // number of punctured bits in a fraction of the puncture matrix
351  // correcponding to the end of the received_signal vector
352  p = received_signal.size() - p * total;
353  // precise calculation of the number of unpunctured bits
354  // (in the above fraction of the puncture matrix)
355  while (p > 0) {
356  for (j = 0; j < n; j++) {
357  if (puncture_matrix(j, nn) == bin(1))
358  p--;
359  }
360  nn++;
361  }
362  temp_size += n * nn;
363  if (p != 0) {
364  it_warning("Punctured_Convolutional_Code::decode_tailbite(): Improper "
365  "length of the received punctured block, dummy bits have been "
366  "added");
367  }
368 
369  vec temp(temp_size);
370 
371  nn = 0;
372  j = 0;
373  p = 0;
374 
375  while (nn < temp.size()) {
376  if ((puncture_matrix(j, p) == bin(1)) && (i < received_signal.size())) {
377  temp(nn) = received_signal(i);
378  i++;
379  }
380  else { // insert dummy symbols with same contribution for 0 and 1
381  temp(nn) = 0;
382  }
383 
384  nn++;
385  j++;
386 
387  if (j == n) {
388  j = 0;
389  p = (p + 1) % Period;
390  }
391  } // while
392 
394 }
395 
396 
397 /*
398  Calculate the inverse sequence
399 
400  Assumes that encode_tail is used in the encoding process. Returns false if there is an
401  error in the coded sequence (not a valid codeword). Does not check that the tail forces
402  the encoder into the zeroth state.
403 */
404 bool Punctured_Convolutional_Code::inverse_tail(const bvec coded_sequence, bvec &input)
405 {
406  int state = 0, zero_state, one_state, zero_temp, one_temp, i, j, p = 0, prev_pos = 0, no_symbols;
407  int block_length = 0;
408  bvec zero_output(n), one_output(n), temp_output(n);
409 
410  block_length = coded_sequence.size() * Period / total - m;
411 
412  it_error_if(block_length <= 0, "The input sequence is to short");
413  input.set_length(block_length, false); // not include the tail in the output
414 
415  p = 0;
416 
417  for (i = 0; i < block_length; i++) {
418  zero_state = state;
419  one_state = state | (1 << m);
420  no_symbols = 0;
421  for (j = 0; j < n; j++) {
422  if (puncture_matrix(j, p) == bin(1)) {
423  zero_temp = zero_state & gen_pol(j);
424  one_temp = one_state & gen_pol(j);
425  zero_output(no_symbols) = xor_int_table(zero_temp);
426  one_output(no_symbols) = xor_int_table(one_temp);
427  no_symbols++;
428  }
429  }
430  if (coded_sequence.mid(prev_pos, no_symbols) == zero_output.left(no_symbols)) {
431  input(i) = bin(0);
432  state = zero_state >> 1;
433  }
434  else if (coded_sequence.mid(prev_pos, no_symbols) == one_output.left(no_symbols)) {
435  input(i) = bin(1);
436  state = one_state >> 1;
437  }
438  else
439  return false;
440 
441  prev_pos += no_symbols;
442  p = (p + 1) % Period;
443  }
444 
445  return true;
446 }
447 
448 
449 
450 
451 /*
452  It is possible to do this more efficiently by registrating all (inputs,states,Periods)
453  that has zero metric (just and with the generators). After that build paths from a input=1 state.
454 */
456 {
457  int max_stack_size = 50000;
458  ivec S_stack(max_stack_size), t_stack(max_stack_size);
459  int start, S, W0, W1, S0, S1, pos, t = 0;
460  int stack_pos = -1;
461 
462  for (pos = 0; pos < Period; pos++) { // test all start positions
463  for (start = 0; start < (1 << m); start++) {
464  stack_pos = -1;
465  S = start;
466  t = 0;
467 
468  node1:
469  if (t > (1 << m) * Period) { return true; }
470  S0 = next_state(S, 0);
471  S1 = next_state(S, 1);
472  weight(S, W0, W1, (pos + t) % Period);
473  if (W1 > 0) { goto node0; }
474  if ((W0 == 0) && (S0 == start) && (((pos + t + 1) % Period) == pos)) { return true; }
475  if ((W0 == 0) && (S0 == 0) && (S != 0)) { return true; }
476  if ((S0 != 0) && (W0 == 0)) {
477  stack_pos++;
478  if (stack_pos >= max_stack_size) {
479  max_stack_size = 2 * max_stack_size;
480  S_stack.set_size(max_stack_size, true);
481  t_stack.set_size(max_stack_size, true);
482  }
483  S_stack(stack_pos) = S0;
484  t_stack(stack_pos) = t + 1;
485  }
486  if ((W1 == 0) && (S1 == start) && (((pos + t + 1) % Period) == pos)) { return true; }
487  S = S1;
488  t++;
489  goto node1;
490 
491  node0:
492  if (W0 > 0) goto stack;
493  if ((W0 == 0) && (S0 == start) && (((pos + t + 1) % Period) == pos)) { return true; }
494  if ((W0 == 0) && (S0 == 0) && (S != 0)) { return true; }
495  if (S0 != 0) {
496  S = S0;
497  t++;
498  goto node1;
499  }
500  else {
501  goto stack;
502  }
503 
504  stack:
505  if (stack_pos >= 0) {
506  S = S_stack(stack_pos);
507  t = t_stack(stack_pos);
508  stack_pos--;
509  goto node1;
510  }
511  }
512  }
513  return false;
514 }
515 
516 void Punctured_Convolutional_Code::distance_profile(ivec &dist_prof, int start_time, int dmax, bool reverse)
517 {
518  int max_stack_size = 50000;
519  ivec S_stack(max_stack_size), W_stack(max_stack_size), t_stack(max_stack_size);
520 
521  int stack_pos = -1, t, S, W, W0, w0, w1;
522 
523 
524  dist_prof.zeros();
525  dist_prof += dmax; // just select a big number!
526  if (reverse)
527  W = weight_reverse(0, 1, start_time);
528  else
529  W = weight(0, 1, start_time);
530 
531  S = next_state(0, 1); // start from zero state and a one input
532  t = 0;
533  dist_prof(0) = W;
534 
535 node1:
536  if (reverse)
537  weight_reverse(S, w0, w1, (start_time + t + 1) % Period);
538  else
539  weight(S, w0, w1, (start_time + t + 1) % Period);
540 
541  if (t < m) {
542  W0 = W + w0;
543  if (W0 < dist_prof(m)) { // store node0 (S, W0, and t+1)
544  stack_pos++;
545  if (stack_pos >= max_stack_size) {
546  max_stack_size = 2 * max_stack_size;
547  S_stack.set_size(max_stack_size, true);
548  W_stack.set_size(max_stack_size, true);
549  t_stack.set_size(max_stack_size, true);
550  }
551  S_stack(stack_pos) = next_state(S, 0);
552  W_stack(stack_pos) = W0;
553  t_stack(stack_pos) = t + 1;
554  }
555  }
556  else goto stack;
557 
558  W += w1;
559  if (W > dist_prof(m))
560  goto stack;
561 
562  t++;
563  S = next_state(S, 1);
564 
565  if (W < dist_prof(t))
566  dist_prof(t) = W;
567 
568  if (t == m) goto stack;
569  goto node1;
570 
571 
572 stack:
573  if (stack_pos >= 0) {
574  // get root node from stack
575  S = S_stack(stack_pos);
576  W = W_stack(stack_pos);
577  t = t_stack(stack_pos);
578  stack_pos--;
579 
580  if (W < dist_prof(t))
581  dist_prof(t) = W;
582 
583  if (t == m) goto stack;
584 
585  goto node1;
586  }
587 }
588 
589 int Punctured_Convolutional_Code::fast(Array<ivec> &spectrum, int start_time, int dfree, int no_terms,
590  int d_best_so_far, bool test_catastrophic)
591 {
592  int cat_treshold = (1 << m) * Period;
593  int i, j, t = 0;
594  ivec dist_prof(K), dist_prof_rev(K), dist_prof_temp(K);
595 
596  //calculate distance profile
597  distance_profile(dist_prof, start_time, dfree);
598  distance_profile(dist_prof_rev, 0, dfree, true); // for the reverse code
599 
600  int dist_prof_rev0 = dist_prof_rev(0);
601 
602  bool reverse = true; // true = use reverse dist_prof
603 
604  // choose the lowest dist_prof over all periods
605  for (i = 1; i < Period; i++) {
606  distance_profile(dist_prof_temp, i, dfree, true);
607  // switch if new is lower
608  for (j = 0; j < K; j++) {
609  if (dist_prof_temp(j) < dist_prof_rev(j)) {
610  dist_prof_rev(j) = dist_prof_temp(j);
611  }
612  }
613  }
614 
615  dist_prof_rev0 = dist_prof(0);
616  dist_prof = dist_prof_rev;
617 
618  int d = dfree + no_terms - 1;
619  int max_stack_size = 50000;
620  ivec S_stack(max_stack_size), W_stack(max_stack_size), b_stack(max_stack_size);
621  ivec c_stack(max_stack_size), t_stack(max_stack_size);
622  int stack_pos = -1;
623 
624  // F1.
625  int mf = 1, b = 1;
626  spectrum.set_size(2);
627  spectrum(0).set_size(dfree + no_terms, 0); // ad
628  spectrum(1).set_size(dfree + no_terms, 0); // cd
629  spectrum(0).zeros();
630  spectrum(1).zeros();
631  int S, S0, S1, W0, W1, w0, w1, c = 0;
632  S = next_state(0, 1); // start in zero state and one input
633  int W = d - dist_prof_rev0;
634  t = 1;
635 
636 F2:
637  S0 = next_state(S, 0);
638  S1 = next_state(S, 1);
639 
640  if (reverse) {
641  weight(S, w0, w1, (start_time + t) % Period);
642  }
643  else {
644  weight_reverse(S, w0, w1, (start_time + t) % Period);
645  }
646  W0 = W - w0;
647  W1 = W - w1;
648 
649  if (mf < m) goto F6;
650 
651  //F3:
652  if (W0 >= 0) {
653  spectrum(0)(d - W0)++;
654  spectrum(1)(d - W0) += b;
655  }
656  //Test on d_best_so_far
657  if ((d - W0) < d_best_so_far) { return -1; }
658 
659 F4:
660  if ((W1 < dist_prof(m - 1)) || (W < dist_prof(m))) goto F5;
661  // select node 1
662  if (test_catastrophic && (W == W1)) {
663  c++;
664  if (c > cat_treshold)
665  return 0;
666  }
667  else {
668  c = 0;
669  }
670 
671  W = W1;
672  S = S1;
673  t++;
674  mf = 1;
675  b++;
676  goto F2;
677 
678 F5:
679  if (stack_pos == -1) goto end;
680  // get node from stack
681  S = S_stack(stack_pos);
682  W = W_stack(stack_pos);
683  b = b_stack(stack_pos);
684  c = c_stack(stack_pos);
685  t = t_stack(stack_pos);
686  stack_pos--;
687  mf = 1;
688  goto F2;
689 
690 F6:
691  if (W0 < dist_prof(m - mf - 1)) goto F4;
692 
693  //F7:
694  if ((W1 >= dist_prof(m - 1)) && (W >= dist_prof(m))) {
695  // save node 1
696  if (test_catastrophic && (stack_pos > 40000))
697  return 0;
698 
699  stack_pos++;
700  if (stack_pos >= max_stack_size) {
701  max_stack_size = 2 * max_stack_size;
702  S_stack.set_size(max_stack_size, true);
703  W_stack.set_size(max_stack_size, true);
704  b_stack.set_size(max_stack_size, true);
705  c_stack.set_size(max_stack_size, true);
706  t_stack.set_size(max_stack_size, true);
707  }
708  S_stack(stack_pos) = S1;
709  W_stack(stack_pos) = W1;
710  b_stack(stack_pos) = b + 1; // because gone to node 1
711  c_stack(stack_pos) = c;
712  t_stack(stack_pos) = t + 1;
713  }
714  // select node 0
715  S = S0;
716  t++;
717  if (test_catastrophic && (W == W0)) {
718  c++;
719  if (c > cat_treshold)
720  return false;
721  }
722  else {
723  c = 0;
724  }
725 
726  W = W0;
727  mf++;
728  goto F2;
729 
730 end:
731  return 1;
732 }
733 
735 {
736  Array<ivec> temp_spectra(2);
737  spectrum.set_size(2);
738  spectrum(0).set_size(dmax + no_terms, false);
739  spectrum(1).set_size(dmax + no_terms, false);
740  spectrum(0).zeros();
741  spectrum(1).zeros();
742 
743  for (int pos = 0; pos < Period; pos++) {
744  calculate_spectrum(temp_spectra, pos, dmax, no_terms);
745  spectrum(0) += temp_spectra(0);
746  spectrum(1) += temp_spectra(1);
747  }
748 }
749 
750 void Punctured_Convolutional_Code::calculate_spectrum(Array<ivec> &spectrum, int time, int dmax, int no_terms, int block_length)
751 {
752  imat Ad_states(1 << (K - 1), dmax + no_terms), Cd_states(1 << m, dmax + no_terms);
753  imat Ad_temp(1 << (K - 1), dmax + no_terms), Cd_temp(1 << m, dmax + no_terms);
754  ivec mindist(1 << (K - 1)), mindist_temp(1 << m);
755 
756  spectrum.set_size(2);
757  spectrum(0).set_size(dmax + no_terms, false);
758  spectrum(1).set_size(dmax + no_terms, false);
759  spectrum(0).zeros();
760  spectrum(1).zeros();
761  Ad_states.zeros();
762  Cd_states.zeros();
763  mindist.zeros();
764  int wmax = dmax + no_terms;
765  ivec visited_states(1 << m), visited_states_temp(1 << m);
766  bool proceede, expand_s1;
767  int t, d, w0, w1, s, s0, s1 = 0, s_start;
768 
769  // initial phase. Evolv trellis up to time K.
770  visited_states.zeros(); // 0 = false
771 
772  s1 = next_state(0, 1); // Start in state 0 and 1 input
773  visited_states(s1) = 1; // 1 = true.
774  w1 = weight(0, 1, time);
775  Ad_states(s1, w1) = 1;
776  Cd_states(s1, w1) = 1;
777  mindist(s1) = w1;
778 
779  if (block_length > 0) {
780  s0 = next_state(0, 0);
781  visited_states(s0) = 1; // 1 = true. Expand also the zero-path
782  w0 = weight(0, 0, time);
783  Ad_states(s0, w0) = 1;
784  Cd_states(s0, w0) = 0;
785  mindist(s0) = w0;
786  s_start = 0;
787  }
788  else {
789  s_start = 1;
790  }
791 
792  t = 1;
793  proceede = true;
794  while (proceede) {
795  proceede = false;
796  Ad_temp.zeros();
797  Cd_temp.zeros();
798  mindist_temp.zeros();
799  visited_states_temp.zeros(); //false
800 
801  for (s = s_start; s < (1 << m); s++) {
802 
803  if (visited_states(s) == 1) {
804  if ((mindist(s) >= 0) && (mindist(s) < wmax)) {
805  proceede = true;
806  weight(s, w0, w1, (time + t) % Period);
807 
808  s0 = next_state(s, 0);
809  for (d = mindist(s); d < (wmax - w0); d++) {
810  Ad_temp(s0, d + w0) += Ad_states(s, d);
811  Cd_temp(s0, d + w0) += Cd_states(s, d);
812  }
813  if (visited_states_temp(s0) == 0) { mindist_temp(s0) = mindist(s) + w0; }
814  else { mindist_temp(s0) = ((mindist(s) + w0) < mindist_temp(s0)) ? mindist(s) + w0 : mindist_temp(s0); }
815  visited_states_temp(s0) = 1; //true
816 
817  expand_s1 = false;
818  if ((block_length == 0) || (t < (block_length - (K - 1)))) {
819  expand_s1 = true;
820  }
821 
822  if (expand_s1) {
823  s1 = next_state(s, 1);
824  for (d = mindist(s); d < (wmax - w1); d++) {
825  Ad_temp(s1, d + w1) += Ad_states(s, d);
826  Cd_temp(s1, d + w1) += Cd_states(s, d) + Ad_states(s, d);
827  }
828  if (visited_states_temp(s1) == 0) { mindist_temp(s1) = mindist(s) + w1; }
829  else { mindist_temp(s1) = ((mindist(s) + w1) < mindist_temp(s1)) ? mindist(s) + w1 : mindist_temp(s1); }
830  visited_states_temp(s1) = 1; //true
831  }
832  }
833  }
834  }
835 
836  Ad_states = Ad_temp;
837  Cd_states = Cd_temp;
838  if (block_length == 0) {
839  spectrum(0) += Ad_temp.get_row(0);
840  spectrum(1) += Cd_temp.get_row(0);
841  }
842  visited_states = visited_states_temp;
843  mindist = elem_mult(mindist_temp, visited_states);
844  t++;
845  if ((t > block_length) && (block_length > 0)) { proceede = false; }
846  }
847 
848  if (block_length > 0) {
849  spectrum(0) = Ad_states.get_row(0);
850  spectrum(1) = Cd_states.get_row(0);
851  }
852 
853 }
854 
855 } // namespace itpp
#define it_error_if(t, s)
Abort if t is true.
Definition: itassert.h:117
void encode_tail(const bvec &input, bvec &output)
Encoding that begins and ends in the zero state.
int K
Constraint length.
Definition: convcode.h:413
void decode_trunc(const vec &received_signal, bvec &output)
Viterbi decoding using truncation of memory (default = 5*K)
Vec< T > reverse(const Vec< T > &in)
Reverse the input vector.
Definition: matfunc.h:777
virtual void decode(const vec &received_signal, bvec &output)
Viterbi decoding using specified method.
Mat< Num_T > elem_mult(const Mat< Num_T > &m1, const Mat< Num_T > &m2)
Element wise multiplication of two matrices.
Definition: mat.h:1582
int total
The number of "1" in the puncture matrix.
bvec xor_int_table
Auxilary table used by the codec.
Definition: convcode.h:431
int next_state(const int instate, const int input)
Next state from instate given the input.
Definition: convcode.h:374
void calculate_spectrum(Array< ivec > &spectrum, int dmax, int no_terms)
Calculate spectrum.
int weight_reverse(const int state, const int input, int time)
Weight of the reverse code from state with input (0 or 1) at transition time.
int fast(Array< ivec > &spectrum, int time, int dfree, int no_terms, int d_best_so_far=0, bool test_catastrophic=false)
Cederwall&#39;s fast algorithm.
virtual void decode_tailbite(const vec &received_signal, bvec &output)
Decode a block of encoded data where encode_tailbite has been used.
Definition: convcode.cpp:879
void encode_trunc(const bvec &input, bvec &output)
Encode a binary vector starting from the previous encoder state.
Definition: convcode.cpp:642
void encode(const bvec &input, bvec &output)
Encode a binary vector of inputs using specified method.
int m
Memory of the encoder.
Definition: convcode.h:415
bmat puncture_matrix
The puncture matrix (n rows and Period columns)
void encode_tailbite(const bvec &input, bvec &output)
Encode an input binary vector using tailbiting.
Definition: convcode.cpp:692
ivec gen_pol_rev
Generator polynomials for the reverse code.
Definition: convcode.h:421
void encode_trunc(const bvec &input, bvec &output)
Encode a binary vector of inputs starting from state set by the set_state function.
vec spectrum(const vec &v, int nfft, int noverlap)
Power spectrum calculation.
Definition: sigfun.cpp:267
itpp namespace
Definition: itmex.h:36
void decode_tailbite(const vec &received_signal, bvec &output)
Decode a block of encoded data where encode_tailbite has been used. Tries all start states...
int Period
The puncture period (i.e. the number of columns in the puncture matrix)
void decode_tail(const vec &received_signal, bvec &output)
Decode a block of encoded data where encode_tail has been used.
virtual void decode_trunc(const vec &received_signal, bvec &output)
Viterbi decoding using truncation of memory (default = 5*K)
Definition: convcode.cpp:965
void set_puncture_matrix(const bmat &pmatrix)
Set puncture matrix (size n*Period)
#define it_warning(s)
Display a warning message.
Definition: itassert.h:173
double rate
The rate of the code.
Definition: convcode.h:429
int n
Number of generators.
Definition: convcode.h:411
void distance_profile(ivec &dist_prof, int time, int dmax=100000, bool reverse=false)
Calculate distance profile. If reverse = true calculate for the reverse code instead.
int weight(const int state, const int input, int time)
The weight of path from state with input (0 or 1) at transition time.
Binary arithmetic (boolean) class.
Definition: binary.h:56
#define it_error(s)
Abort unconditionally.
Definition: itassert.h:126
bool catastrophic(void)
Check if the code is catastrophic. Returns true if catastrophic.
CONVOLUTIONAL_CODE_METHOD cc_method
encoding and decoding method
Definition: convcode.h:435
void encode_tailbite(const bvec &input, bvec &output)
Encode a binary vector of inputs using tailbiting.
void encode_tail(const bvec &input, bvec &output)
Encoding that starts and ends in the zero state.
Definition: convcode.cpp:662
ivec gen_pol
Generator polynomials.
Definition: convcode.h:419
virtual void decode_tail(const vec &received_signal, bvec &output)
Decode a block of encoded data where encode_tail has been used.
Definition: convcode.cpp:771
Definitions of a Binary Punctured Convolutional Encoder class.
Mat< bin > bmat
bin matrix
Definition: mat.h:508
SourceForge Logo

Generated on Sun Apr 10 2022 12:00:00 for IT++ by Doxygen 1.8.14