37std::string Turbo_Codec::string_from_metric(
const Turbo_Codec::Metric& in_metric)
39 if(in_metric == Metric::LOGMAX) {
40 return std::string(
"LOGMAX");
42 else if(in_metric == Metric::LOGMAP) {
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");
61 interleaver_size = interleaver_sequence.
size();
62 Nuncoded = interleaver_size;
68 metric = Metric::LOGMAX;
71 metric = Metric::LOGMAP;
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");
98 Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
101 bit_interleaver.set_interleaver_depth(interleaver_size);
103 bit_interleaver.set_interleaver_sequence(interleaver_sequence);
117 interleaver_size = interleaver_sequence.
size();
118 Nuncoded = interleaver_size;
121 Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
124 bit_interleaver.set_interleaver_depth(interleaver_size);
126 bit_interleaver.set_interleaver_sequence(interleaver_sequence);
136 metric = Metric::LOGMAX;
139 metric = Metric::LOGMAP;
142 metric = Metric::MAP;
145 metric = Metric::TABLE;
148 it_error(
"Turbo_Codec::set_metric: The decoder metric must be either MAP, LOGMAP, LOGMAX or TABLE");
169 Lc = 4.0 * std::sqrt(Ec) / N0;
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++; }
236 if((n1 == 1) && (n2 == 1) && (metric != Metric::MAP)) {
277 for(k = 0; k < Nuncoded; k++) {
285 for(k = 0; k < m_tail; k++) {
292 for(k = 0; k < m_tail; k++) {
332 it_assert(input.length() == Nuncoded,
"Turbo_Codec::encode_block: Parameter error in Nuncoded.");
396 it_assert(
true_bits.
size() == Nuncoded,
"Turbo_Codec::decode_block: Illegal size of input vector true_bits");
405 "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
410 for(
i = 0;
i < iterations;
i++) {
413 if(metric == Metric::MAP) {
416 else if((metric == Metric::LOGMAX) || (metric == Metric::LOGMAP) || (metric == Metric::TABLE)) {
418 if(logmax_scale_factor != 1.0) {
419 Le12 *= logmax_scale_factor;
423 it_error(
"Turbo_Codec::decode_block: Illegal metric value");
431 if(metric == Metric::MAP) {
434 else if((metric == Metric::LOGMAX) || (metric == Metric::LOGMAP) || (metric == Metric::TABLE)) {
436 if(logmax_scale_factor != 1.0) {
441 it_error(
"Turbo_Codec::decode_block: Illegal metric value");
451 for(l = 0; l < Nuncoded; l++) {
458 if(
i < (iterations - 1)) {
465 if((adaptive_stop) && (
i > 0)) {
475 for(k = (
i + 1); k < iterations; k++) {
507 decoded_bits_previous_iteration.set_size(Nuncoded,
false);
529 "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
539 for(k = 0; k < Nuncoded; k++) {
549 for(k = 0; k < m_tail; k++) {
557 for(k = 0; k < m_tail; k++) {
578 for(
j = 0;
j < iterations;
j++) {
581 if(logmax_scale_factor != 1.0) {
Le12 *= logmax_scale_factor; }
585 if(logmax_scale_factor != 1.0) {
Le21_int *= logmax_scale_factor; }
596 else if(
j < (iterations - 1)) {
616 for(l = 0; l < Nuncoded; l++) {
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);
679 return static_cast<double>(Nuncoded) / Ncoded;
681 return static_cast<double>(Nuncoded) / pNcoded;
704 it_assert(
Period != 0,
"Punctured_Turbo_Codec: puncture matrix is not set");
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);
769 it_assert(
Period != 0,
"Punctured_Turbo_Codec: puncture matrix is not set");
774 for(k = 0; k < Nuncoded; k++) {
775 for(
j = 0;
j < n_tot;
j++) {
776 if(puncture_matrix(
j, p) ==
bin(1)) {
790 for(k = 0; k < m_tail; k++) {
791 for(
j = 0;
j < n1 + 1;
j++) {
792 if(puncture_matrix(
j, p) ==
bin(1)) {
804 for(k = 0; k < m_tail; k++) {
806 if(puncture_matrix(0,
p1) ==
bin(1)) {
815 for(
j = n1 + 1;
j < n_tot;
j++) {
816 if(puncture_matrix(
j,
p1) ==
bin(1)) {
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++;
887 j =
static_cast<int>(std::ceil(
static_cast<double>(
tc.m_tail * (
tc.punct_total1 +
tc.punct_total2)) /
tc.Period));
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--;
903 for(
j = 0;
j <
tc.n_tot;
j++)
904 if(
tc.puncture_matrix(
j, p) ==
bin(1))
ii++;
905 p = (p + 1) %
tc.Period;
909 for(
i = 0;
i <
tc.m_tail;
i++) {
910 for(
j = 0;
j <
tc.n1 + 1;
j++)
912 p1 = (
p1 + 1) %
tc.Period;
915 for(
i = 0;
i <
tc.m_tail;
i++) {
916 for(
j = 0;
j <
tc.n_tot;
j++) {
918 if(
j == 0)
j +=
tc.n1;
920 p1 = (
p1 + 1) %
tc.Period;
953 I = sort_index(
randu(interleaver_size));
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)) {
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) {
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++) {
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) {
1077 for(
j = 0;
j <= (R - 1);
j++) {
1086 for(
j = 0;
j <= (R - 1);
j++) {
1087 for(
i = 0;
i <= (p - 2);
i++) {
1093 else if(C == (p + 1)) {
1094 for(
j = 0;
j <= (R - 1);
j++) {
1095 for(
i = 0;
i <= (p - 2);
i++) {
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;
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");
1151 int left, right, index,
temp;
1158 while((search) && (left <= right)) {
1159 index = (left + right) / 2;
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;
1182 for(
int i = 0;
i < K;
i++) {
Array< T > mid(int pos, int n) const
Get n elements of the array starting from pos.
int size() const
Returns the number of data elements in the array object.
Array< T > left(int n) const
Get n left elements of the array.
void set_size(int n, bool copy=false)
Resizing an Array<T>.
int length() const
Returns the number of data elements in the array object.
Array< T > right(int n) const
Get n right elements of the array.
Log-likelihood algebra calculation unit.
Punctured turbo encoder/decoder Class.
int Period
Number of columns in the puncturing matrix.
void set_parameters(ivec gen1, ivec gen2, int constraint_length, const ivec &interleaver_sequence, bmat &pmatrix, int in_iterations=8, std::string in_metric="LOGMAX", double in_logmax_scale_factor=1.0, bool in_adaptive_stop=false, itpp::LLR_calc_unit lcalc=itpp::LLR_calc_unit())
Set parameters for the punctured turbo encoder/decoder.
void calculate_punctured_size(void)
Calculates length of the puncturing codeword.
void set_puncture_matrix(const bmat &pmatrix)
Sets puncturing matrix for turbo code (size n_tot * Period)
virtual void decode(const vec &received_signal, bvec &decoded_bits, const bvec &true_bits="0")
Decoder function.
double get_rate(bool nominal=true)
Returns rate of the turbo code.
void encode(const bvec &input, bvec &output)
Encoder function.
virtual void map_decode(const vec &rec_systematic, const mat &rec_parity, const vec &extrinsic_input, vec &extrinsic_output, bool set_terminated=false)
Maximum A Posteriori (MAP) Probability symbol-by-symbol decoder.
void set_generator_polynomials(const ivec &gen, int constraint_length)
Set generator polynomials.
void encode_tail(const bvec &input, bvec &tail, bmat &parity_bits)
Encode a binary vector of inputs and also adds a tail of K-1 zeros to force the encoder into the zero...
virtual void log_decode_n2(const vec &rec_systematic, const vec &rec_parity, const vec &extrinsic_input, vec &extrinsic_output, bool set_terminated=false, std::string metric="LOGMAX")
Special Log-MAP/Log-MAX decoder implementation for n = 2.
void set_llrcalc(LLR_calc_unit in_llrcalc)
Set the lookup table for algebra with quantized LLR values (see LLR_calc_unit class)
virtual void log_decode(const vec &rec_systematic, const mat &rec_parity, const vec &extrinsic_input, vec &extrinsic_output, bool set_terminated=false, std::string metric="LOGMAX")
Log domain implementation of the Maximum A Posteriori (MAP) Probability symbol-by-symbol decoder.
void set_interleaver_depth(int in_interleaver_depth)
Set the length of the interleaver sequence to be used.
Vec< T > interleave(const Vec< T > &input)
Function for sequence interleaving. May add some zeros.
Vec< T > deinterleave(const Vec< T > &input, short keepzeros=0)
Function for sequence deinterleaving. Removes additional zeros if keepzeros = 0.
void set_interleaver_sequence(ivec in_interleaver_sequence)
Set the interleaver sequence to be used.
void encode(const bvec &input, bvec &output)
Encoder function.
void set_iterations(int in_iterations=8)
Sets the number of decoding iterations. Default value is 8.
void set_metric(std::string in_metric="LOGMAX", double in_logmax_scale_factor=1.0, LLR_calc_unit lcalc=LLR_calc_unit())
Set the decoder metric.
virtual void decode_block(const vec &rec_syst1, const vec &rec_syst2, const mat &rec_parity1, const mat &rec_parity2, bmat &decoded_bits_i, int &nrof_used_iterations_i, const bvec &true_bits="0")
Decode a single block.
void set_awgn_channel_parameters(double in_Ec, double in_N0)
Set parameters for decoding on an AWGN channel.
void set_parameters(ivec gen1, ivec gen2, int constraint_length, const ivec &interleaver_sequence, int in_iterations=8, const std::string &in_metric="LOGMAX", double in_logmax_scale_factor=1.0, bool in_adaptive_stop=false, LLR_calc_unit lcalc=LLR_calc_unit())
Set parameters for the turbo encoder/decoder.
void set_adaptive_stop(bool in_adaptive_stop=true)
Use and adaptive number of iterations.
void set_interleaver(const ivec &interleaver_sequence)
Set a new internal interleaver sequence for the turbo encoder/decoder.
void encode_block(const bvec &input, bvec &in1, bvec &in2, bmat &parity1, bmat &parity2)
Encode a single block.
void set_scaling_factor(double in_Lc)
Set scaling factor for decoding on e.g. Rayleigh fading channels.
virtual void decode(const vec &received_signal, bvec &decoded_bits, const bvec &true_bits="0")
Decoder function.
void decode_n3(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations, const bvec &true_bits="0")
Special decoder function for R = 1/3 i.e. two parity bits for each systematic bit.
Binary arithmetic (boolean) class.
#define it_error_if(t, s)
Abort if t is true.
#define it_error(s)
Abort unconditionally.
#define it_assert(t, s)
Abort if t is not true.
int mod(int k, int n)
Calculates the modulus, i.e. the signed reminder after division.
int gcd(int a, int b)
Compute the greatest common divisor (GCD) g of the elements a and b.
void roots(const vec &p, cvec &r)
Calculate the roots of the polynomial.
double randu(void)
Generates a random uniform (0,1) number.
ITPP_EXPORT vec zeros(int size)
A Double vector of zeros.
Mat< bin > bmat
bin matrix
ivec lte_turbo_interleaver_sequence(int interleaver_size)
Generates the interleaver sequence for the internal turbo encoder interleaver used in LTE.
ivec wcdma_turbo_interleaver_sequence(int interleaver_size)
Generates the interleaver sequence for the internal turbo encoder interleaver used in WCDMA.
const Array< T > concat(const Array< T > &a, const T &e)
Append element e to the end of the Array a.
int calculate_uncoded_size(Punctured_Turbo_Codec &tc, int punctured_size, int &fill_bits)
Definition of a (punctured) turbo encoder/decoder class.