IT++ Logo
turbo.cpp
Go to the documentation of this file.
1 
29 #include <itpp/comm/turbo.h>
30 
31 
32 namespace itpp
33 {
34 // -------------------------------------------------------------------------------------
35 // Turbo Codec
36 // -------------------------------------------------------------------------------------
37 std::string Turbo_Codec::string_from_metric(const Turbo_Codec::Metric& in_metric)
38 {
39  if(in_metric == Metric::LOGMAX) {
40  return std::string("LOGMAX");
41  }
42  else if(in_metric == Metric::LOGMAP) {
43  return std::string("LOGMAP");
44  }
45  else if(in_metric == Metric::MAP) {
46  return std::string("MAP");
47  }
48  else if(in_metric == Metric::TABLE) {
49  return std::string("TABLE");
50  }
51  else {
52  return std::string("UNKNOWN");
53  }
54 }
55 void Turbo_Codec::set_parameters(ivec gen1, ivec gen2, int constraint_length, const ivec &interleaver_sequence,
56  int in_iterations, std::string in_metric, double in_logmax_scale_factor,
57  bool in_adaptive_stop, LLR_calc_unit in_llrcalc)
58 {
59  //Set the input parameters:
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;
65 
66  //Check the decoding metric
67  if(in_metric == "LOGMAX") {
68  metric = Metric::LOGMAX;
69  }
70  else if(in_metric == "LOGMAP") {
71  metric = Metric::LOGMAP;
72  }
73  else if(in_metric == "MAP") {
74  metric = Metric::MAP;
75  }
76  else if(in_metric == "TABLE") {
77  metric = Metric::TABLE;
78  }
79  else {
80  it_error("Turbo_Codec::set_parameters: The decoder metric must be either MAP, LOGMAP, LOGMAX or TABLE");
81  }
82 
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");
85  }
86 
87  //The RSC Encoders:
88  rscc1.set_generator_polynomials(gen1, constraint_length);
89  rscc2.set_generator_polynomials(gen2, constraint_length);
90  n1 = gen1.length() - 1; //Number of parity bits from rscc1
91  n2 = gen2.length() - 1; //Number of parity bits from rscc2
92  n_tot = 1 + n1 + n2; //Total number of parity bits and systematic bits
93 
94  //Set the number of tail bits:
95  m_tail = constraint_length - 1;
96 
97  //Calculate the number of coded bits per code-block:
98  Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
99 
100  //Set the interleaver sequence
101  bit_interleaver.set_interleaver_depth(interleaver_size);
102  float_interleaver.set_interleaver_depth(interleaver_size);
103  bit_interleaver.set_interleaver_sequence(interleaver_sequence);
104  float_interleaver.set_interleaver_sequence(interleaver_sequence);
105 
106  //Default value of the channel reliability scaling factor is 1
107  Lc = 1.0;
108 
109  // LLR algebra table
110  rscc1.set_llrcalc(in_llrcalc);
111  rscc2.set_llrcalc(in_llrcalc);
112 
113 }
114 
115 void Turbo_Codec::set_interleaver(const ivec &interleaver_sequence)
116 {
117  interleaver_size = interleaver_sequence.size();
118  Nuncoded = interleaver_size;
119 
120  //Calculate the number of coded bits per code-block:
121  Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
122 
123  //Set the interleaver sequence
124  bit_interleaver.set_interleaver_depth(interleaver_size);
125  float_interleaver.set_interleaver_depth(interleaver_size);
126  bit_interleaver.set_interleaver_sequence(interleaver_sequence);
127  float_interleaver.set_interleaver_sequence(interleaver_sequence);
128 }
129 
130 void Turbo_Codec::set_metric(std::string in_metric, double in_logmax_scale_factor, LLR_calc_unit in_llrcalc)
131 {
132  logmax_scale_factor = in_logmax_scale_factor;
133 
134  //Check the decoding metric
135  if(in_metric == "LOGMAX") {
136  metric = Metric::LOGMAX;
137  }
138  else if(in_metric == "LOGMAP") {
139  metric = Metric::LOGMAP;
140  }
141  else if(in_metric == "MAP") {
142  metric = Metric::MAP;
143  }
144  else if(in_metric == "TABLE") {
145  metric = Metric::TABLE;
146  }
147  else {
148  it_error("Turbo_Codec::set_metric: The decoder metric must be either MAP, LOGMAP, LOGMAX or TABLE");
149  }
150 
151  rscc1.set_llrcalc(in_llrcalc);
152  rscc2.set_llrcalc(in_llrcalc);
153 }
154 
155 void Turbo_Codec::set_iterations(int in_iterations)
156 {
157  iterations = in_iterations;
158 }
159 
160 void Turbo_Codec::set_adaptive_stop(bool in_adaptive_stop)
161 {
162  adaptive_stop = in_adaptive_stop;
163 }
164 
165 void Turbo_Codec::set_awgn_channel_parameters(double in_Ec, double in_N0)
166 {
167  Ec = in_Ec;
168  N0 = in_N0;
169  Lc = 4.0 * std::sqrt(Ec) / N0;
170 }
171 
173 {
174  Lc = in_Lc;
175 }
176 
177 
178 void Turbo_Codec::encode(const bvec &input, bvec &output)
179 {
180  //Local variables:
181  int i, k, j, no_blocks;
182  int count;
183  bvec input_bits, in1, in2, tail1, tail2, out;
184  bmat parity1, parity2;
185 
186  //Initializations:
187  no_blocks = input.length() / Nuncoded;
188  output.set_size(no_blocks * Ncoded, false);
189 
190  //Set the bit counter to zero:
191  count = 0;
192 
193  //Encode all code blocks:
194  for(i = 0; i < no_blocks; i++) {
195 
196  //Encode one block
197  input_bits = input.mid(i * Nuncoded, Nuncoded);
198  encode_block(input_bits, in1, in2, parity1, parity2);
199 
200  //The data part:
201  for(k = 0; k < Nuncoded; k++) {
202  output(count) = in1(k);
203  count++; //Systematic bits
204  for(j = 0; j < n1; j++) { output(count) = parity1(k, j); count++; } //Parity-1 bits
205  for(j = 0; j < n2; j++) { output(count) = parity2(k, j); count++; } //Parity-2 bits
206  }
207 
208  //The first tail:
209  for(k = 0; k < m_tail; k++) {
210  output(count) = in1(Nuncoded + k);
211  count++; //First systematic tail bit
212  for(j = 0; j < n1; j++) { output(count) = parity1(Nuncoded + k, j); count++; } //Parity-1 tail bits
213  }
214 
215  //The second tail:
216  for(k = 0; k < m_tail; k++) {
217  output(count) = in2(Nuncoded + k);
218  count++; //Second systematic tail bit
219  for(j = 0; j < n2; j++) { output(count) = parity2(Nuncoded + k, j); count++; } //Parity-2 tail bits
220  }
221 
222  }
223 
224 }
225 
226 void Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, const bvec &true_bits)
227 {
228  ivec nrof_used_iterations;
229  decode(received_signal, decoded_bits, nrof_used_iterations, true_bits);
230 }
231 
232 void Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations,
233  const bvec &true_bits)
234 {
235 
236  if((n1 == 1) && (n2 == 1) && (metric != Metric::MAP)) {
237  //This is a speed optimized decoder for R=1/3 (log domain metrics only)
238  decode_n3(received_signal, decoded_bits, nrof_used_iterations, true_bits);
239  }
240  else {
241 
242  //Local variables:
243  vec rec, rec_syst1, rec_syst2;
244  mat rec_parity1, rec_parity2;
245  bmat decoded_bits_i;
246  int no_blocks, i, j, k, nrof_used_iterations_i;
247  int count;
248  bool CHECK_TRUE_BITS;
249 
250  //Initilaizations:
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);
256  rec_syst2.clear();
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);
260 
261  //Check the vector true_bits:
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;
265  }
266  else {
267  CHECK_TRUE_BITS = false;
268  }
269 
270  //Set the bit counter to zero:
271  count = 0;
272 
273  //Itterate over all received code blocks:
274  for(i = 0; i < no_blocks; i++) {
275 
276  //The data part:
277  for(k = 0; k < Nuncoded; k++) {
278  rec_syst1(k) = received_signal(count);
279  count++; //Systematic bit
280  for(j = 0; j < n1; j++) { rec_parity1(k, j) = received_signal(count); count++; } //Parity-1 bits
281  for(j = 0; j < n2; j++) { rec_parity2(k, j) = received_signal(count); count++; } //Parity-2 bits
282  }
283 
284  //The first tail:
285  for(k = 0; k < m_tail; k++) {
286  rec_syst1(Nuncoded + k) = received_signal(count);
287  count++; //Tail 1 systematic bit
288  for(j = 0; j < n1; j++) { rec_parity1(Nuncoded + k, j) = received_signal(count); count++; } //Tail 1 parity-1 bits
289  }
290 
291  //The second tail:
292  for(k = 0; k < m_tail; k++) {
293  rec_syst2(Nuncoded + k) = received_signal(count);
294  count++; //Tail2 systematic bit
295  for(j = 0; j < n2; j++) { rec_parity2(Nuncoded + k, j) = received_signal(count); count++; } //Tali2 parity-2 bits
296  }
297 
298  //Scale the input data if necessary:
299  if(Lc != 1.0) {
300  rec_syst1 *= Lc;
301  rec_syst2 *= Lc;
302  rec_parity1 *= Lc;
303  rec_parity2 *= Lc;
304  }
305 
306  //Decode the block:
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;
311  }
312  else {
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;
315  }
316 
317  //Put the decoded bits in the output vector:
318  decoded_bits.replace_mid(i * Nuncoded, decoded_bits_i.get_row(iterations - 1));
319 
320  }
321 
322  }
323 
324 }
325 
326 void Turbo_Codec::encode_block(const bvec &input, bvec &in1, bvec &in2, bmat &parity1, bmat &parity2)
327 {
328  //Local variables:
329  bvec tail1, tail2, interleaved_input;
330 
331  //Error check:
332  it_assert(input.length() == Nuncoded, "Turbo_Codec::encode_block: Parameter error in Nuncoded.");
333 
334  //Initializations:
335  tail1.set_size(m_tail, false);
336  tail1.clear();
337  tail2.set_size(m_tail, false);
338  tail2.clear();
339  parity1.set_size(Nuncoded + m_tail, n1, false);
340  parity1.clear();
341  parity2.set_size(Nuncoded + m_tail, n2, false);
342  parity2.clear();
343  interleaved_input.set_size(Nuncoded, false);
344  interleaved_input.clear();
345 
346  //The first encoder:
347  rscc1.encode_tail(input, tail1, parity1);
348 
349  //The interleaver:
350  bit_interleaver.interleave(input, interleaved_input);
351 
352  //The second encoder:
353  rscc2.encode_tail(interleaved_input, tail2, parity2);
354 
355  //The input vectors used to the two constituent encoders:
356  in1 = concat(input, tail1);
357  in2 = concat(interleaved_input, tail2);
358 
359 }
360 
361 void Turbo_Codec::decode_block(const vec &rec_syst1, const vec &rec_syst2, const mat &rec_parity1,
362  const mat &rec_parity2, bmat &decoded_bits_i, int &nrof_used_iterations_i,
363  const bvec &true_bits)
364 {
365  //Local variables:
366  int i;
367  int count, l, k;
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;
371 
372  //Size initializations:
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);
376  Le21.zeros();
377 
378  //Calculate the interleaved and the deinterleaved sequences:
379  float_interleaver.interleave(rec_syst1.left(interleaver_size), int_rec_syst1);
380  float_interleaver.deinterleave(rec_syst2.left(interleaver_size), deint_rec_syst2);
381 
382  //Combine the results from rec_syst1 and rec_syst2 (in case some bits are transmitted several times)
383  rec_syst = rec_syst1.left(interleaver_size) + deint_rec_syst2;
384  int_rec_syst = rec_syst2.left(interleaver_size) + int_rec_syst1;
385 
386  //Get the two tails
387  tail1 = rec_syst1.right(m_tail);
388  tail2 = rec_syst2.right(m_tail);
389 
390  //Form the input vectors (including tails) to the two decoders:
391  rec_syst = concat(rec_syst, tail1);
392  int_rec_syst = concat(int_rec_syst, tail2);
393 
394  // Check the vector true_bits
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;
398  }
399  else {
400  CHECK_TRUE_BITS = false;
401  }
402 
403  if(CHECK_TRUE_BITS) {
404  it_assert(adaptive_stop == false,
405  "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
406  }
407 
408  // Do the iterative decoding:
409  nrof_used_iterations_i = iterations;
410  for(i = 0; i < iterations; i++) {
411 
412  // Decode Code 1
413  if(metric == Metric::MAP) {
414  rscc1.map_decode(rec_syst, rec_parity1, Le21, Le12, true);
415  }
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;
420  }
421  }
422  else {
423  it_error("Turbo_Codec::decode_block: Illegal metric value");
424  }
425 
426  // Interleave the extrinsic information:
427  float_interleaver.interleave(Le12.left(interleaver_size), tmp);
428  Le12_int = concat(tmp, zeros(Le12.size() - interleaver_size));
429 
430  // Decode Code 2
431  if(metric == Metric::MAP) {
432  rscc2.map_decode(int_rec_syst, rec_parity2, Le12_int, Le21_int, true);
433  }
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;
438  }
439  }
440  else {
441  it_error("Turbo_Codec::decode_block: Illegal metric value");
442  }
443 
444  // De-interleave the extrinsic information:
445  float_interleaver.deinterleave(Le21_int.left(interleaver_size), tmp);
446  Le21 = concat(tmp, zeros(Le21_int.size() - interleaver_size));
447 
448  // Take bit decisions
449  L = rec_syst + Le21 + Le12;
450  count = 0;
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));
453  count++;
454  }
455 
456  //Check if it is possible to stop iterating early:
457  CONTINUE = true;
458  if(i < (iterations - 1)) {
459 
460  if(CHECK_TRUE_BITS) {
461  CONTINUE = false;
462  for(k = 0; k < Nuncoded; k++) { if(true_bits(k) != decoded_bits_i(i, k)) { CONTINUE = true; break; } }
463  }
464 
465  if((adaptive_stop) && (i > 0)) {
466  CONTINUE = false;
467  for(k = 0; k < Nuncoded; k++) { if(decoded_bits_i(i - 1, k) != decoded_bits_i(i, k)) { CONTINUE = true; break; } }
468  }
469 
470  }
471 
472  //Check if iterations shall continue:
473  if(CONTINUE == false) {
474  //Copy the results from current iteration to all following iterations:
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;
478  }
479  break;
480  }
481 
482  }
483 
484 }
485 
486 void Turbo_Codec::decode_n3(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations,
487  const bvec &true_bits)
488 {
489  //Local variables:
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;
497 
498  //Initializations:
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);
503  rec_syst2.clear();
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);
509 
510  //Size initializations:
511  Le12.set_size(Nuncoded, false);
512  Le21.set_size(Nuncoded, false);
513 
514  //Set the bit counter to zero:
515  count = 0;
516  count_out = 0;
517 
518  // Check the vector true_bits
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;
522  }
523  else {
524  CHECK_TRUE_BITS = false;
525  }
526 
527  if(CHECK_TRUE_BITS) {
528  it_assert(adaptive_stop == false,
529  "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
530  }
531 
532  //Iterate over all received code blocks:
533  for(i = 0; i < no_blocks; i++) {
534 
535  //Reset extrinsic data:
536  Le21.zeros();
537 
538  //The data part:
539  for(k = 0; k < Nuncoded; k++) {
540  rec_syst1(k) = received_signal(count);
541  count++; //Systematic bit
542  rec_parity1(k) = received_signal(count);
543  count++; //Parity-1 bits
544  rec_parity2(k) = received_signal(count);
545  count++; //Parity-2 bits
546  }
547 
548  //The first tail:
549  for(k = 0; k < m_tail; k++) {
550  rec_syst1(Nuncoded + k) = received_signal(count);
551  count++; //Tail 1 systematic bit
552  rec_parity1(Nuncoded + k) = received_signal(count);
553  count++; //Tail 1 parity-1 bits
554  }
555 
556  //The second tail:
557  for(k = 0; k < m_tail; k++) {
558  rec_syst2(Nuncoded + k) = received_signal(count);
559  count++; //Tail2 systematic bit
560  rec_parity2(Nuncoded + k) = received_signal(count);
561  count++; //Tali2 parity-2 bits
562  }
563 
564  float_interleaver.interleave(rec_syst1.left(Nuncoded), int_rec_syst1);
565  rec_syst2.replace_mid(0, int_rec_syst1);
566 
567  //Scale the input data if necessary:
568  if(Lc != 1.0) {
569  rec_syst1 *= Lc;
570  rec_syst2 *= Lc;
571  rec_parity1 *= Lc;
572  rec_parity2 *= Lc;
573  }
574 
575  //Decode the block:
576  CONTINUE = true;
577  nrof_used_iterations_i = iterations;
578  for(j = 0; j < iterations; j++) {
579 
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; }
582  float_interleaver.interleave(Le12, Le12_int);
583 
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; }
586  float_interleaver.deinterleave(Le21_int, Le21);
587 
588  if(adaptive_stop) {
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; }
592  else {
593  if(temp_decoded_bits == decoded_bits_previous_iteration) {
594  CONTINUE = false;
595  }
596  else if(j < (iterations - 1)) {
597  decoded_bits_previous_iteration = temp_decoded_bits;
598  }
599  }
600  }
601 
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)) {
606  CONTINUE = false;
607  }
608  }
609 
610  if(CONTINUE == false) { nrof_used_iterations_i = j + 1; break; }
611 
612  }
613 
614  //Take final bit decisions
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));
618  count_out++;
619  }
620 
621  nrof_used_iterations(i) = nrof_used_iterations_i;
622 
623  }
624 
625 }
626 
627 // -------------------------------------------------------------------------------------
628 // Punctured Turbo Codec
629 // -------------------------------------------------------------------------------------
630 
631 void Punctured_Turbo_Codec::set_parameters(ivec gen1, ivec gen2, int constraint_length, const ivec &interleaver_sequence, bmat &pmatrix, int in_iterations, std::string in_metric, double in_logmax_scale_factor, bool in_adaptive_stop, itpp::LLR_calc_unit lcalc)
632 {
633  Turbo_Codec::set_parameters(gen1, gen2, constraint_length, interleaver_sequence, in_iterations, in_metric, in_logmax_scale_factor, in_adaptive_stop, lcalc);
634  set_puncture_matrix(pmatrix);
635 }
636 
638 {
639  int p, j;
640 
641  punct_total = 0;
642  punct_total2 = 0;
643 
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();
647 
648  // all rows
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));
652  }
653  // systematic bits
654  for(p = 0; p < Period; p++)
655  punct_total2 += static_cast<int>(puncture_matrix(0, p));
656  punct_total1 = punct_total2;
657  // 1st code parity bits
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));
661  }
662  // 2nd code parity bits
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));
666  }
667 
668  // nominal rate
669  rate = Period / static_cast<double>(punct_total);
671 }
672 
673 
675 {
676  if(nominal) return rate;
677  else {
678  if(Period == 0)
679  return static_cast<double>(Nuncoded) / Ncoded;
680  else
681  return static_cast<double>(Nuncoded) / pNcoded;
682  }
683 }
684 
685 
686 bvec Punctured_Turbo_Codec::encode(const bvec &input)
687 {
688  bvec coded_bits;
689 
690  encode(input, coded_bits);
691  return coded_bits;
692 }
693 
694 bvec Punctured_Turbo_Codec::decode(const vec &received_signal)
695 {
696  bvec decoded_bits;
697 
698  decode(received_signal, decoded_bits);
699  return decoded_bits;
700 }
701 
702 void Punctured_Turbo_Codec::encode(const bvec &input, bvec &output)
703 {
704  it_assert(Period != 0, "Punctured_Turbo_Codec: puncture matrix is not set");
705 
706  Turbo_Codec::encode(input, output);
707 
708  int i, k, p, j, p1;
709  int no_blocks = output.size() / Ncoded;
710  int count = 0, count_p = 0;
711 
712  for(k = 0; k < no_blocks; k++) {
713  p = 0;
714  // data
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);
719  count_p++;
720  }
721  count++;
722  }
723  p = (p + 1) % Period;
724  }
725  p1 = p;
726 
727  //The first tail:
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);
732  count_p++;
733  }
734  count++;
735  }
736  p = (p + 1) % Period;
737  }
738  //The second tail:
739  for(i = 0; i < m_tail; i++) {
740  // systematic bit
741  if(puncture_matrix(0, p1) == bin(1)) {
742  output(count_p) = output(count);
743  count_p++;
744  }
745  count++;
746  // parity
747  for(j = n1 + 1; j < n_tot; j++) {
748  if(puncture_matrix(j, p1) == bin(1)) {
749  output(count_p) = output(count);
750  count_p++;
751  }
752  count++;
753  }
754  p1 = (p1 + 1) % Period;
755  }
756  } //for
757 
758  output.set_size(count_p, true);
759 }
760 
761 
762 void Punctured_Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations, const bvec &true_bits)
763 {
764  int i, k, p, j, p1;
765  int index = 0, index_p = 0;
766  int no_blocks = received_signal.size() / pNcoded;
767  vec temp(no_blocks * Ncoded);
768 
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++) {
772  p = 0;
773  // data
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);
778  index_p++;
779  }
780  else { // insert dummy symbols with same contribution for 0 and 1
781  temp(index) = 0;
782  }
783  index++;
784  }
785  p = (p + 1) % Period;
786  } // for
787  p1 = p;
788 
789  // 1st code tail
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);
794  index_p++;
795  }
796  else { // insert dummy symbols with same contribution for 0 and 1
797  temp(index) = 0;
798  }
799  index++;
800  }
801  p = (p + 1) % Period;
802  } // for
803  // 2nd code tail
804  for(k = 0; k < m_tail; k++) {
805  // systematic bits
806  if(puncture_matrix(0, p1) == bin(1)) {
807  temp(index) = received_signal(index_p);
808  index_p++;
809  }
810  else { // insert dummy symbols with same contribution for 0 and 1
811  temp(index) = 0;
812  }
813  index++;
814  // parity bits
815  for(j = n1 + 1; j < n_tot; j++) {
816  if(puncture_matrix(j, p1) == bin(1)) {
817  temp(index) = received_signal(index_p);
818  index_p++;
819  }
820  else { // insert dummy symbols with same contribution for 0 and 1
821  temp(index) = 0;
822  }
823  index++;
824  }
825  p1 = (p1 + 1) % Period;
826  } //2nd tail
827  } // for
828 
829  Turbo_Codec::decode(temp, decoded_bits, nrof_used_iterations, true_bits);
830 }
831 
832 void Punctured_Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, const bvec &true_bits)
833 {
834  ivec nrof_used_iterations;
835  decode(received_signal, decoded_bits, nrof_used_iterations, true_bits);
836 }
837 
839 {
840  int i, j, ii, p = 0, p1;
841 
842  if(Period == 0)
843  pNcoded = Ncoded;
844  else {
845  i = (Nuncoded / Period);
846  ii = i * punct_total;
847  i *= Period;
848  for(; i < Nuncoded; i++) {
849  for(j = 0; j < n_tot; j++)
850  if(puncture_matrix(j, p) == bin(1)) ii++;
851  p = (p + 1) % Period;
852  }
853  p1 = p;
854 
855  // first tail
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++;
859  p = (p + 1) % Period;
860  }
861  // second tail
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++;
865  if(j == 0) j += n1;
866  }
867  p1 = (p1 + 1) % Period;
868  }
869 
870  pNcoded = ii;
871  }
872 }
873 
874 int calculate_uncoded_size(Punctured_Turbo_Codec &tc, int punctured_size, int &fill_bits)
875 {
876  // fill_bits - number of bits that must be added at the end of encoded block (in order to obtain punctured_size length vector)
877 
878  int Nuncoded;
879 
880  if(tc.Period == 0) {
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));
883  }
884  else {
885  int i, j, ii, p, p1, no_pblocks;
886  // uncoded - // no_pblocks might be too small
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;
890 
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--;
894  if(ii < 0) break;
895  }
896  Nuncoded = no_pblocks * tc.Period + i;
897 
898  // punctured (from uncoded)
899  no_pblocks = (Nuncoded / tc.Period);
900  ii = no_pblocks * tc.punct_total;
901  p = 0;
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++;
905  p = (p + 1) % tc.Period;
906  }
907  p1 = p;
908  // first tail
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;
913  }
914  // second tail
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;
919  }
920  p1 = (p1 + 1) % tc.Period;
921  }
922  fill_bits = punctured_size - ii;
923  }
924 
925  return Nuncoded;
926 }
927 
928 
929 // -------------------------------------------------------------------------------------
930 // Special interleaver sequence generators
931 // -------------------------------------------------------------------------------------
932 
933 ivec wcdma_turbo_interleaver_sequence(int interleaver_size)
934 {
935  const int MAX_INTERLEAVER_SIZE = 5114;
936  const int MIN_INTERLEAVER_SIZE = 40;
937  int K; //Interleaver size
938  int R; //Number of rows of rectangular matrix
939  int C; //Number of columns of rectangular matrix
940  int p; //Prime number
941  int v; //Primitive root
942  ivec s; //Base sequence for intra-row permutation
943  ivec q; //Minimum prime integers
944  ivec r; //Permuted prime integers
945  ivec T; //Inter-row permutation pattern
946  imat U; //Intra-row permutation patter
947  ivec I; //The interleaver sequence
948  ivec primes, roots, Pat1, Pat2, Pat3, Pat4, Isort;
949  int i, j, qj, temp, row, col, index, count;
950 
951  if(interleaver_size > MAX_INTERLEAVER_SIZE) {
952 
953  I = sort_index(randu(interleaver_size));
954  return I;
955 
956  }
957  else {
958 
959  p = 0;
960  v = 0;
961 
962  //Check the range of the 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");
965 
966  K = interleaver_size;
967 
968  //Definitions of primes and associated primitive roots:
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";
971 
972  //Determine R
973  if((K >= 40) && (K <= 159)) {
974  R = 5;
975  }
976  else if(((K >= 160) && (K <= 200)) || ((K >= 481) && (K <= 530))) {
977  R = 10;
978  }
979  else {
980  R = 20;
981  }
982 
983  //Determine C
984  if((K >= 481) && (K <= 530)) {
985  p = 53;
986  v = 2;
987  C = p;
988  }
989  else {
990  //Find minimum prime p such that (p+1) - K/R >= 0 ...
991  for(i = 0; i < primes.length(); i++) {
992  if((double(primes(i) + 1) - double(K) / double(R)) >= 0.0) {
993  p = primes(i);
994  v = roots(i);
995  break;
996  }
997  }
998  //... and etermine C such that
999  if((double(p) - double(K) / double(R)) >= 0.0) {
1000  if((double(p) - 1.0 - double(K) / double(R)) >= 0.0) {
1001  C = p - 1;
1002  }
1003  else {
1004  C = p;
1005  }
1006  }
1007  else {
1008  C = p + 1;
1009  }
1010  }
1011 
1012  //Construct the base sequencs s for intra-row permutaions
1013  s.set_size(p - 1, false);
1014  s.clear();
1015  s(0) = 1;
1016  for(i = 1; i <= (p - 2); i++) {
1017  s(i) = mod(v * s(i - 1), p);
1018  }
1019 
1020  //Let q(0) = 1 be the first prime integer in {q(j)}, and select the consecutive
1021  //minimum prime integers {q(j)}, j = 1, 2, ..., (R-1) such that gcd( q(j), p-1) == 1, q(j) > 6, and q(j) > q(j-1)
1022  q.set_size(R, false);
1023  q.clear();
1024  q(0) = 1;
1025  for(j = 1; j <= (R - 1); j++) {
1026  for(i = 0; i < primes.length(); i++) {
1027  qj = primes(i);
1028  if((qj > 6) && (qj > q(j - 1))) {
1029  if(gcd(qj, p - 1) == 1) {
1030  q(j) = qj;
1031  break;
1032  }
1033  }
1034  }
1035  }
1036 
1037  //Definitions of Pat1, Pat2, Pat3, and Pat4:
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";
1041  Pat4 = "4 3 2 1 0";
1042 
1043  //T(j) is the inter-row permutation patters defined as one of the following four
1044  //kinds of patterns: Pat1, Pat2, Pat3, and Pat4 depending on the number of input bits K
1045  if(K >= 3211) {
1046  T = Pat1;
1047  }
1048  else if(K >= 3161) {
1049  T = Pat2;
1050  }
1051  else if(K >= 2481) {
1052  T = Pat1;
1053  }
1054  else if(K >= 2281) {
1055  T = Pat2;
1056  }
1057  else if(K >= 531) {
1058  T = Pat1;
1059  }
1060  else if(K >= 481) {
1061  T = Pat3;
1062  }
1063  else if(K >= 201) {
1064  T = Pat1;
1065  }
1066  else if(K >= 160) {
1067  T = Pat3;
1068  }
1069  else {
1070  T = Pat4;
1071  }
1072 
1073  //Permute {q(j)} to make {r(j)} such that r(T(j)) = q(j), j = 0, 1, ..., (R-1),
1074  //where T(j) indicates the original row position of the j-th permuted row
1075  r.set_size(R, false);
1076  r.clear();
1077  for(j = 0; j <= (R - 1); j++) {
1078  r(T(j)) = q(j);
1079  }
1080 
1081  //U(j,i) is the input bit position of i-th output after the permutation of j-th row
1082  //Perform the j-th (j=0, 1, 2, ..., (R-1)) intra-row permutation as
1083  U.set_size(R, C, false);
1084  U.clear();
1085  if(C == p) {
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));
1089  }
1090  U(j, p - 1) = 0;
1091  }
1092  }
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));
1097  }
1098  U(j, p - 1) = 0;
1099  U(j, p) = p;
1100  }
1101  if(K == (C * R)) {
1102  temp = U(R - 1, p);
1103  U(R - 1, p) = U(R - 1, 0);
1104  U(R - 1, 0) = temp;
1105  }
1106  }
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;
1111  }
1112  }
1113  }
1114 
1115  //Calculate the interleaver sequence:
1116  I.set_size(K, false);
1117  I.clear();
1118  count = 0;
1119  for(i = 0; i < C; i++) {
1120  for(j = 0; j < R; j++) {
1121  row = T(j);
1122  col = U(row, i);
1123  index = row * C + col;
1124  if(index < K) {
1125  I(count) = index;
1126  count++;
1127  }
1128  }
1129  }
1130 
1131  return I;
1132  }
1133 }
1134 
1135 ivec lte_turbo_interleaver_sequence(int interleaver_size)
1136 // for standard see pp. 14 http://www.3gpp.org/FTP/Specs/latest/Rel-10/36_series/36212-a50.zip
1137 {
1138 
1139  //Definitions of block lengths and associated f1 and f2 factors:
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;
1145 
1146  // Check the range of the interleaver size:
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");
1149 
1150  // Check whether the given interleaver size is correct:
1151  int left, right, index, temp;
1152  bool search = true;
1153 
1154  // do a binary search for interleaver_size in block_lengths
1155  left = 0;
1156  right = block_lengths.size() - 1;
1157  temp = 0;
1158  while((search) && (left <= right)) {
1159  index = (left + right) / 2;
1160  temp = block_lengths(index);
1161  if(temp == interleaver_size) {
1162  search = false;
1163  }
1164  else {
1165  if(temp > interleaver_size) {
1166  right = index - 1;
1167  }
1168  else {
1169  left = index + 1;
1170  }
1171  }
1172  }
1173  it_assert(!search, "lte_turbo_interleaver_sequence: The interleaver size is incorrect!");
1174 
1175  // Definitions of key parameters:
1176  int K = interleaver_size; // Interleaver size
1177  int f1_factor = f1_factors(index);
1178  int f2_factor = f2_factors(index);
1179  ivec I(K); //The interleaver sequence
1180 
1181  // Calculate the interleaver sequence:
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);
1184  }
1185 
1186  return I;
1187 }
1188 
1189 
1190 } // namespace itpp
SourceForge Logo

Generated on Sat May 25 2013 16:32:22 for IT++ by Doxygen 1.8.2