37 std::string Turbo_Codec::string_from_metric(
const Turbo_Codec::Metric& in_metric)
39 if(in_metric == Metric::LOGMAX) {
40 return std::string(
"LOGMAX");
43 return std::string(
"LOGMAP");
45 else if(in_metric == Metric::MAP) {
46 return std::string(
"MAP");
48 else if(in_metric == Metric::TABLE) {
49 return std::string(
"TABLE");
52 return std::string(
"UNKNOWN");
56 int in_iterations, std::string in_metric,
double in_logmax_scale_factor,
60 iterations = in_iterations;
61 interleaver_size = interleaver_sequence.size();
62 Nuncoded = interleaver_size;
63 logmax_scale_factor = in_logmax_scale_factor;
64 adaptive_stop = in_adaptive_stop;
67 if(in_metric ==
"LOGMAX") {
68 metric = Metric::LOGMAX;
70 else if(in_metric ==
"LOGMAP") {
73 else if(in_metric ==
"MAP") {
76 else if(in_metric ==
"TABLE") {
77 metric = Metric::TABLE;
80 it_error(
"Turbo_Codec::set_parameters: The decoder metric must be either MAP, LOGMAP, LOGMAX or TABLE");
83 if(logmax_scale_factor != 1.0) {
84 it_assert(metric == Metric::LOGMAX,
"Turbo_Codec::set_parameters: logmax_scale_factor can only be used together with LOGMAX decoding");
90 n1 = gen1.length() - 1;
91 n2 = gen2.length() - 1;
95 m_tail = constraint_length - 1;
98 Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
117 interleaver_size = interleaver_sequence.size();
118 Nuncoded = interleaver_size;
121 Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
132 logmax_scale_factor = in_logmax_scale_factor;
135 if(in_metric ==
"LOGMAX") {
136 metric = Metric::LOGMAX;
138 else if(in_metric ==
"LOGMAP") {
141 else if(in_metric ==
"MAP") {
142 metric = Metric::MAP;
144 else if(in_metric ==
"TABLE") {
145 metric = Metric::TABLE;
148 it_error(
"Turbo_Codec::set_metric: The decoder metric must be either MAP, LOGMAP, LOGMAX or TABLE");
157 iterations = in_iterations;
162 adaptive_stop = in_adaptive_stop;
181 int i, k, j, no_blocks;
183 bvec input_bits, in1, in2, tail1, tail2, out;
184 bmat parity1, parity2;
187 no_blocks = input.length() / Nuncoded;
188 output.set_size(no_blocks * Ncoded,
false);
194 for(i = 0; i < no_blocks; i++) {
197 input_bits = input.mid(i * Nuncoded, Nuncoded);
201 for(k = 0; k < Nuncoded; k++) {
202 output(count) = in1(k);
204 for(j = 0; j < n1; j++) { output(count) = parity1(k, j); count++; }
205 for(j = 0; j < n2; j++) { output(count) = parity2(k, j); count++; }
209 for(k = 0; k < m_tail; k++) {
210 output(count) = in1(Nuncoded + k);
212 for(j = 0; j < n1; j++) { output(count) = parity1(Nuncoded + k, j); count++; }
216 for(k = 0; k < m_tail; k++) {
217 output(count) = in2(Nuncoded + k);
219 for(j = 0; j < n2; j++) { output(count) = parity2(Nuncoded + k, j); count++; }
228 ivec nrof_used_iterations;
229 decode(received_signal, decoded_bits, nrof_used_iterations, true_bits);
233 const bvec &true_bits)
236 if((n1 == 1) && (n2 == 1) && (metric != Metric::MAP)) {
238 decode_n3(received_signal, decoded_bits, nrof_used_iterations, true_bits);
243 vec rec, rec_syst1, rec_syst2;
244 mat rec_parity1, rec_parity2;
246 int no_blocks, i, j, k, nrof_used_iterations_i;
248 bool CHECK_TRUE_BITS;
251 no_blocks = received_signal.length() / Ncoded;
252 decoded_bits.set_size(no_blocks * Nuncoded,
false);
253 decoded_bits_i.set_size(iterations, no_blocks * Nuncoded,
false);
254 rec_syst1.set_size(Nuncoded + m_tail,
false);
255 rec_syst2.set_size(Nuncoded + m_tail,
false);
257 rec_parity1.set_size(Nuncoded + m_tail, n1,
false);
258 rec_parity2.set_size(Nuncoded + m_tail, n2,
false);
259 nrof_used_iterations.set_size(no_blocks,
false);
262 if(true_bits.size() > 1) {
263 it_assert(true_bits.size() == (Nuncoded * no_blocks),
"Turbo_Codec::decode: Wrong size of input vectors");
264 CHECK_TRUE_BITS =
true;
267 CHECK_TRUE_BITS =
false;
274 for(i = 0; i < no_blocks; i++) {
277 for(k = 0; k < Nuncoded; k++) {
278 rec_syst1(k) = received_signal(count);
280 for(j = 0; j < n1; j++) { rec_parity1(k, j) = received_signal(count); count++; }
281 for(j = 0; j < n2; j++) { rec_parity2(k, j) = received_signal(count); count++; }
285 for(k = 0; k < m_tail; k++) {
286 rec_syst1(Nuncoded + k) = received_signal(count);
288 for(j = 0; j < n1; j++) { rec_parity1(Nuncoded + k, j) = received_signal(count); count++; }
292 for(k = 0; k < m_tail; k++) {
293 rec_syst2(Nuncoded + k) = received_signal(count);
295 for(j = 0; j < n2; j++) { rec_parity2(Nuncoded + k, j) = received_signal(count); count++; }
307 if(CHECK_TRUE_BITS) {
308 decode_block(rec_syst1, rec_syst2, rec_parity1, rec_parity2, decoded_bits_i,
309 nrof_used_iterations_i, true_bits.mid(i * Nuncoded, Nuncoded));
310 nrof_used_iterations(i) = nrof_used_iterations_i;
313 decode_block(rec_syst1, rec_syst2, rec_parity1, rec_parity2, decoded_bits_i, nrof_used_iterations_i);
314 nrof_used_iterations(i) = nrof_used_iterations_i;
318 decoded_bits.replace_mid(i * Nuncoded, decoded_bits_i.get_row(iterations - 1));
329 bvec tail1, tail2, interleaved_input;
332 it_assert(input.length() == Nuncoded,
"Turbo_Codec::encode_block: Parameter error in Nuncoded.");
335 tail1.set_size(m_tail,
false);
337 tail2.set_size(m_tail,
false);
339 parity1.set_size(Nuncoded + m_tail, n1,
false);
341 parity2.set_size(Nuncoded + m_tail, n2,
false);
343 interleaved_input.set_size(Nuncoded,
false);
344 interleaved_input.clear();
350 bit_interleaver.
interleave(input, interleaved_input);
353 rscc2.
encode_tail(interleaved_input, tail2, parity2);
356 in1 =
concat(input, tail1);
357 in2 =
concat(interleaved_input, tail2);
362 const mat &rec_parity2,
bmat &decoded_bits_i,
int &nrof_used_iterations_i,
363 const bvec &true_bits)
368 vec extrinsic_input, extrinsic_output, int_rec_syst1, int_rec_syst, tmp;
369 vec deint_rec_syst2, rec_syst, sub_rec_syst, Le12, Le21, Le12_int, Le21_int, L, tail1, tail2;
370 bool CHECK_TRUE_BITS, CONTINUE;
373 decoded_bits_i.set_size(iterations, Nuncoded,
false);
374 Le12.set_size(Nuncoded + m_tail,
false);
375 Le21.set_size(Nuncoded + m_tail,
false);
379 float_interleaver.
interleave(rec_syst1.left(interleaver_size), int_rec_syst1);
380 float_interleaver.
deinterleave(rec_syst2.left(interleaver_size), deint_rec_syst2);
383 rec_syst = rec_syst1.
left(interleaver_size) + deint_rec_syst2;
384 int_rec_syst = rec_syst2.
left(interleaver_size) + int_rec_syst1;
387 tail1 = rec_syst1.
right(m_tail);
388 tail2 = rec_syst2.
right(m_tail);
391 rec_syst =
concat(rec_syst, tail1);
392 int_rec_syst =
concat(int_rec_syst, tail2);
395 if(true_bits.size() > 1) {
396 it_assert(true_bits.size() == Nuncoded,
"Turbo_Codec::decode_block: Illegal size of input vector true_bits");
397 CHECK_TRUE_BITS =
true;
400 CHECK_TRUE_BITS =
false;
403 if(CHECK_TRUE_BITS) {
405 "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
409 nrof_used_iterations_i = iterations;
410 for(i = 0; i < iterations; i++) {
413 if(metric == Metric::MAP) {
414 rscc1.
map_decode(rec_syst, rec_parity1, Le21, Le12,
true);
416 else if((metric == Metric::LOGMAX) || (metric ==
Metric::LOGMAP) || (metric == Metric::TABLE)) {
417 rscc1.
log_decode(rec_syst, rec_parity1, Le21, Le12,
true, string_from_metric(metric));
418 if(logmax_scale_factor != 1.0) {
419 Le12 *= logmax_scale_factor;
423 it_error(
"Turbo_Codec::decode_block: Illegal metric value");
427 float_interleaver.
interleave(Le12.left(interleaver_size), tmp);
428 Le12_int =
concat(tmp,
zeros(Le12.size() - interleaver_size));
431 if(metric == Metric::MAP) {
432 rscc2.
map_decode(int_rec_syst, rec_parity2, Le12_int, Le21_int,
true);
434 else if((metric == Metric::LOGMAX) || (metric ==
Metric::LOGMAP) || (metric == Metric::TABLE)) {
435 rscc2.
log_decode(int_rec_syst, rec_parity2, Le12_int, Le21_int,
true, string_from_metric(metric));
436 if(logmax_scale_factor != 1.0) {
437 Le21_int *= logmax_scale_factor;
441 it_error(
"Turbo_Codec::decode_block: Illegal metric value");
445 float_interleaver.
deinterleave(Le21_int.left(interleaver_size), tmp);
446 Le21 =
concat(tmp,
zeros(Le21_int.size() - interleaver_size));
449 L = rec_syst + Le21 + Le12;
451 for(l = 0; l < Nuncoded; l++) {
452 (L(l) > 0.0) ? (decoded_bits_i(i, count) =
bin(0)) : (decoded_bits_i(i, count) =
bin(1));
458 if(i < (iterations - 1)) {
460 if(CHECK_TRUE_BITS) {
462 for(k = 0; k < Nuncoded; k++) {
if(true_bits(k) != decoded_bits_i(i, k)) { CONTINUE =
true;
break; } }
465 if((adaptive_stop) && (i > 0)) {
467 for(k = 0; k < Nuncoded; k++) {
if(decoded_bits_i(i - 1, k) != decoded_bits_i(i, k)) { CONTINUE =
true;
break; } }
473 if(CONTINUE ==
false) {
475 for(k = (i + 1); k < iterations; k++) {
476 decoded_bits_i.set_row(k, decoded_bits_i.get_row(i));
477 nrof_used_iterations_i = i + 1;
487 const bvec &true_bits)
490 vec rec, rec_syst1, int_rec_syst1, rec_syst2;
491 vec rec_parity1, rec_parity2;
492 vec extrinsic_input, extrinsic_output, Le12, Le21, Le12_int, Le21_int, L;
493 bvec temp_decoded_bits;
494 int no_blocks, i, j, k, l, nrof_used_iterations_i;
495 int count, count_out;
496 bool CHECK_TRUE_BITS, CONTINUE;
499 no_blocks = received_signal.length() / Ncoded;
500 decoded_bits.set_size(no_blocks * Nuncoded,
false);
501 rec_syst1.set_size(Nuncoded + m_tail,
false);
502 rec_syst2.set_size(Nuncoded + m_tail,
false);
504 rec_parity1.set_size(Nuncoded + m_tail,
false);
505 rec_parity2.set_size(Nuncoded + m_tail,
false);
506 temp_decoded_bits.set_size(Nuncoded,
false);
507 decoded_bits_previous_iteration.set_size(Nuncoded,
false);
508 nrof_used_iterations.set_size(no_blocks,
false);
511 Le12.set_size(Nuncoded,
false);
512 Le21.set_size(Nuncoded,
false);
519 if(true_bits.size() > 1) {
520 it_assert(true_bits.size() == Nuncoded * no_blocks,
"Turbo_Codec::decode_n3: Illegal size of input vector true_bits");
521 CHECK_TRUE_BITS =
true;
524 CHECK_TRUE_BITS =
false;
527 if(CHECK_TRUE_BITS) {
529 "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
533 for(i = 0; i < no_blocks; i++) {
539 for(k = 0; k < Nuncoded; k++) {
540 rec_syst1(k) = received_signal(count);
542 rec_parity1(k) = received_signal(count);
544 rec_parity2(k) = received_signal(count);
549 for(k = 0; k < m_tail; k++) {
550 rec_syst1(Nuncoded + k) = received_signal(count);
552 rec_parity1(Nuncoded + k) = received_signal(count);
557 for(k = 0; k < m_tail; k++) {
558 rec_syst2(Nuncoded + k) = received_signal(count);
560 rec_parity2(Nuncoded + k) = received_signal(count);
564 float_interleaver.
interleave(rec_syst1.left(Nuncoded), int_rec_syst1);
577 nrof_used_iterations_i = iterations;
578 for(j = 0; j < iterations; j++) {
580 rscc1.
log_decode_n2(rec_syst1, rec_parity1, Le21, Le12,
true, string_from_metric(metric));
581 if(logmax_scale_factor != 1.0) { Le12 *= logmax_scale_factor; }
584 rscc2.
log_decode_n2(rec_syst2, rec_parity2, Le12_int, Le21_int,
true, string_from_metric(metric));
585 if(logmax_scale_factor != 1.0) { Le21_int *= logmax_scale_factor; }
589 L = rec_syst1.
left(Nuncoded) + Le21.
left(Nuncoded) + Le12.
left(Nuncoded);
590 for(l = 0; l < Nuncoded; l++) {(L(l) > 0.0) ? (temp_decoded_bits(l) =
bin(0)) : (temp_decoded_bits(l) =
bin(1)); }
591 if(j == 0) { decoded_bits_previous_iteration = temp_decoded_bits; }
593 if(temp_decoded_bits == decoded_bits_previous_iteration) {
596 else if(j < (iterations - 1)) {
597 decoded_bits_previous_iteration = temp_decoded_bits;
602 if(CHECK_TRUE_BITS) {
603 L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
604 for(l = 0; l < Nuncoded; l++) {(L(l) > 0.0) ? (temp_decoded_bits(l) =
bin(0)) : (temp_decoded_bits(l) =
bin(1)); }
605 if(temp_decoded_bits == true_bits.mid(i * Nuncoded, Nuncoded)) {
610 if(CONTINUE ==
false) { nrof_used_iterations_i = j + 1;
break; }
615 L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
616 for(l = 0; l < Nuncoded; l++) {
617 (L(l) > 0.0) ? (decoded_bits(count_out) =
bin(0)) : (decoded_bits(count_out) =
bin(1));
621 nrof_used_iterations(i) = nrof_used_iterations_i;
633 Turbo_Codec::set_parameters(gen1, gen2, constraint_length, interleaver_sequence, in_iterations, in_metric, in_logmax_scale_factor, in_adaptive_stop, lcalc);
644 it_error_if(pmatrix.rows() != n_tot || pmatrix.cols() == 0,
"Wrong size of puncture matrix");
645 puncture_matrix = pmatrix;
646 Period = puncture_matrix.cols();
649 for(j = 0; j < n_tot; j++) {
650 for(p = 0; p <
Period; p++)
651 punct_total += static_cast<int>(puncture_matrix(j, p));
654 for(p = 0; p <
Period; p++)
655 punct_total2 += static_cast<int>(puncture_matrix(0, p));
656 punct_total1 = punct_total2;
658 for(j = 1; j < n1 + 1; j++) {
659 for(p = 0; p <
Period; p++)
660 punct_total1 += static_cast<int>(puncture_matrix(j, p));
663 for(j = 1 + n1; j < n_tot; j++) {
664 for(p = 0; p <
Period; p++)
665 punct_total2 += static_cast<int>(puncture_matrix(j, p));
669 rate = Period /
static_cast<double>(punct_total);
676 if(nominal)
return rate;
679 return static_cast<double>(Nuncoded) / Ncoded;
681 return static_cast<double>(Nuncoded) / pNcoded;
690 encode(input, coded_bits);
698 decode(received_signal, decoded_bits);
704 it_assert(
Period != 0,
"Punctured_Turbo_Codec: puncture matrix is not set");
709 int no_blocks = output.size() / Ncoded;
710 int count = 0, count_p = 0;
712 for(k = 0; k < no_blocks; k++) {
715 for(i = 0; i < Nuncoded; i++) {
716 for(j = 0; j < n_tot; j++) {
717 if(puncture_matrix(j, p) ==
bin(1)) {
718 output(count_p) = output(count);
728 for(i = 0; i < m_tail; i++) {
729 for(j = 0; j < n1 + 1; j++) {
730 if(puncture_matrix(j, p) ==
bin(1)) {
731 output(count_p) = output(count);
739 for(i = 0; i < m_tail; i++) {
741 if(puncture_matrix(0, p1) ==
bin(1)) {
742 output(count_p) = output(count);
747 for(j = n1 + 1; j < n_tot; j++) {
748 if(puncture_matrix(j, p1) ==
bin(1)) {
749 output(count_p) = output(count);
758 output.set_size(count_p,
true);
765 int index = 0, index_p = 0;
766 int no_blocks = received_signal.size() / pNcoded;
767 vec temp(no_blocks * Ncoded);
769 it_assert(
Period != 0,
"Punctured_Turbo_Codec: puncture matrix is not set");
770 it_assert(no_blocks * pNcoded == received_signal.size(),
"Punctured_Turbo_Codec: received vector is not an integer multiple of encoded block");
771 for(i = 0; i < no_blocks; i++) {
774 for(k = 0; k < Nuncoded; k++) {
775 for(j = 0; j < n_tot; j++) {
776 if(puncture_matrix(j, p) ==
bin(1)) {
777 temp(index) = received_signal(index_p);
790 for(k = 0; k < m_tail; k++) {
791 for(j = 0; j < n1 + 1; j++) {
792 if(puncture_matrix(j, p) ==
bin(1)) {
793 temp(index) = received_signal(index_p);
804 for(k = 0; k < m_tail; k++) {
806 if(puncture_matrix(0, p1) ==
bin(1)) {
807 temp(index) = received_signal(index_p);
815 for(j = n1 + 1; j < n_tot; j++) {
816 if(puncture_matrix(j, p1) ==
bin(1)) {
817 temp(index) = received_signal(index_p);
834 ivec nrof_used_iterations;
835 decode(received_signal, decoded_bits, nrof_used_iterations, true_bits);
840 int i, j, ii, p = 0, p1;
846 ii = i * punct_total;
848 for(; i < Nuncoded; i++) {
849 for(j = 0; j < n_tot; j++)
850 if(puncture_matrix(j, p) ==
bin(1)) ii++;
856 for(i = 0; i < m_tail; i++) {
857 for(j = 0; j < n1 + 1; j++)
858 if(puncture_matrix(j, p) ==
bin(1)) ii++;
862 for(i = 0; i < m_tail; i++) {
863 for(j = 0; j < n_tot; j++) {
864 if(puncture_matrix(j, p1) ==
bin(1)) ii++;
881 Nuncoded = (punctured_size - tc.m_tail * (tc.n_tot + 1)) / tc.n_tot;
882 fill_bits = punctured_size - (Nuncoded * tc.n_tot + tc.m_tail * (tc.n_tot + 1));
885 int i, j, ii, p, p1, no_pblocks;
887 j =
static_cast<int>(
std::ceil(static_cast<double>(tc.m_tail * (tc.punct_total1 + tc.punct_total2)) / tc.
Period));
888 no_pblocks = (punctured_size - j) / tc.punct_total;
889 ii = punctured_size - no_pblocks * tc.punct_total - j;
891 for(i = 0; i < 2 * tc.
Period; i++) {
892 for(j = 0; j < tc.n_tot; j++)
893 if(tc.puncture_matrix(j, i % tc.
Period) ==
bin(1)) ii--;
896 Nuncoded = no_pblocks * tc.
Period + i;
899 no_pblocks = (Nuncoded / tc.
Period);
900 ii = no_pblocks * tc.punct_total;
902 for(i = no_pblocks * tc.
Period; i < Nuncoded; i++) {
903 for(j = 0; j < tc.n_tot; j++)
904 if(tc.puncture_matrix(j, p) ==
bin(1)) ii++;
909 for(i = 0; i < tc.m_tail; i++) {
910 for(j = 0; j < tc.n1 + 1; j++)
911 if(tc.puncture_matrix(j, p1) ==
bin(1)) ii++;
912 p1 = (p1 + 1) % tc.
Period;
915 for(i = 0; i < tc.m_tail; i++) {
916 for(j = 0; j < tc.n_tot; j++) {
917 if(tc.puncture_matrix(j, p1) ==
bin(1)) ii++;
918 if(j == 0) j += tc.n1;
920 p1 = (p1 + 1) % tc.
Period;
922 fill_bits = punctured_size - ii;
935 const int MAX_INTERLEAVER_SIZE = 5114;
936 const int MIN_INTERLEAVER_SIZE = 40;
948 ivec primes,
roots, Pat1, Pat2, Pat3, Pat4, Isort;
949 int i, j, qj, temp, row, col, index, count;
951 if(interleaver_size > MAX_INTERLEAVER_SIZE) {
953 I = sort_index(
randu(interleaver_size));
963 it_assert(interleaver_size <= MAX_INTERLEAVER_SIZE,
"wcdma_turbo_interleaver_sequence: The interleaver size is to large");
964 it_assert(interleaver_size >= MIN_INTERLEAVER_SIZE,
"wcdma_turbo_interleaver_sequence: The interleaver size is to small");
966 K = interleaver_size;
969 primes =
"2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257";
970 roots =
"0 0 0 3 2 2 3 2 5 2 3 2 6 3 5 2 2 2 2 7 5 3 2 3 5 2 5 2 6 3 3 2 3 2 2 6 5 2 5 2 2 2 19 5 2 3 2 3 2 6 3 7 7 6 3";
973 if((K >= 40) && (K <= 159)) {
976 else if(((K >= 160) && (K <= 200)) || ((K >= 481) && (K <= 530))) {
984 if((K >= 481) && (K <= 530)) {
991 for(i = 0; i < primes.length(); i++) {
992 if((
double(primes(i) + 1) -
double(K) /
double(R)) >= 0.0) {
999 if((
double(p) -
double(K) /
double(R)) >= 0.0) {
1000 if((
double(p) - 1.0 -
double(K) /
double(R)) >= 0.0) {
1013 s.set_size(p - 1,
false);
1016 for(i = 1; i <= (p - 2); i++) {
1017 s(i) =
mod(v * s(i - 1), p);
1022 q.set_size(R,
false);
1025 for(j = 1; j <= (R - 1); j++) {
1026 for(i = 0; i < primes.length(); i++) {
1028 if((qj > 6) && (qj > q(j - 1))) {
1029 if(
gcd(qj, p - 1) == 1) {
1038 Pat1 =
"19 9 14 4 0 2 5 7 12 18 10 8 13 17 3 1 16 6 15 11";
1039 Pat2 =
"19 9 14 4 0 2 5 7 12 18 16 13 17 15 3 1 6 11 8 10";
1040 Pat3 =
"9 8 7 6 5 4 3 2 1 0";
1048 else if(K >= 3161) {
1051 else if(K >= 2481) {
1054 else if(K >= 2281) {
1075 r.set_size(R,
false);
1077 for(j = 0; j <= (R - 1); j++) {
1083 U.set_size(R, C,
false);
1086 for(j = 0; j <= (R - 1); j++) {
1087 for(i = 0; i <= (p - 2); i++) {
1088 U(j, i) = s(
mod(i * r(j), p - 1));
1093 else if(C == (p + 1)) {
1094 for(j = 0; j <= (R - 1); j++) {
1095 for(i = 0; i <= (p - 2); i++) {
1096 U(j, i) = s(
mod(i * r(j), p - 1));
1103 U(R - 1, p) = U(R - 1, 0);
1107 else if(C == (p - 1)) {
1108 for(j = 0; j <= (R - 1); j++) {
1109 for(i = 0; i <= (p - 2); i++) {
1110 U(j, i) = s(
mod(i * r(j), p - 1)) - 1;
1116 I.set_size(K,
false);
1119 for(i = 0; i < C; i++) {
1120 for(j = 0; j < R; j++) {
1123 index = row * C + col;
1140 ivec block_lengths(
"40 48 56 64 72 80 88 96 104 112 120 128 136 144 152 160 168 176 184 192 200 208 216 224 232 240 248 256 264 272 280 288 296 304 312 320 328 336 344 352 360 368 376 384 392 400 408 416 424 432 440 448 456 464 472 480 488 496 504 512 528 544 560 576 592 608 624 640 656 672 688 704 720 736 752 768 784 800 816 832 848 864 880 896 912 928 944 960 976 992 1008 1024 1056 1088 1120 1152 1184 1216 1248 1280 1312 1344 1376 1408 1440 1472 1504 1536 1568 1600 1632 1664 1696 1728 1760 1792 1824 1856 1888 1920 1952 1984 2016 2048 2112 2176 2240 2304 2368 2432 2496 2560 2624 2688 2752 2816 2880 2944 3008 3072 3136 3200 3264 3328 3392 3456 3520 3584 3648 3712 3776 3840 3904 3968 4032 4096 4160 4224 4288 4352 4416 4480 4544 4608 4672 4736 4800 4864 4928 4992 5056 5120 5184 5248 5312 5376 5440 5504 5568 5632 5696 5760 5824 5888 5952 6016 6080 6144");
1141 ivec f1_factors(
" 3 7 19 7 7 11 5 11 7 41 103 15 9 17 9 21 101 21 57 23 13 27 11 27 85 29 33 15 17 33 103 19 19 37 19 21 21 115 193 21 133 81 45 23 243 151 155 25 51 47 91 29 29 247 29 89 91 157 55 31 17 35 227 65 19 37 41 39 185 43 21 155 79 139 23 217 25 17 127 25 239 17 137 215 29 15 147 29 59 65 55 31 17 171 67 35 19 39 19 199 21 211 21 43 149 45 49 71 13 17 25 183 55 127 27 29 29 57 45 31 59 185 113 31 17 171 209 253 367 265 181 39 27 127 143 43 29 45 157 47 13 111 443 51 51 451 257 57 313 271 179 331 363 375 127 31 33 43 33 477 35 233 357 337 37 71 71 37 39 127 39 39 31 113 41 251 43 21 43 45 45 161 89 323 47 23 47 263");
1142 ivec f2_factors(
"10 12 42 16 18 20 22 24 26 84 90 32 34 108 38 120 84 44 46 48 50 52 36 56 58 60 62 32 198 68 210 36 74 76 78 120 82 84 86 44 90 46 94 48 98 40 102 52 106 72 110 168 114 58 118 180 122 62 84 64 66 68 420 96 74 76 234 80 82 252 86 44 120 92 94 48 98 80 102 52 106 48 110 112 114 58 118 60 122 124 84 64 66 204 140 72 74 76 78 240 82 252 86 88 60 92 846 48 28 80 102 104 954 96 110 112 114 116 354 120 610 124 420 64 66 136 420 216 444 456 468 80 164 504 172 88 300 92 188 96 28 240 204 104 212 192 220 336 228 232 236 120 244 248 168 64 130 264 134 408 138 280 142 480 146 444 120 152 462 234 158 80 96 902 166 336 170 86 174 176 178 120 182 184 186 94 190 480");
1143 const int MAX_INTERLEAVER_SIZE = 6144;
1144 const int MIN_INTERLEAVER_SIZE = 40;
1147 it_assert(interleaver_size <= MAX_INTERLEAVER_SIZE,
"lte_turbo_interleaver_sequence: The interleaver size is too large");
1148 it_assert(interleaver_size >= MIN_INTERLEAVER_SIZE,
"lte_turbo_interleaver_sequence: The interleaver size is too small");
1151 int left, right, index, temp;
1156 right = block_lengths.size() - 1;
1158 while((search) && (left <= right)) {
1159 index = (left + right) / 2;
1160 temp = block_lengths(index);
1161 if(temp == interleaver_size) {
1165 if(temp > interleaver_size) {
1173 it_assert(!search,
"lte_turbo_interleaver_sequence: The interleaver size is incorrect!");
1176 int K = interleaver_size;
1177 int f1_factor = f1_factors(index);
1178 int f2_factor = f2_factors(index);
1182 for(
int i = 0; i < K; i++) {
1183 I(i) =
static_cast<int>((
static_cast<int64_t
>(i) * f1_factor + static_cast<int64_t>(i) * i * f2_factor) % K);