IT++ Logo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
turbo.cpp
Go to the documentation of this file.
1 
29 #include <itpp/comm/turbo.h>
30 
31 
32 namespace itpp
33 {
34 
35 void Turbo_Codec::set_parameters(ivec gen1, ivec gen2, int constraint_length, const ivec &interleaver_sequence,
36  int in_iterations, std::string in_metric, double in_logmax_scale_factor,
37  bool in_adaptive_stop, LLR_calc_unit in_llrcalc)
38 {
39  //Set the input parameters:
40  iterations = in_iterations;
41  interleaver_size = interleaver_sequence.size();
42  Nuncoded = interleaver_size;
43  logmax_scale_factor = in_logmax_scale_factor;
44  adaptive_stop = in_adaptive_stop;
45 
46  //Check the decoding metric
47  if (in_metric == "LOGMAX") {
48  metric = "LOGMAX";
49  }
50  else if (in_metric == "LOGMAP") {
51  metric = "LOGMAP";
52  }
53  else if (in_metric == "MAP") {
54  metric = "MAP";
55  }
56  else if (in_metric == "TABLE") {
57  metric = "TABLE";
58  }
59  else {
60  it_error("Turbo_Codec::set_parameters: The decoder metric must be either MAP, LOGMAP or LOGMAX");
61  }
62 
63  if (logmax_scale_factor != 1.0) {
64  it_assert(metric == "LOGMAX", "Turbo_Codec::set_parameters: logmax_scale_factor can only be used together with LOGMAX decoding");
65  }
66 
67  //The RSC Encoders:
68  rscc1.set_generator_polynomials(gen1, constraint_length);
69  rscc2.set_generator_polynomials(gen2, constraint_length);
70  n1 = gen1.length() - 1; //Number of parity bits from rscc1
71  n2 = gen2.length() - 1; //Number of parity bits from rscc2
72  n_tot = 1 + n1 + n2; //Total number of parity bits and systematic bits
73 
74  //Set the number of tail bits:
75  m_tail = constraint_length - 1;
76 
77  //Calculate the number of coded bits per code-block:
78  Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
79 
80  //Set the interleaver sequence
81  bit_interleaver.set_interleaver_depth(interleaver_size);
82  float_interleaver.set_interleaver_depth(interleaver_size);
83  bit_interleaver.set_interleaver_sequence(interleaver_sequence);
84  float_interleaver.set_interleaver_sequence(interleaver_sequence);
85 
86  //Default value of the channel reliability scaling factor is 1
87  Lc = 1.0;
88 
89  // LLR algebra table
90  rscc1.set_llrcalc(in_llrcalc);
91  rscc2.set_llrcalc(in_llrcalc);
92 
93 }
94 
95 void Turbo_Codec::set_interleaver(const ivec &interleaver_sequence)
96 {
97  interleaver_size = interleaver_sequence.size();
98  Nuncoded = interleaver_size;
99 
100  //Calculate the number of coded bits per code-block:
101  Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
102 
103  //Set the interleaver sequence
104  bit_interleaver.set_interleaver_depth(interleaver_size);
105  float_interleaver.set_interleaver_depth(interleaver_size);
106  bit_interleaver.set_interleaver_sequence(interleaver_sequence);
107  float_interleaver.set_interleaver_sequence(interleaver_sequence);
108 }
109 
110 void Turbo_Codec::set_metric(std::string in_metric, double in_logmax_scale_factor, LLR_calc_unit in_llrcalc)
111 {
112  logmax_scale_factor = in_logmax_scale_factor;
113 
114  //Check the decoding metric
115  if (in_metric == "LOGMAX") {
116  metric = "LOGMAX";
117  }
118  else if (in_metric == "LOGMAP") {
119  metric = "LOGMAP";
120  }
121  else if (in_metric == "MAP") {
122  metric = "MAP";
123  }
124  else if (in_metric == "TABLE") {
125  metric = "TABLE";
126  }
127  else {
128  it_error("Turbo_Codec::set_metric: The decoder metric must be either MAP, LOGMAP or LOGMAX");
129  }
130 
131  rscc1.set_llrcalc(in_llrcalc);
132  rscc2.set_llrcalc(in_llrcalc);
133 }
134 
135 void Turbo_Codec::set_iterations(int in_iterations)
136 {
137  iterations = in_iterations;
138 }
139 
140 void Turbo_Codec::set_adaptive_stop(bool in_adaptive_stop)
141 {
142  adaptive_stop = in_adaptive_stop;
143 }
144 
145 void Turbo_Codec::set_awgn_channel_parameters(double in_Ec, double in_N0)
146 {
147  Ec = in_Ec;
148  N0 = in_N0;
149  Lc = 4.0 * std::sqrt(Ec) / N0;
150 }
151 
153 {
154  Lc = in_Lc;
155 }
156 
157 
158 void Turbo_Codec::encode(const bvec &input, bvec &output)
159 {
160  //Local variables:
161  int i, k, j, no_blocks;
162  int count;
163  bvec input_bits, in1, in2, tail1, tail2, out;
164  bmat parity1, parity2;
165 
166  //Initializations:
167  no_blocks = input.length() / Nuncoded;
168  output.set_size(no_blocks*Ncoded, false);
169 
170  //Set the bit counter to zero:
171  count = 0;
172 
173  //Encode all code blocks:
174  for (i = 0; i < no_blocks; i++) {
175 
176  //Encode one block
177  input_bits = input.mid(i * Nuncoded, Nuncoded);
178  encode_block(input_bits, in1, in2, parity1, parity2);
179 
180  //The data part:
181  for (k = 0; k < Nuncoded; k++) {
182  output(count) = in1(k);
183  count++; //Systematic bits
184  for (j = 0; j < n1; j++) { output(count) = parity1(k, j); count++; } //Parity-1 bits
185  for (j = 0; j < n2; j++) { output(count) = parity2(k, j); count++; } //Parity-2 bits
186  }
187 
188  //The first tail:
189  for (k = 0; k < m_tail; k++) {
190  output(count) = in1(Nuncoded + k);
191  count++; //First systematic tail bit
192  for (j = 0; j < n1; j++) { output(count) = parity1(Nuncoded + k, j); count++; } //Parity-1 tail bits
193  }
194 
195  //The second tail:
196  for (k = 0; k < m_tail; k++) {
197  output(count) = in2(Nuncoded + k);
198  count++; //Second systematic tail bit
199  for (j = 0; j < n2; j++) { output(count) = parity2(Nuncoded + k, j); count++; } //Parity-2 tail bits
200  }
201 
202  }
203 
204 }
205 
206 void Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, const bvec &true_bits)
207 {
208  ivec nrof_used_iterations;
209  decode(received_signal, decoded_bits, nrof_used_iterations, true_bits);
210 }
211 
212 void Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations,
213  const bvec &true_bits)
214 {
215 
216  if ((n1 == 1) && (n2 == 1) && (metric != "MAP")) {
217  //This is a speed optimized decoder for R=1/3 (log domain metrics only)
218  decode_n3(received_signal, decoded_bits, nrof_used_iterations, true_bits);
219  }
220  else {
221 
222  //Local variables:
223  vec rec, rec_syst1, rec_syst2;
224  mat rec_parity1, rec_parity2;
225  bmat decoded_bits_i;
226  int no_blocks, i, j, k, nrof_used_iterations_i;
227  int count;
228  bool CHECK_TRUE_BITS;
229 
230  //Initilaizations:
231  no_blocks = received_signal.length() / Ncoded;
232  decoded_bits.set_size(no_blocks * Nuncoded, false);
233  decoded_bits_i.set_size(iterations, no_blocks * Nuncoded, false);
234  rec_syst1.set_size(Nuncoded + m_tail, false);
235  rec_syst2.set_size(Nuncoded + m_tail, false);
236  rec_syst2.clear();
237  rec_parity1.set_size(Nuncoded + m_tail, n1, false);
238  rec_parity2.set_size(Nuncoded + m_tail, n2, false);
239  nrof_used_iterations.set_size(no_blocks, false);
240 
241  //Check the vector true_bits:
242  if (true_bits.size() > 1) {
243  it_assert(true_bits.size() == (Nuncoded * no_blocks), "Turbo_Codec::decode: Wrong size of input vectors");
244  CHECK_TRUE_BITS = true;
245  }
246  else {
247  CHECK_TRUE_BITS = false;
248  }
249 
250  //Set the bit counter to zero:
251  count = 0;
252 
253  //Itterate over all received code blocks:
254  for (i = 0; i < no_blocks; i++) {
255 
256  //The data part:
257  for (k = 0; k < Nuncoded; k++) {
258  rec_syst1(k) = received_signal(count);
259  count++; //Systematic bit
260  for (j = 0; j < n1; j++) { rec_parity1(k, j) = received_signal(count); count++; } //Parity-1 bits
261  for (j = 0; j < n2; j++) { rec_parity2(k, j) = received_signal(count); count++; } //Parity-2 bits
262  }
263 
264  //The first tail:
265  for (k = 0; k < m_tail; k++) {
266  rec_syst1(Nuncoded + k) = received_signal(count);
267  count++; //Tail 1 systematic bit
268  for (j = 0; j < n1; j++) { rec_parity1(Nuncoded + k, j) = received_signal(count); count++; } //Tail 1 parity-1 bits
269  }
270 
271  //The second tail:
272  for (k = 0; k < m_tail; k++) {
273  rec_syst2(Nuncoded + k) = received_signal(count);
274  count++; //Tail2 systematic bit
275  for (j = 0; j < n2; j++) { rec_parity2(Nuncoded + k, j) = received_signal(count); count++; } //Tali2 parity-2 bits
276  }
277 
278  //Scale the input data if necessary:
279  if (Lc != 1.0) {
280  rec_syst1 *= Lc;
281  rec_syst2 *= Lc;
282  rec_parity1 *= Lc;
283  rec_parity2 *= Lc;
284  }
285 
286  //Decode the block:
287  if (CHECK_TRUE_BITS) {
288  decode_block(rec_syst1, rec_syst2, rec_parity1, rec_parity2, decoded_bits_i,
289  nrof_used_iterations_i, true_bits.mid(i*Nuncoded, Nuncoded));
290  nrof_used_iterations(i) = nrof_used_iterations_i;
291  }
292  else {
293  decode_block(rec_syst1, rec_syst2, rec_parity1, rec_parity2, decoded_bits_i, nrof_used_iterations_i);
294  nrof_used_iterations(i) = nrof_used_iterations_i;
295  }
296 
297  //Put the decoded bits in the output vector:
298  decoded_bits.replace_mid(i*Nuncoded, decoded_bits_i.get_row(iterations - 1));
299 
300  }
301 
302  }
303 
304 }
305 
306 void Turbo_Codec::encode_block(const bvec &input, bvec &in1, bvec &in2, bmat &parity1, bmat &parity2)
307 {
308  //Local variables:
309  bvec tail1, tail2, interleaved_input;
310 
311  //Error check:
312  it_assert(input.length() == Nuncoded, "Turbo_Codec::encode_block: Parameter error in Nuncoded.");
313 
314  //Initializations:
315  tail1.set_size(m_tail, false);
316  tail1.clear();
317  tail2.set_size(m_tail, false);
318  tail2.clear();
319  parity1.set_size(Nuncoded + m_tail, n1, false);
320  parity1.clear();
321  parity2.set_size(Nuncoded + m_tail, n2, false);
322  parity2.clear();
323  interleaved_input.set_size(Nuncoded, false);
324  interleaved_input.clear();
325 
326  //The first encoder:
327  rscc1.encode_tail(input, tail1, parity1);
328 
329  //The interleaver:
330  bit_interleaver.interleave(input, interleaved_input);
331 
332  //The second encoder:
333  rscc2.encode_tail(interleaved_input, tail2, parity2);
334 
335  //The input vectors used to the two constituent encoders:
336  in1 = concat(input, tail1);
337  in2 = concat(interleaved_input, tail2);
338 
339 }
340 
341 void Turbo_Codec::decode_block(const vec &rec_syst1, const vec &rec_syst2, const mat &rec_parity1,
342  const mat &rec_parity2, bmat &decoded_bits_i, int &nrof_used_iterations_i,
343  const bvec &true_bits)
344 {
345  //Local variables:
346  int i;
347  int count, l, k;
348  vec extrinsic_input, extrinsic_output, int_rec_syst1, int_rec_syst, tmp;
349  vec deint_rec_syst2, rec_syst, sub_rec_syst, Le12, Le21, Le12_int, Le21_int, L, tail1, tail2;
350  bool CHECK_TRUE_BITS, CONTINUE;
351 
352  //Size initializations:
353  decoded_bits_i.set_size(iterations, Nuncoded, false);
354  Le12.set_size(Nuncoded + m_tail, false);
355  Le21.set_size(Nuncoded + m_tail, false);
356  Le21.zeros();
357 
358  //Calculate the interleaved and the deinterleaved sequences:
359  float_interleaver.interleave(rec_syst1.left(interleaver_size), int_rec_syst1);
360  float_interleaver.deinterleave(rec_syst2.left(interleaver_size), deint_rec_syst2);
361 
362  //Combine the results from rec_syst1 and rec_syst2 (in case some bits are transmitted several times)
363  rec_syst = rec_syst1.left(interleaver_size) + deint_rec_syst2;
364  int_rec_syst = rec_syst2.left(interleaver_size) + int_rec_syst1;
365 
366  //Get the two tails
367  tail1 = rec_syst1.right(m_tail);
368  tail2 = rec_syst2.right(m_tail);
369 
370  //Form the input vectors (including tails) to the two decoders:
371  rec_syst = concat(rec_syst, tail1);
372  int_rec_syst = concat(int_rec_syst, tail2);
373 
374  // Check the vector true_bits
375  if (true_bits.size() > 1) {
376  it_assert(true_bits.size() == Nuncoded, "Turbo_Codec::decode_block: Illegal size of input vector true_bits");
377  CHECK_TRUE_BITS = true;
378  }
379  else {
380  CHECK_TRUE_BITS = false;
381  }
382 
383  if (CHECK_TRUE_BITS) {
384  it_assert(adaptive_stop == false,
385  "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
386  }
387 
388  // Do the iterative decoding:
389  nrof_used_iterations_i = iterations;
390  for (i = 0; i < iterations; i++) {
391 
392  // Decode Code 1
393  if (metric == "MAP") {
394  rscc1.map_decode(rec_syst, rec_parity1, Le21, Le12, true);
395  }
396  else if ((metric == "LOGMAX") || (metric == "LOGMAP") || (metric == "TABLE")) {
397  rscc1.log_decode(rec_syst, rec_parity1, Le21, Le12, true, metric);
398  if (logmax_scale_factor != 1.0) {
399  Le12 *= logmax_scale_factor;
400  }
401  }
402  else {
403  it_error("Turbo_Codec::decode_block: Illegal metric value");
404  }
405 
406  // Interleave the extrinsic information:
407  float_interleaver.interleave(Le12.left(interleaver_size), tmp);
408  Le12_int = concat(tmp, zeros(Le12.size() - interleaver_size));
409 
410  // Decode Code 2
411  if (metric == "MAP") {
412  rscc2.map_decode(int_rec_syst, rec_parity2, Le12_int, Le21_int, true);
413  }
414  else if ((metric == "LOGMAX") || (metric == "LOGMAP") || (metric == "TABLE")) {
415  rscc2.log_decode(int_rec_syst, rec_parity2, Le12_int, Le21_int, true, metric);
416  if (logmax_scale_factor != 1.0) {
417  Le21_int *= logmax_scale_factor;
418  }
419  }
420  else {
421  it_error("Turbo_Codec::decode_block: Illegal metric value");
422  }
423 
424  // De-interleave the extrinsic information:
425  float_interleaver.deinterleave(Le21_int.left(interleaver_size), tmp);
426  Le21 = concat(tmp, zeros(Le21_int.size() - interleaver_size));
427 
428  // Take bit decisions
429  L = rec_syst + Le21 + Le12;
430  count = 0;
431  for (l = 0; l < Nuncoded; l++) {
432  (L(l) > 0.0) ? (decoded_bits_i(i, count) = bin(0)) : (decoded_bits_i(i, count) = bin(1));
433  count++;
434  }
435 
436  //Check if it is possible to stop iterating early:
437  CONTINUE = true;
438  if (i < (iterations - 1)) {
439 
440  if (CHECK_TRUE_BITS) {
441  CONTINUE = false;
442  for (k = 0; k < Nuncoded; k++) { if (true_bits(k) != decoded_bits_i(i, k)) { CONTINUE = true; break; } }
443  }
444 
445  if ((adaptive_stop) && (i > 0)) {
446  CONTINUE = false;
447  for (k = 0; k < Nuncoded; k++) { if (decoded_bits_i(i - 1, k) != decoded_bits_i(i, k)) { CONTINUE = true; break; } }
448  }
449 
450  }
451 
452  //Check if iterations shall continue:
453  if (CONTINUE == false) {
454  //Copy the results from current iteration to all following iterations:
455  for (k = (i + 1); k < iterations; k++) {
456  decoded_bits_i.set_row(k, decoded_bits_i.get_row(i));
457  nrof_used_iterations_i = i + 1;
458  }
459  break;
460  }
461 
462  }
463 
464 }
465 
466 void Turbo_Codec::decode_n3(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations,
467  const bvec &true_bits)
468 {
469  //Local variables:
470  vec rec, rec_syst1, int_rec_syst1, rec_syst2;
471  vec rec_parity1, rec_parity2;
472  vec extrinsic_input, extrinsic_output, Le12, Le21, Le12_int, Le21_int, L;
473  bvec temp_decoded_bits;
474  int no_blocks, i, j, k, l, nrof_used_iterations_i;
475  int count, count_out;
476  bool CHECK_TRUE_BITS, CONTINUE;
477 
478  //Initializations:
479  no_blocks = received_signal.length() / Ncoded;
480  decoded_bits.set_size(no_blocks * Nuncoded, false);
481  rec_syst1.set_size(Nuncoded + m_tail, false);
482  rec_syst2.set_size(Nuncoded + m_tail, false);
483  rec_syst2.clear();
484  rec_parity1.set_size(Nuncoded + m_tail, false);
485  rec_parity2.set_size(Nuncoded + m_tail, false);
486  temp_decoded_bits.set_size(Nuncoded, false);
487  decoded_bits_previous_iteration.set_size(Nuncoded, false);
488  nrof_used_iterations.set_size(no_blocks, false);
489 
490  //Size initializations:
491  Le12.set_size(Nuncoded, false);
492  Le21.set_size(Nuncoded, false);
493 
494  //Set the bit counter to zero:
495  count = 0;
496  count_out = 0;
497 
498  // Check the vector true_bits
499  if (true_bits.size() > 1) {
500  it_assert(true_bits.size() == Nuncoded*no_blocks, "Turbo_Codec::decode_n3: Illegal size of input vector true_bits");
501  CHECK_TRUE_BITS = true;
502  }
503  else {
504  CHECK_TRUE_BITS = false;
505  }
506 
507  if (CHECK_TRUE_BITS) {
508  it_assert(adaptive_stop == false,
509  "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
510  }
511 
512  //Iterate over all received code blocks:
513  for (i = 0; i < no_blocks; i++) {
514 
515  //Reset extrinsic data:
516  Le21.zeros();
517 
518  //The data part:
519  for (k = 0; k < Nuncoded; k++) {
520  rec_syst1(k) = received_signal(count);
521  count++; //Systematic bit
522  rec_parity1(k) = received_signal(count);
523  count++; //Parity-1 bits
524  rec_parity2(k) = received_signal(count);
525  count++; //Parity-2 bits
526  }
527 
528  //The first tail:
529  for (k = 0; k < m_tail; k++) {
530  rec_syst1(Nuncoded + k) = received_signal(count);
531  count++; //Tail 1 systematic bit
532  rec_parity1(Nuncoded + k) = received_signal(count);
533  count++; //Tail 1 parity-1 bits
534  }
535 
536  //The second tail:
537  for (k = 0; k < m_tail; k++) {
538  rec_syst2(Nuncoded + k) = received_signal(count);
539  count++; //Tail2 systematic bit
540  rec_parity2(Nuncoded + k) = received_signal(count);
541  count++; //Tali2 parity-2 bits
542  }
543 
544  float_interleaver.interleave(rec_syst1.left(Nuncoded), int_rec_syst1);
545  rec_syst2.replace_mid(0, int_rec_syst1);
546 
547  //Scale the input data if necessary:
548  if (Lc != 1.0) {
549  rec_syst1 *= Lc;
550  rec_syst2 *= Lc;
551  rec_parity1 *= Lc;
552  rec_parity2 *= Lc;
553  }
554 
555  //Decode the block:
556  CONTINUE = true;
557  nrof_used_iterations_i = iterations;
558  for (j = 0; j < iterations; j++) {
559 
560  rscc1.log_decode_n2(rec_syst1, rec_parity1, Le21, Le12, true, metric);
561  if (logmax_scale_factor != 1.0) { Le12 *= logmax_scale_factor; }
562  float_interleaver.interleave(Le12, Le12_int);
563 
564  rscc2.log_decode_n2(rec_syst2, rec_parity2, Le12_int, Le21_int, true, metric);
565  if (logmax_scale_factor != 1.0) { Le21_int *= logmax_scale_factor; }
566  float_interleaver.deinterleave(Le21_int, Le21);
567 
568  if (adaptive_stop) {
569  L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
570  for (l = 0; l < Nuncoded; l++) {(L(l) > 0.0) ? (temp_decoded_bits(l) = bin(0)) : (temp_decoded_bits(l) = bin(1)); }
571  if (j == 0) { decoded_bits_previous_iteration = temp_decoded_bits; }
572  else {
573  if (temp_decoded_bits == decoded_bits_previous_iteration) {
574  CONTINUE = false;
575  }
576  else if (j < (iterations - 1)) {
577  decoded_bits_previous_iteration = temp_decoded_bits;
578  }
579  }
580  }
581 
582  if (CHECK_TRUE_BITS) {
583  L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
584  for (l = 0; l < Nuncoded; l++) {(L(l) > 0.0) ? (temp_decoded_bits(l) = bin(0)) : (temp_decoded_bits(l) = bin(1)); }
585  if (temp_decoded_bits == true_bits.mid(i*Nuncoded, Nuncoded)) {
586  CONTINUE = false;
587  }
588  }
589 
590  if (CONTINUE == false) { nrof_used_iterations_i = j + 1; break; }
591 
592  }
593 
594  //Take final bit decisions
595  L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
596  for (l = 0; l < Nuncoded; l++) {
597  (L(l) > 0.0) ? (decoded_bits(count_out) = bin(0)) : (decoded_bits(count_out) = bin(1));
598  count_out++;
599  }
600 
601  nrof_used_iterations(i) = nrof_used_iterations_i;
602 
603  }
604 
605 }
606 
607 ivec wcdma_turbo_interleaver_sequence(int interleaver_size)
608 {
609  const int MAX_INTERLEAVER_SIZE = 5114;
610  const int MIN_INTERLEAVER_SIZE = 40;
611  int K; //Interleaver size
612  int R; //Number of rows of rectangular matrix
613  int C; //Number of columns of rectangular matrix
614  int p; //Prime number
615  int v; //Primitive root
616  ivec s; //Base sequence for intra-row permutation
617  ivec q; //Minimum prime integers
618  ivec r; //Permuted prime integers
619  ivec T; //Inter-row permutation pattern
620  imat U; //Intra-row permutation patter
621  ivec I; //The interleaver sequence
622  ivec primes, roots, Pat1, Pat2, Pat3, Pat4, Isort;
623  int i, j, qj, temp, row, col, index, count;
624 
625  if (interleaver_size > MAX_INTERLEAVER_SIZE) {
626 
627  I = sort_index(randu(interleaver_size));
628  return I;
629 
630  }
631  else {
632 
633  p = 0;
634  v = 0;
635 
636  //Check the range of the interleaver size:
637  it_assert(interleaver_size <= MAX_INTERLEAVER_SIZE, "wcdma_turbo_interleaver_sequence: The interleaver size is to large");
638  it_assert(interleaver_size >= MIN_INTERLEAVER_SIZE, "wcdma_turbo_interleaver_sequence: The interleaver size is to small");
639 
640  K = interleaver_size;
641 
642  //Definitions of primes and associated primitive roots:
643  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";
644  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";
645 
646  //Determine R
647  if ((K >= 40) && (K <= 159)) {
648  R = 5;
649  }
650  else if (((K >= 160) && (K <= 200)) || ((K >= 481) && (K <= 530))) {
651  R = 10;
652  }
653  else {
654  R = 20;
655  }
656 
657  //Determine C
658  if ((K >= 481) && (K <= 530)) {
659  p = 53;
660  v = 2;
661  C = p;
662  }
663  else {
664  //Find minimum prime p such that (p+1) - K/R >= 0 ...
665  for (i = 0; i < primes.length(); i++) {
666  if ((double(primes(i) + 1) - double(K) / double(R)) >= 0.0) {
667  p = primes(i);
668  v = roots(i);
669  break;
670  }
671  }
672  //... and etermine C such that
673  if ((double(p) - double(K) / double(R)) >= 0.0) {
674  if ((double(p) - 1.0 - double(K) / double(R)) >= 0.0) {
675  C = p - 1;
676  }
677  else {
678  C = p;
679  }
680  }
681  else {
682  C = p + 1;
683  }
684  }
685 
686  //Construct the base sequencs s for intra-row permutaions
687  s.set_size(p - 1, false);
688  s.clear();
689  s(0) = 1;
690  for (i = 1; i <= (p - 2); i++) {
691  s(i) = mod(v * s(i - 1), p);
692  }
693 
694  //Let q(0) = 1 be the first prime integer in {q(j)}, and select the consecutive
695  //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)
696  q.set_size(R, false);
697  q.clear();
698  q(0) = 1;
699  for (j = 1; j <= (R - 1); j++) {
700  for (i = 0; i < primes.length(); i++) {
701  qj = primes(i);
702  if ((qj > 6) && (qj > q(j - 1))) {
703  if (gcd(qj, p - 1) == 1) {
704  q(j) = qj;
705  break;
706  }
707  }
708  }
709  }
710 
711  //Definitions of Pat1, Pat2, Pat3, and Pat4:
712  Pat1 = "19 9 14 4 0 2 5 7 12 18 10 8 13 17 3 1 16 6 15 11";
713  Pat2 = "19 9 14 4 0 2 5 7 12 18 16 13 17 15 3 1 6 11 8 10";
714  Pat3 = "9 8 7 6 5 4 3 2 1 0";
715  Pat4 = "4 3 2 1 0";
716 
717  //T(j) is the inter-row permutation patters defined as one of the following four
718  //kinds of patterns: Pat1, Pat2, Pat3, and Pat4 depending on the number of input bits K
719  if (K >= 3211) {
720  T = Pat1;
721  }
722  else if (K >= 3161) {
723  T = Pat2;
724  }
725  else if (K >= 2481) {
726  T = Pat1;
727  }
728  else if (K >= 2281) {
729  T = Pat2;
730  }
731  else if (K >= 531) {
732  T = Pat1;
733  }
734  else if (K >= 481) {
735  T = Pat3;
736  }
737  else if (K >= 201) {
738  T = Pat1;
739  }
740  else if (K >= 160) {
741  T = Pat3;
742  }
743  else {
744  T = Pat4;
745  }
746 
747  //Permute {q(j)} to make {r(j)} such that r(T(j)) = q(j), j = 0, 1, ..., (R-1),
748  //where T(j) indicates the original row position of the j-th permuted row
749  r.set_size(R, false);
750  r.clear();
751  for (j = 0; j <= (R - 1); j++) {
752  r(T(j)) = q(j);
753  }
754 
755  //U(j,i) is the input bit position of i-th output after the permutation of j-th row
756  //Perform the j-th (j=0, 1, 2, ..., (R-1)) intra-row permutation as
757  U.set_size(R, C, false);
758  U.clear();
759  if (C == p) {
760  for (j = 0; j <= (R - 1); j++) {
761  for (i = 0; i <= (p - 2); i++) {
762  U(j, i) = s(mod(i * r(j), p - 1));
763  }
764  U(j, p - 1) = 0;
765  }
766  }
767  else if (C == (p + 1)) {
768  for (j = 0; j <= (R - 1); j++) {
769  for (i = 0; i <= (p - 2); i++) {
770  U(j, i) = s(mod(i * r(j), p - 1));
771  }
772  U(j, p - 1) = 0;
773  U(j, p) = p;
774  }
775  if (K == (C*R)) {
776  temp = U(R - 1, p);
777  U(R - 1, p) = U(R - 1, 0);
778  U(R - 1, 0) = temp;
779  }
780  }
781  else if (C == (p - 1)) {
782  for (j = 0; j <= (R - 1); j++) {
783  for (i = 0; i <= (p - 2); i++) {
784  U(j, i) = s(mod(i * r(j), p - 1)) - 1;
785  }
786  }
787  }
788 
789  //Calculate the interleaver sequence:
790  I.set_size(K, false);
791  I.clear();
792  count = 0;
793  for (i = 0; i < C; i++) {
794  for (j = 0; j < R; j++) {
795  row = T(j);
796  col = U(row, i);
797  index = row * C + col;
798  if (index < K) {
799  I(count) = index;
800  count++;
801  }
802  }
803  }
804 
805  return I;
806  }
807 }
808 
809 } // namespace itpp
SourceForge Logo

Generated on Fri Mar 21 2014 17:14:13 for IT++ by Doxygen 1.8.1.2