IT++ Logo
punct_convcode.cpp
Go to the documentation of this file.
1
30
31
32namespace itpp
33{
34
35// --------------------- Punctured_Conv_Code --------------------------------
36
37//------- Protected functions -----------------------
38int 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
57int 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
76void 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
97void 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
136void 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
154void Punctured_Convolutional_Code::encode_trunc(const bvec &input, bvec &output)
155{
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
172void 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
190void 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 --------------------------------
210void 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*/
224void 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)
244void 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
291}
292
293// Viterbi decoder using TruncLength (=5*K if not specified)
294void 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
342}
343
344// Decode a block of encoded data where encode_tailbite has been used. Tries all start states.
345void 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*/
404bool 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
516void 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
535node1:
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
572stack:
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
589int 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
636F2:
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
659F4:
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
678F5:
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
690F6:
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
730end:
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
750void 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
General array class.
Definition factory.h:40
double rate
The rate of the code.
Definition convcode.h:429
int next_state(const int instate, const int input)
Next state from instate given the input.
Definition convcode.h:374
void encode_tailbite(const bvec &input, bvec &output)
Encode an input binary vector using tailbiting.
Definition convcode.cpp:692
void encode_tail(const bvec &input, bvec &output)
Encoding that starts and ends in the zero state.
Definition convcode.cpp:662
int K
Constraint length.
Definition convcode.h:413
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
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
void encode_trunc(const bvec &input, bvec &output)
Encode a binary vector starting from the previous encoder state.
Definition convcode.cpp:642
int n
Number of generators.
Definition convcode.h:411
int m
Memory of the encoder.
Definition convcode.h:415
ivec gen_pol_rev
Generator polynomials for the reverse code.
Definition convcode.h:421
virtual void decode_trunc(const vec &received_signal, bvec &output)
Viterbi decoding using truncation of memory (default = 5*K)
Definition convcode.cpp:965
CONVOLUTIONAL_CODE_METHOD cc_method
encoding and decoding method
Definition convcode.h:435
bvec xor_int_table
Auxilary table used by the codec.
Definition convcode.h:431
ivec gen_pol
Generator polynomials.
Definition convcode.h:419
int fast(Array< ivec > &spectrum, int time, int dfree, int no_terms, int d_best_so_far=0, bool test_catastrophic=false)
Cederwall's fast algorithm.
void decode_trunc(const vec &received_signal, bvec &output)
Viterbi decoding using truncation of memory (default = 5*K)
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.
void encode_trunc(const bvec &input, bvec &output)
Encode a binary vector of inputs starting from state set by the set_state function.
void encode(const bvec &input, bvec &output)
Encode a binary vector of inputs using specified method.
bmat puncture_matrix
The puncture matrix (n rows and Period columns)
void calculate_spectrum(Array< ivec > &spectrum, int dmax, int no_terms)
Calculate spectrum.
void encode_tailbite(const bvec &input, bvec &output)
Encode a binary vector of inputs using tailbiting.
int total
The number of "1" in the puncture matrix.
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.
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.
void decode_tail(const vec &received_signal, bvec &output)
Decode a block of encoded data where encode_tail has been used.
bool catastrophic(void)
Check if the code is catastrophic. Returns true if catastrophic.
void encode_tail(const bvec &input, bvec &output)
Encoding that begins and ends in the zero state.
int Period
The puncture period (i.e. the number of columns in the puncture matrix)
virtual void decode(const vec &received_signal, bvec &output)
Viterbi decoding using specified method.
void set_puncture_matrix(const bmat &pmatrix)
Set puncture matrix (size n*Period)
Binary arithmetic (boolean) class.
Definition binary.h:57
#define it_error_if(t, s)
Abort if t is true.
Definition itassert.h:117
#define it_error(s)
Abort unconditionally.
Definition itassert.h:126
#define it_warning(s)
Display a warning message.
Definition itassert.h:173
Vec< T > reverse(const Vec< T > &in)
Reverse the input vector.
Definition matfunc.h:777
vec spectrum(const vec &v, int nfft, int noverlap)
Power spectrum calculation.
Definition sigfun.cpp:267
Mat< bin > bmat
bin matrix
Definition mat.h:508
itpp namespace
Definition itmex.h:37
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
Definitions of a Binary Punctured Convolutional Encoder class.
SourceForge Logo

Generated on Mon Apr 7 2025 07:53:18 for IT++ by Doxygen 1.11.0