40 inline double max(
double x,
double y) {
return std::max(x, y); }
45 int Rec_Syst_Conv_Code::calc_state_transition(
const int instate,
const int input, ivec &parity)
47 int i, j, in = 0, temp = (gen_pol_rev(0) & (instate << 1)), parity_temp, parity_bit;
49 for (i = 0; i < K; i++) {
55 parity.set_size(n - 1,
false);
56 for (j = 0; j < (n - 1); j++) {
57 parity_temp = ((instate << 1) + in) & gen_pol_rev(j + 1);
59 for (i = 0; i < K; i++) {
60 parity_bit = (parity_temp & 1) ^ parity_bit;
61 parity_temp = parity_temp >> 1;
63 parity(j) = parity_bit;
65 return in + ((instate << 1) & ((1 << m) - 1));
74 K = constraint_length;
78 gen_pol_rev.set_size(n,
false);
79 for (
int i = 0; i < n; i++) {
84 state_trans.set_size(Nstates, 2,
false);
85 rev_state_trans.set_size(Nstates, 2,
false);
86 output_parity.set_size(Nstates, 2*(n - 1),
false);
87 rev_output_parity.set_size(Nstates, 2*(n - 1),
false);
90 for (s_prim = 0; s_prim < Nstates; s_prim++) {
91 s0 = calc_state_transition(s_prim, 0, p0);
92 state_trans(s_prim, 0) = s0;
93 rev_state_trans(s0, 0) = s_prim;
94 for (j = 0; j < (n - 1); j++) {
95 output_parity(s_prim, 2*j + 0) = p0(j);
96 rev_output_parity(s0, 2*j + 0) = p0(j);
99 s1 = calc_state_transition(s_prim, 1, p1);
100 state_trans(s_prim, 1) = s1;
101 rev_state_trans(s1, 1) = s_prim;
102 for (j = 0; j < (n - 1); j++) {
103 output_parity(s_prim, 2*j + 1) = p1(j);
104 rev_output_parity(s1, 2*j + 1) = p1(j);
126 int i, j,
length = input.size(), target_state;
127 parity_bits.set_size(length + m, n - 1,
false);
128 tail.set_size(m,
false);
131 for (i = 0; i <
length; i++) {
132 for (j = 0; j < (n - 1); j++) {
133 parity_bits(i, j) = output_parity(encoder_state, 2 * j +
int(input(i)));
135 encoder_state = state_trans(encoder_state,
int(input(i)));
139 for (i = 0; i < m; i++) {
140 target_state = (encoder_state << 1) & ((1 << m) - 1);
141 if (state_trans(encoder_state, 0) == target_state) { tail(i) =
bin(0); }
142 else { tail(i) =
bin(1); }
143 for (j = 0; j < (n - 1); j++) {
144 parity_bits(length + i, j) = output_parity(encoder_state, 2 * j +
int(tail(i)));
146 encoder_state = target_state;
153 int i, j,
length = input.size();
154 parity_bits.set_size(length, n - 1,
false);
157 for (i = 0; i <
length; i++) {
158 for (j = 0; j < (n - 1); j++) {
159 parity_bits(i, j) = output_parity(encoder_state, 2 * j +
int(input(i)));
161 encoder_state = state_trans(encoder_state,
int(input(i)));
167 vec &extrinsic_output,
bool in_terminated)
169 double gamma_k_e, nom, den, temp0, temp1, exp_temp0, exp_temp1;
170 int j, s0, s1, k, kk, s, s_prim, s_prim0, s_prim1, block_length = rec_systematic.length();
173 mat alpha(Nstates, block_length + 1);
174 mat beta(Nstates, block_length + 1);
175 mat
gamma(2*Nstates, block_length + 1);
176 vec denom(block_length + 1);
179 extrinsic_output.set_size(block_length,
false);
181 if (in_terminated) { terminated =
true; }
184 for (k = 1; k <= block_length; k++) {
186 for (s_prim = 0; s_prim < Nstates; s_prim++) {
189 for (j = 0; j < (n - 1); j++) {
190 exp_temp0 += 0.5 * Lc * rec_parity(kk, j) * double(1 - 2 * output_parity(s_prim, 2 * j + 0));
191 exp_temp1 += 0.5 * Lc * rec_parity(kk, j) * double(1 - 2 * output_parity(s_prim, 2 * j + 1));
214 gamma(2*s_prim + 0, k) =
trunc_exp(0.5 * (extrinsic_input(kk) + Lc * rec_systematic(kk)) + exp_temp0);
215 gamma(2*s_prim + 1, k) =
trunc_exp(-0.5 * (extrinsic_input(kk) + Lc * rec_systematic(kk)) + exp_temp1);
220 alpha.set_col(0,
zeros(Nstates));
224 for (k = 1; k <= block_length; k++) {
225 for (s = 0; s < Nstates; s++) {
226 s_prim0 = rev_state_trans(s, 0);
227 s_prim1 = rev_state_trans(s, 1);
228 temp0 = alpha(s_prim0, k - 1) *
gamma(2 * s_prim0 + 0, k);
229 temp1 = alpha(s_prim1, k - 1) *
gamma(2 * s_prim1 + 1, k);
230 alpha(s, k) = temp0 + temp1;
231 denom(k) += temp0 + temp1;
233 alpha.set_col(k, alpha.get_col(k) / denom(k));
238 beta.set_col(block_length,
zeros(Nstates));
239 beta(0, block_length) = 1.0;
242 beta.set_col(block_length, alpha.get_col(block_length));
246 for (k = block_length; k >= 2; k--) {
247 for (s_prim = 0; s_prim < Nstates; s_prim++) {
248 s0 = state_trans(s_prim, 0);
249 s1 = state_trans(s_prim, 1);
250 beta(s_prim, k - 1) = (beta(s0, k) *
gamma(2 * s_prim + 0, k)) + (beta(s1, k) *
gamma(2 * s_prim + 1, k));
252 beta.set_col(k - 1, beta.get_col(k - 1) / denom(k));
256 for (k = 1; k <= block_length; k++) {
260 for (s_prim = 0; s_prim < Nstates; s_prim++) {
261 s0 = state_trans(s_prim, 0);
262 s1 = state_trans(s_prim, 1);
265 for (j = 0; j < (n - 1); j++) {
266 exp_temp0 += 0.5 * Lc * rec_parity(kk, j) * double(1 - 2 * output_parity(s_prim, 2 * j + 0));
267 exp_temp1 += 0.5 * Lc * rec_parity(kk, j) * double(1 - 2 * output_parity(s_prim, 2 * j + 1));
271 nom += alpha(s_prim, k - 1) * gamma_k_e * beta(s0, k);
275 den += alpha(s_prim, k - 1) * gamma_k_e * beta(s1, k);
278 extrinsic_output(kk) =
trunc_log(nom / den);
284 const vec &extrinsic_input, vec &extrinsic_output,
bool in_terminated, std::string metric)
286 if (metric ==
"TABLE") {
290 QLLRvec rec_systematic_q = llrcalc.
to_qllr(rec_systematic);
291 QLLRmat rec_parity_q = llrcalc.
to_qllr(rec_parity);
292 QLLRvec extrinsic_input_q = llrcalc.
to_qllr(extrinsic_input);
293 QLLRvec extrinsic_output_q(
length(extrinsic_output));
294 log_decode(rec_systematic_q, rec_parity_q, extrinsic_input_q,
295 extrinsic_output_q, in_terminated);
296 extrinsic_output = llrcalc.
to_double(extrinsic_output_q);
300 double nom, den, exp_temp0, exp_temp1, rp, temp0, temp1;
301 int i, j, s0, s1, k, kk, l, s, s_prim, s_prim0, s_prim1, block_length = rec_systematic.length();
308 it_error(
"Rec_Syst_Conv_Code::log_decode: Illegal metric parameter");
311 mat alpha(Nstates, block_length + 1);
312 mat beta(Nstates, block_length + 1);
313 mat
gamma(2*Nstates, block_length + 1);
314 extrinsic_output.set_size(block_length,
false);
315 vec denom(block_length + 1);
316 for (k = 0; k <= block_length; k++) { denom(k) = -infinity; }
318 if (in_terminated) { terminated =
true; }
322 "Rec_Syst_Conv_Code::log_decode: This function assumes that Lc = 1.0. Please use proper scaling of the input data");
325 for (k = 1; k <= block_length; k++) {
327 for (s_prim = 0; s_prim < Nstates; s_prim++) {
330 for (j = 0; j < (n - 1); j++) {
331 rp = rec_parity(kk, j);
332 if (output_parity(s_prim , 2*j + 0) == 0) { exp_temp0 += rp; }
333 else { exp_temp0 -= rp; }
334 if (output_parity(s_prim , 2*j + 1) == 0) { exp_temp1 += rp; }
335 else { exp_temp1 -= rp; }
337 gamma(2*s_prim + 0, k) = 0.5 * ((extrinsic_input(kk) + rec_systematic(kk)) + exp_temp0);
338 gamma(2*s_prim + 1, k) = -0.5 * ((extrinsic_input(kk) + rec_systematic(kk)) - exp_temp1);
343 for (j = 1; j < Nstates; j++) { alpha(j, 0) = -infinity; }
347 for (k = 1; k <= block_length; k++) {
348 for (s = 0; s < Nstates; s++) {
349 s_prim0 = rev_state_trans(s, 0);
350 s_prim1 = rev_state_trans(s, 1);
351 temp0 = alpha(s_prim0, k - 1) +
gamma(2 * s_prim0 + 0, k);
352 temp1 = alpha(s_prim1, k - 1) +
gamma(2 * s_prim1 + 1, k);
353 alpha(s, k) =
com_log(temp0, temp1);
354 denom(k) =
com_log(alpha(s, k), denom(k));
357 for (l = 0; l < Nstates; l++) { alpha(l, k) -= denom(k); }
362 for (i = 1; i < Nstates; i++) { beta(i, block_length) = -infinity; }
363 beta(0, block_length) = 0.0;
366 beta.set_col(block_length, alpha.get_col(block_length));
370 for (k = block_length; k >= 1; k--) {
371 for (s_prim = 0; s_prim < Nstates; s_prim++) {
372 s0 = state_trans(s_prim, 0);
373 s1 = state_trans(s_prim, 1);
374 beta(s_prim, k - 1) =
com_log(beta(s0, k) +
gamma(2 * s_prim + 0, k) , beta(s1, k) +
gamma(2 * s_prim + 1, k));
377 for (l = 0; l < Nstates; l++) { beta(l, k - 1) -= denom(k); }
381 for (k = 1; k <= block_length; k++) {
385 for (s_prim = 0; s_prim < Nstates; s_prim++) {
386 s0 = state_trans(s_prim, 0);
387 s1 = state_trans(s_prim, 1);
390 for (j = 0; j < (n - 1); j++) {
391 rp = rec_parity(kk, j);
392 if (output_parity(s_prim , 2*j + 0) == 0) { exp_temp0 += rp; }
393 else { exp_temp0 -= rp; }
394 if (output_parity(s_prim , 2*j + 1) == 0) { exp_temp1 += rp; }
395 else { exp_temp1 -= rp; }
397 nom =
com_log(nom, alpha(s_prim, kk) + 0.5 * exp_temp0 + beta(s0, k));
398 den =
com_log(den, alpha(s_prim, kk) + 0.5 * exp_temp1 + beta(s1, k));
400 extrinsic_output(kk) = nom - den;
405 const vec &extrinsic_input, vec &extrinsic_output,
bool in_terminated, std::string metric)
407 if (metric ==
"TABLE") {
408 QLLRvec rec_systematic_q = llrcalc.
to_qllr(rec_systematic);
409 QLLRvec rec_parity_q = llrcalc.
to_qllr(rec_parity);
410 QLLRvec extrinsic_input_q = llrcalc.
to_qllr(extrinsic_input);
411 QLLRvec extrinsic_output_q(
length(extrinsic_output));
412 log_decode_n2(rec_systematic_q, rec_parity_q, extrinsic_input_q,
413 extrinsic_output_q, in_terminated);
414 extrinsic_output = llrcalc.
to_double(extrinsic_output_q);
419 double nom, den, exp_temp0, exp_temp1, rp;
420 int k, kk, l, s, s_prim, s_prim0, s_prim1, block_length = rec_systematic.length();
421 int ext_info_length = extrinsic_input.length();
429 it_error(
"Rec_Syst_Conv_Code::log_decode_n2: Illegal metric parameter");
432 mat alpha(Nstates, block_length + 1);
433 mat beta(Nstates, block_length + 1);
434 mat
gamma(2*Nstates, block_length + 1);
435 extrinsic_output.set_size(ext_info_length,
false);
438 if (in_terminated) { terminated =
true; }
442 "Rec_Syst_Conv_Code::log_decode_n2: This function assumes that Lc = 1.0. Please use proper scaling of the input data");
445 for (s = 1; s < Nstates; s++) { alpha(s, 0) = -infinity; }
449 for (k = 1; k <= block_length; k++) {
451 if (kk < ext_info_length) {
452 ex = 0.5 * (extrinsic_input(kk) + rec_systematic(kk));
455 ex = 0.5 * rec_systematic(kk);
457 rp = 0.5 * rec_parity(kk);
458 for (s = 0; s < Nstates; s++) {
459 s_prim0 = rev_state_trans(s, 0);
460 s_prim1 = rev_state_trans(s, 1);
461 if (output_parity(s_prim0 , 0)) { exp_temp0 = -rp; }
462 else { exp_temp0 = rp; }
463 if (output_parity(s_prim1 , 1)) { exp_temp1 = -rp; }
464 else { exp_temp1 = rp; }
465 gamma(2*s_prim0 , k) = ex + exp_temp0;
466 gamma(2*s_prim1 + 1, k) = -ex + exp_temp1;
467 alpha(s, k) =
com_log(alpha(s_prim0, kk) +
gamma(2 * s_prim0 , k),
468 alpha(s_prim1, kk) +
gamma(2 * s_prim1 + 1, k));
472 for (l = 0; l < Nstates; l++) { alpha(l, k) -=
norm; }
477 for (s = 1; s < Nstates; s++) { beta(s, block_length) = -infinity; }
478 beta(0, block_length) = 0.0;
481 beta.set_col(block_length, alpha.get_col(block_length));
485 for (k = block_length; k >= 1; k--) {
487 for (s_prim = 0; s_prim < Nstates; s_prim++) {
488 beta(s_prim, kk) =
com_log(beta(state_trans(s_prim, 0), k) +
gamma(2 * s_prim, k),
489 beta(state_trans(s_prim, 1), k) +
gamma(2 * s_prim + 1, k));
492 for (l = 0; l < Nstates; l++) { beta(l, k) -=
norm; }
496 for (k = 1; k <= block_length; k++) {
498 if (kk < ext_info_length) {
501 rp = 0.5 * rec_parity(kk);
502 for (s_prim = 0; s_prim < Nstates; s_prim++) {
503 if (output_parity(s_prim , 0)) { exp_temp0 = -rp; }
504 else { exp_temp0 = rp; }
505 if (output_parity(s_prim , 1)) { exp_temp1 = -rp; }
506 else { exp_temp1 = rp; }
507 nom =
com_log(nom, alpha(s_prim, kk) + exp_temp0 + beta(state_trans(s_prim, 0), k));
508 den =
com_log(den, alpha(s_prim, kk) + exp_temp1 + beta(state_trans(s_prim, 1), k));
510 extrinsic_output(kk) = nom - den;
518 const QLLRvec &extrinsic_input,
519 QLLRvec &extrinsic_output,
bool in_terminated)
522 int nom, den, exp_temp0, exp_temp1, rp, temp0, temp1;
523 int i, j, s0, s1, k, kk, l, s, s_prim, s_prim0, s_prim1, block_length = rec_systematic.length();
526 QLLRmat alpha_q(Nstates, block_length + 1);
527 QLLRmat beta_q(Nstates, block_length + 1);
528 QLLRmat gamma_q(2*Nstates, block_length + 1);
529 extrinsic_output.set_size(block_length,
false);
530 QLLRvec denom_q(block_length + 1);
531 for (k = 0; k <= block_length; k++) { denom_q(k) = -QLLR_MAX; }
533 if (in_terminated) { terminated =
true; }
537 "Rec_Syst_Conv_Code::log_decode: This function assumes that Lc = 1.0. Please use proper scaling of the input data");
540 for (k = 1; k <= block_length; k++) {
542 for (s_prim = 0; s_prim < Nstates; s_prim++) {
545 for (j = 0; j < (n - 1); j++) {
546 rp = rec_parity(kk, j);
547 if (output_parity(s_prim , 2*j + 0) == 0) { exp_temp0 += rp; }
548 else { exp_temp0 -= rp; }
549 if (output_parity(s_prim , 2*j + 1) == 0) { exp_temp1 += rp; }
550 else { exp_temp1 -= rp; }
553 gamma_q(2*s_prim + 0, k) = ((extrinsic_input(kk) + rec_systematic(kk)) + exp_temp0) / 2;
554 gamma_q(2*s_prim + 1, k) = - ((extrinsic_input(kk) + rec_systematic(kk)) - exp_temp1) / 2;
559 for (j = 1; j < Nstates; j++) { alpha_q(j, 0) = -QLLR_MAX; }
563 for (k = 1; k <= block_length; k++) {
564 for (s = 0; s < Nstates; s++) {
565 s_prim0 = rev_state_trans(s, 0);
566 s_prim1 = rev_state_trans(s, 1);
567 temp0 = alpha_q(s_prim0, k - 1) + gamma_q(2 * s_prim0 + 0, k);
568 temp1 = alpha_q(s_prim1, k - 1) + gamma_q(2 * s_prim1 + 1, k);
571 alpha_q(s, k) = llrcalc.
jaclog(temp0, temp1);
572 denom_q(k) = llrcalc.
jaclog(alpha_q(s, k), denom_q(k));
575 for (l = 0; l < Nstates; l++) { alpha_q(l, k) -= denom_q(k); }
580 for (i = 1; i < Nstates; i++) { beta_q(i, block_length) = -QLLR_MAX; }
581 beta_q(0, block_length) = 0;
584 beta_q.set_col(block_length, alpha_q.get_col(block_length));
588 for (k = block_length; k >= 1; k--) {
589 for (s_prim = 0; s_prim < Nstates; s_prim++) {
590 s0 = state_trans(s_prim, 0);
591 s1 = state_trans(s_prim, 1);
593 beta_q(s_prim, k - 1) = llrcalc.
jaclog(beta_q(s0, k) + gamma_q(2 * s_prim + 0, k) , beta_q(s1, k) + gamma_q(2 * s_prim + 1, k));
596 for (l = 0; l < Nstates; l++) { beta_q(l, k - 1) -= denom_q(k); }
600 for (k = 1; k <= block_length; k++) {
604 for (s_prim = 0; s_prim < Nstates; s_prim++) {
605 s0 = state_trans(s_prim, 0);
606 s1 = state_trans(s_prim, 1);
609 for (j = 0; j < (n - 1); j++) {
610 rp = rec_parity(kk, j);
611 if (output_parity(s_prim , 2*j + 0) == 0) { exp_temp0 += rp; }
612 else { exp_temp0 -= rp; }
613 if (output_parity(s_prim , 2*j + 1) == 0) { exp_temp1 += rp; }
614 else { exp_temp1 -= rp; }
618 nom = llrcalc.
jaclog(nom, alpha_q(s_prim, kk) + exp_temp0 / 2 + beta_q(s0, k));
619 den = llrcalc.
jaclog(den, alpha_q(s_prim, kk) + exp_temp1 / 2 + beta_q(s1, k));
621 extrinsic_output(kk) = nom - den;
629 const QLLRvec &rec_parity,
630 const QLLRvec &extrinsic_input,
631 QLLRvec &extrinsic_output,
634 int nom, den, exp_temp0, exp_temp1, rp;
635 int k, kk, l, s, s_prim, s_prim0, s_prim1, block_length = rec_systematic.length();
636 int ext_info_length = extrinsic_input.length();
641 QLLRmat alpha_q(Nstates, block_length + 1);
642 QLLRmat beta_q(Nstates, block_length + 1);
643 QLLRmat gamma_q(2*Nstates, block_length + 1);
644 extrinsic_output.set_size(ext_info_length,
false);
647 if (in_terminated) { terminated =
true; }
651 "Rec_Syst_Conv_Code::log_decode_n2: This function assumes that Lc = 1.0. Please use proper scaling of the input data");
654 for (s = 1; s < Nstates; s++) { alpha_q(s, 0) = -QLLR_MAX; }
658 for (k = 1; k <= block_length; k++) {
660 if (kk < ext_info_length) {
661 ex = (extrinsic_input(kk) + rec_systematic(kk)) / 2;
664 ex = rec_systematic(kk) / 2;
666 rp = rec_parity(kk) / 2;
667 for (s = 0; s < Nstates; s++) {
668 s_prim0 = rev_state_trans(s, 0);
669 s_prim1 = rev_state_trans(s, 1);
670 if (output_parity(s_prim0 , 0)) { exp_temp0 = -rp; }
671 else { exp_temp0 = rp; }
672 if (output_parity(s_prim1 , 1)) { exp_temp1 = -rp; }
673 else { exp_temp1 = rp; }
674 gamma_q(2*s_prim0 , k) = ex + exp_temp0;
675 gamma_q(2*s_prim1 + 1, k) = -ex + exp_temp1;
676 alpha_q(s, k) = llrcalc.
jaclog(alpha_q(s_prim0, kk) + gamma_q(2 * s_prim0 , k),
677 alpha_q(s_prim1, kk) + gamma_q(2 * s_prim1 + 1, k));
680 norm = alpha_q(0, k);
681 for (l = 0; l < Nstates; l++) { alpha_q(l, k) -=
norm; }
686 for (s = 1; s < Nstates; s++) { beta_q(s, block_length) = -QLLR_MAX; }
687 beta_q(0, block_length) = 0;
690 beta_q.set_col(block_length, alpha_q.get_col(block_length));
694 for (k = block_length; k >= 1; k--) {
696 for (s_prim = 0; s_prim < Nstates; s_prim++) {
697 beta_q(s_prim, kk) = llrcalc.
jaclog(beta_q(state_trans(s_prim, 0), k) + gamma_q(2 * s_prim, k),
698 beta_q(state_trans(s_prim, 1), k) + gamma_q(2 * s_prim + 1, k));
701 for (l = 0; l < Nstates; l++) { beta_q(l, k) -=
norm; }
705 for (k = 1; k <= block_length; k++) {
707 if (kk < ext_info_length) {
710 rp = rec_parity(kk) / 2;
711 for (s_prim = 0; s_prim < Nstates; s_prim++) {
712 if (output_parity(s_prim , 0)) { exp_temp0 = -rp; }
713 else { exp_temp0 = rp; }
714 if (output_parity(s_prim , 1)) { exp_temp1 = -rp; }
715 else { exp_temp1 = rp; }
716 nom = llrcalc.
jaclog(nom, alpha_q(s_prim, kk) + exp_temp0 + beta_q(state_trans(s_prim, 0), k));
717 den = llrcalc.
jaclog(den, alpha_q(s_prim, kk) + exp_temp1 + beta_q(state_trans(s_prim, 1), k));
719 extrinsic_output(kk) = nom - den;
726 llrcalc = in_llrcalc;