IT++ Logo

turbo.cpp

Go to the documentation of this file.
00001 
00030 #include <itpp/comm/turbo.h>
00031 
00032 
00033 namespace itpp
00034 {
00035 
00036 void Turbo_Codec::set_parameters(ivec gen1, ivec gen2, int constraint_length, const ivec &interleaver_sequence,
00037                                  int in_iterations, std::string in_metric, double in_logmax_scale_factor,
00038                                  bool in_adaptive_stop,  LLR_calc_unit in_llrcalc)
00039 {
00040   //Set the input parameters:
00041   iterations          = in_iterations;
00042   interleaver_size    = interleaver_sequence.size();
00043   Nuncoded            = interleaver_size;
00044   logmax_scale_factor = in_logmax_scale_factor;
00045   adaptive_stop       = in_adaptive_stop;
00046 
00047   //Check the decoding metric
00048   if (in_metric == "LOGMAX") {
00049     metric = "LOGMAX";
00050   }
00051   else if (in_metric == "LOGMAP") {
00052     metric = "LOGMAP";
00053   }
00054   else if (in_metric == "MAP") {
00055     metric = "MAP";
00056   }
00057   else if (in_metric == "TABLE") {
00058     metric = "TABLE";
00059   }
00060   else {
00061     it_error("Turbo_Codec::set_parameters: The decoder metric must be either MAP, LOGMAP or LOGMAX");
00062   }
00063 
00064   if (logmax_scale_factor != 1.0) {
00065     it_assert(metric == "LOGMAX", "Turbo_Codec::set_parameters: logmax_scale_factor can only be used together with LOGMAX decoding");
00066   }
00067 
00068   //The RSC Encoders:
00069   rscc1.set_generator_polynomials(gen1, constraint_length);
00070   rscc2.set_generator_polynomials(gen2, constraint_length);
00071   n1 = gen1.length() - 1; //Number of parity bits from rscc1
00072   n2 = gen2.length() - 1; //Number of parity bits from rscc2
00073   n_tot = 1 + n1 + n2;  //Total number of parity bits and systematic bits
00074 
00075   //Set the number of tail bits:
00076   m_tail = constraint_length - 1;
00077 
00078   //Calculate the number of coded bits per code-block:
00079   Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
00080 
00081   //Set the interleaver sequence
00082   bit_interleaver.set_interleaver_depth(interleaver_size);
00083   float_interleaver.set_interleaver_depth(interleaver_size);
00084   bit_interleaver.set_interleaver_sequence(interleaver_sequence);
00085   float_interleaver.set_interleaver_sequence(interleaver_sequence);
00086 
00087   //Default value of the channel reliability scaling factor is 1
00088   Lc = 1.0;
00089 
00090   // LLR algebra table
00091   rscc1.set_llrcalc(in_llrcalc);
00092   rscc2.set_llrcalc(in_llrcalc);
00093 
00094 }
00095 
00096 void Turbo_Codec::set_interleaver(const ivec &interleaver_sequence)
00097 {
00098   interleaver_size = interleaver_sequence.size();
00099   Nuncoded = interleaver_size;
00100 
00101   //Calculate the number of coded bits per code-block:
00102   Ncoded = Nuncoded * n_tot + m_tail * (1 + n1) + m_tail * (1 + n2);
00103 
00104   //Set the interleaver sequence
00105   bit_interleaver.set_interleaver_depth(interleaver_size);
00106   float_interleaver.set_interleaver_depth(interleaver_size);
00107   bit_interleaver.set_interleaver_sequence(interleaver_sequence);
00108   float_interleaver.set_interleaver_sequence(interleaver_sequence);
00109 }
00110 
00111 void Turbo_Codec::set_metric(std::string in_metric, double in_logmax_scale_factor, LLR_calc_unit in_llrcalc)
00112 {
00113   logmax_scale_factor = in_logmax_scale_factor;
00114 
00115   //Check the decoding metric
00116   if (in_metric == "LOGMAX") {
00117     metric = "LOGMAX";
00118   }
00119   else if (in_metric == "LOGMAP") {
00120     metric = "LOGMAP";
00121   }
00122   else if (in_metric == "MAP") {
00123     metric = "MAP";
00124   }
00125   else if (in_metric == "TABLE") {
00126     metric = "TABLE";
00127   }
00128   else {
00129     it_error("Turbo_Codec::set_metric: The decoder metric must be either MAP, LOGMAP or LOGMAX");
00130   }
00131 
00132   rscc1.set_llrcalc(in_llrcalc);
00133   rscc2.set_llrcalc(in_llrcalc);
00134 }
00135 
00136 void Turbo_Codec::set_iterations(int in_iterations)
00137 {
00138   iterations = in_iterations;
00139 }
00140 
00141 void Turbo_Codec::set_adaptive_stop(bool in_adaptive_stop)
00142 {
00143   adaptive_stop = in_adaptive_stop;
00144 }
00145 
00146 void Turbo_Codec::set_awgn_channel_parameters(double in_Ec, double in_N0)
00147 {
00148   Ec = in_Ec;
00149   N0 = in_N0;
00150   Lc = 4.0 * std::sqrt(Ec) / N0;
00151 }
00152 
00153 void Turbo_Codec::set_scaling_factor(double in_Lc)
00154 {
00155   Lc = in_Lc;
00156 }
00157 
00158 
00159 void Turbo_Codec::encode(const bvec &input, bvec &output)
00160 {
00161   //Local variables:
00162   int i, k, j, no_blocks;
00163   int count;
00164   bvec input_bits, in1, in2, tail1, tail2, out;
00165   bmat parity1, parity2;
00166 
00167   //Initializations:
00168   no_blocks = input.length() / Nuncoded;
00169   output.set_size(no_blocks*Ncoded, false);
00170 
00171   //Set the bit counter to zero:
00172   count = 0;
00173 
00174   //Encode all code blocks:
00175   for (i = 0; i < no_blocks; i++) {
00176 
00177     //Encode one block
00178     input_bits = input.mid(i * Nuncoded, Nuncoded);
00179     encode_block(input_bits, in1, in2, parity1, parity2);
00180 
00181     //The data part:
00182     for (k = 0; k < Nuncoded; k++) {
00183       output(count) = in1(k);
00184       count++;                                //Systematic bits
00185       for (j = 0; j < n1; j++) { output(count) = parity1(k, j); count++; } //Parity-1 bits
00186       for (j = 0; j < n2; j++) { output(count) = parity2(k, j); count++; } //Parity-2 bits
00187     }
00188 
00189     //The first tail:
00190     for (k = 0; k < m_tail; k++) {
00191       output(count) = in1(Nuncoded + k);
00192       count++;                                //First systematic tail bit
00193       for (j = 0; j < n1; j++) { output(count) = parity1(Nuncoded + k, j); count++; } //Parity-1 tail bits
00194     }
00195 
00196     //The second tail:
00197     for (k = 0; k < m_tail; k++) {
00198       output(count) = in2(Nuncoded + k);
00199       count++;                                //Second systematic tail bit
00200       for (j = 0; j < n2; j++) { output(count) = parity2(Nuncoded + k, j); count++; } //Parity-2 tail bits
00201     }
00202 
00203   }
00204 
00205 }
00206 
00207 void Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, const bvec &true_bits)
00208 {
00209   ivec nrof_used_iterations;
00210   decode(received_signal, decoded_bits, nrof_used_iterations, true_bits);
00211 }
00212 
00213 void Turbo_Codec::decode(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations,
00214                          const bvec &true_bits)
00215 {
00216 
00217   if ((n1 == 1) && (n2 == 1) && (metric != "MAP")) {
00218     //This is a speed optimized decoder for R=1/3 (log domain metrics only)
00219     decode_n3(received_signal, decoded_bits, nrof_used_iterations, true_bits);
00220   }
00221   else {
00222 
00223     //Local variables:
00224     vec rec, rec_syst1, rec_syst2;
00225     mat rec_parity1, rec_parity2;
00226     bmat decoded_bits_i;
00227     int no_blocks, i, j, k, nrof_used_iterations_i;
00228     int count;
00229     bool CHECK_TRUE_BITS;
00230 
00231     //Initilaizations:
00232     no_blocks = received_signal.length() / Ncoded;
00233     decoded_bits.set_size(no_blocks * Nuncoded, false);
00234     decoded_bits_i.set_size(iterations, no_blocks * Nuncoded, false);
00235     rec_syst1.set_size(Nuncoded + m_tail, false);
00236     rec_syst2.set_size(Nuncoded + m_tail, false);
00237     rec_syst2.clear();
00238     rec_parity1.set_size(Nuncoded + m_tail, n1, false);
00239     rec_parity2.set_size(Nuncoded + m_tail, n2, false);
00240     nrof_used_iterations.set_size(no_blocks, false);
00241 
00242     //Check the vector true_bits:
00243     if (true_bits.size() > 1) {
00244       it_assert(true_bits.size() == (Nuncoded * no_blocks), "Turbo_Codec::decode: Wrong size of input vectors");
00245       CHECK_TRUE_BITS = true;
00246     }
00247     else {
00248       CHECK_TRUE_BITS = false;
00249     }
00250 
00251     //Set the bit counter to zero:
00252     count = 0;
00253 
00254     //Itterate over all received code blocks:
00255     for (i = 0; i < no_blocks; i++) {
00256 
00257       //The data part:
00258       for (k = 0; k < Nuncoded; k++) {
00259         rec_syst1(k) = received_signal(count);
00260         count++;                               //Systematic bit
00261         for (j = 0; j < n1; j++) { rec_parity1(k, j) = received_signal(count); count++; }  //Parity-1 bits
00262         for (j = 0; j < n2; j++) { rec_parity2(k, j) = received_signal(count); count++; }  //Parity-2 bits
00263       }
00264 
00265       //The first tail:
00266       for (k = 0; k < m_tail; k++) {
00267         rec_syst1(Nuncoded + k) = received_signal(count);
00268         count++;                               //Tail 1 systematic bit
00269         for (j = 0; j < n1; j++) { rec_parity1(Nuncoded + k, j) = received_signal(count); count++; }  //Tail 1 parity-1 bits
00270       }
00271 
00272       //The second tail:
00273       for (k = 0; k < m_tail; k++) {
00274         rec_syst2(Nuncoded + k) = received_signal(count);
00275         count++;                              //Tail2 systematic bit
00276         for (j = 0; j < n2; j++) { rec_parity2(Nuncoded + k, j) = received_signal(count); count++; } //Tali2 parity-2 bits
00277       }
00278 
00279       //Scale the input data if necessary:
00280       if (Lc != 1.0) {
00281         rec_syst1 *= Lc;
00282         rec_syst2 *= Lc;
00283         rec_parity1 *= Lc;
00284         rec_parity2 *= Lc;
00285       }
00286 
00287       //Decode the block:
00288       if (CHECK_TRUE_BITS) {
00289         decode_block(rec_syst1, rec_syst2, rec_parity1, rec_parity2, decoded_bits_i,
00290                      nrof_used_iterations_i, true_bits.mid(i*Nuncoded, Nuncoded));
00291         nrof_used_iterations(i) = nrof_used_iterations_i;
00292       }
00293       else {
00294         decode_block(rec_syst1, rec_syst2, rec_parity1, rec_parity2, decoded_bits_i, nrof_used_iterations_i);
00295         nrof_used_iterations(i) = nrof_used_iterations_i;
00296       }
00297 
00298       //Put the decoded bits in the output vector:
00299       decoded_bits.replace_mid(i*Nuncoded, decoded_bits_i.get_row(iterations - 1));
00300 
00301     }
00302 
00303   }
00304 
00305 }
00306 
00307 void Turbo_Codec::encode_block(const bvec &input, bvec &in1, bvec &in2, bmat &parity1, bmat &parity2)
00308 {
00309   //Local variables:
00310   bvec tail1, tail2, interleaved_input;
00311 
00312   //Error check:
00313   it_assert(input.length() == Nuncoded, "Turbo_Codec::encode_block: Parameter error in Nuncoded.");
00314 
00315   //Initializations:
00316   tail1.set_size(m_tail, false);
00317   tail1.clear();
00318   tail2.set_size(m_tail, false);
00319   tail2.clear();
00320   parity1.set_size(Nuncoded + m_tail, n1, false);
00321   parity1.clear();
00322   parity2.set_size(Nuncoded + m_tail, n2, false);
00323   parity2.clear();
00324   interleaved_input.set_size(Nuncoded, false);
00325   interleaved_input.clear();
00326 
00327   //The first encoder:
00328   rscc1.encode_tail(input, tail1, parity1);
00329 
00330   //The interleaver:
00331   bit_interleaver.interleave(input, interleaved_input);
00332 
00333   //The second encoder:
00334   rscc2.encode_tail(interleaved_input, tail2, parity2);
00335 
00336   //The input vectors used to the two constituent encoders:
00337   in1 = concat(input, tail1);
00338   in2 = concat(interleaved_input, tail2);
00339 
00340 }
00341 
00342 void Turbo_Codec::decode_block(const vec &rec_syst1, const vec &rec_syst2, const mat &rec_parity1,
00343                                const mat &rec_parity2, bmat &decoded_bits_i, int &nrof_used_iterations_i,
00344                                const bvec &true_bits)
00345 {
00346   //Local variables:
00347   int i;
00348   int count, l, k;
00349   vec extrinsic_input, extrinsic_output, int_rec_syst1, int_rec_syst, tmp;
00350   vec deint_rec_syst2, rec_syst, sub_rec_syst, Le12, Le21, Le12_int, Le21_int, L, tail1, tail2;
00351   bool CHECK_TRUE_BITS, CONTINUE;
00352 
00353   //Size initializations:
00354   decoded_bits_i.set_size(iterations, Nuncoded, false);
00355   Le12.set_size(Nuncoded + m_tail, false);
00356   Le21.set_size(Nuncoded + m_tail, false);
00357   Le21.zeros();
00358 
00359   //Calculate the interleaved and the deinterleaved sequences:
00360   float_interleaver.interleave(rec_syst1.left(interleaver_size), int_rec_syst1);
00361   float_interleaver.deinterleave(rec_syst2.left(interleaver_size), deint_rec_syst2);
00362 
00363   //Combine the results from rec_syst1 and rec_syst2 (in case some bits are transmitted several times)
00364   rec_syst = rec_syst1.left(interleaver_size) + deint_rec_syst2;
00365   int_rec_syst = rec_syst2.left(interleaver_size) + int_rec_syst1;
00366 
00367   //Get the two tails
00368   tail1 = rec_syst1.right(m_tail);
00369   tail2 = rec_syst2.right(m_tail);
00370 
00371   //Form the input vectors (including tails) to the two decoders:
00372   rec_syst = concat(rec_syst, tail1);
00373   int_rec_syst = concat(int_rec_syst, tail2);
00374 
00375   // Check the vector true_bits
00376   if (true_bits.size() > 1) {
00377     it_assert(true_bits.size() == Nuncoded, "Turbo_Codec::decode_block: Illegal size of input vector true_bits");
00378     CHECK_TRUE_BITS = true;
00379   }
00380   else {
00381     CHECK_TRUE_BITS = false;
00382   }
00383 
00384   if (CHECK_TRUE_BITS) {
00385     it_assert(adaptive_stop == false,
00386               "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
00387   }
00388 
00389   // Do the iterative decoding:
00390   nrof_used_iterations_i = iterations;
00391   for (i = 0; i < iterations; i++) {
00392 
00393     // Decode Code 1
00394     if (metric == "MAP") {
00395       rscc1.map_decode(rec_syst, rec_parity1, Le21, Le12, true);
00396     }
00397     else if ((metric == "LOGMAX") || (metric == "LOGMAP") || (metric == "TABLE")) {
00398       rscc1.log_decode(rec_syst, rec_parity1, Le21, Le12, true, metric);
00399       if (logmax_scale_factor != 1.0) {
00400         Le12 *= logmax_scale_factor;
00401       }
00402     }
00403     else {
00404       it_error("Turbo_Codec::decode_block: Illegal metric value");
00405     }
00406 
00407     // Interleave the extrinsic information:
00408     float_interleaver.interleave(Le12.left(interleaver_size), tmp);
00409     Le12_int = concat(tmp, zeros(Le12.size() - interleaver_size));
00410 
00411     // Decode Code 2
00412     if (metric == "MAP") {
00413       rscc2.map_decode(int_rec_syst, rec_parity2, Le12_int, Le21_int, true);
00414     }
00415     else if ((metric == "LOGMAX") || (metric == "LOGMAP")  || (metric == "TABLE")) {
00416       rscc2.log_decode(int_rec_syst, rec_parity2, Le12_int, Le21_int, true, metric);
00417       if (logmax_scale_factor != 1.0) {
00418         Le21_int *= logmax_scale_factor;
00419       }
00420     }
00421     else {
00422       it_error("Turbo_Codec::decode_block: Illegal metric value");
00423     }
00424 
00425     // De-interleave the extrinsic information:
00426     float_interleaver.deinterleave(Le21_int.left(interleaver_size), tmp);
00427     Le21 = concat(tmp, zeros(Le21_int.size() - interleaver_size));
00428 
00429     // Take bit decisions
00430     L = rec_syst + Le21 + Le12;
00431     count = 0;
00432     for (l = 0; l < Nuncoded; l++) {
00433       (L(l) > 0.0) ? (decoded_bits_i(i, count) = bin(0)) : (decoded_bits_i(i, count) = bin(1));
00434       count++;
00435     }
00436 
00437     //Check if it is possible to stop iterating early:
00438     CONTINUE = true;
00439     if (i < (iterations - 1)) {
00440 
00441       if (CHECK_TRUE_BITS) {
00442         CONTINUE = false;
00443         for (k = 0; k < Nuncoded; k++) { if (true_bits(k) != decoded_bits_i(i, k)) { CONTINUE = true; break; } }
00444       }
00445 
00446       if ((adaptive_stop) && (i > 0)) {
00447         CONTINUE = false;
00448         for (k = 0; k < Nuncoded; k++) { if (decoded_bits_i(i - 1, k) != decoded_bits_i(i, k)) { CONTINUE = true; break; } }
00449       }
00450 
00451     }
00452 
00453     //Check if iterations shall continue:
00454     if (CONTINUE == false) {
00455       //Copy the results from current iteration to all following iterations:
00456       for (k = (i + 1); k < iterations; k++) {
00457         decoded_bits_i.set_row(k, decoded_bits_i.get_row(i));
00458         nrof_used_iterations_i = i + 1;
00459       }
00460       break;
00461     }
00462 
00463   }
00464 
00465 }
00466 
00467 void Turbo_Codec::decode_n3(const vec &received_signal, bvec &decoded_bits, ivec &nrof_used_iterations,
00468                             const bvec &true_bits)
00469 {
00470   //Local variables:
00471   vec rec, rec_syst1, int_rec_syst1, rec_syst2;
00472   vec rec_parity1, rec_parity2;
00473   vec extrinsic_input, extrinsic_output, Le12, Le21, Le12_int, Le21_int, L;
00474   bvec temp_decoded_bits;
00475   int no_blocks, i, j, k, l, nrof_used_iterations_i;
00476   int count, count_out;
00477   bool CHECK_TRUE_BITS, CONTINUE;
00478 
00479   //Initializations:
00480   no_blocks = received_signal.length() / Ncoded;
00481   decoded_bits.set_size(no_blocks * Nuncoded, false);
00482   rec_syst1.set_size(Nuncoded + m_tail, false);
00483   rec_syst2.set_size(Nuncoded + m_tail, false);
00484   rec_syst2.clear();
00485   rec_parity1.set_size(Nuncoded + m_tail, false);
00486   rec_parity2.set_size(Nuncoded + m_tail, false);
00487   temp_decoded_bits.set_size(Nuncoded, false);
00488   decoded_bits_previous_iteration.set_size(Nuncoded, false);
00489   nrof_used_iterations.set_size(no_blocks, false);
00490 
00491   //Size initializations:
00492   Le12.set_size(Nuncoded, false);
00493   Le21.set_size(Nuncoded, false);
00494 
00495   //Set the bit counter to zero:
00496   count = 0;
00497   count_out = 0;
00498 
00499   // Check the vector true_bits
00500   if (true_bits.size() > 1) {
00501     it_assert(true_bits.size() == Nuncoded*no_blocks, "Turbo_Codec::decode_n3: Illegal size of input vector true_bits");
00502     CHECK_TRUE_BITS = true;
00503   }
00504   else {
00505     CHECK_TRUE_BITS = false;
00506   }
00507 
00508   if (CHECK_TRUE_BITS) {
00509     it_assert(adaptive_stop == false,
00510               "Turbo_Codec::decode_block: You can not stop iterations both adaptively and on true bits");
00511   }
00512 
00513   //Iterate over all received code blocks:
00514   for (i = 0; i < no_blocks; i++) {
00515 
00516     //Reset extrinsic data:
00517     Le21.zeros();
00518 
00519     //The data part:
00520     for (k = 0; k < Nuncoded; k++) {
00521       rec_syst1(k)   = received_signal(count);
00522       count++; //Systematic bit
00523       rec_parity1(k) = received_signal(count);
00524       count++; //Parity-1 bits
00525       rec_parity2(k) = received_signal(count);
00526       count++; //Parity-2 bits
00527     }
00528 
00529     //The first tail:
00530     for (k = 0; k < m_tail; k++) {
00531       rec_syst1(Nuncoded + k)   = received_signal(count);
00532       count++; //Tail 1 systematic bit
00533       rec_parity1(Nuncoded + k) = received_signal(count);
00534       count++; //Tail 1 parity-1 bits
00535     }
00536 
00537     //The second tail:
00538     for (k = 0; k < m_tail; k++) {
00539       rec_syst2(Nuncoded + k)   = received_signal(count);
00540       count++; //Tail2 systematic bit
00541       rec_parity2(Nuncoded + k) = received_signal(count);
00542       count++; //Tali2 parity-2 bits
00543     }
00544 
00545     float_interleaver.interleave(rec_syst1.left(Nuncoded), int_rec_syst1);
00546     rec_syst2.replace_mid(0, int_rec_syst1);
00547 
00548     //Scale the input data if necessary:
00549     if (Lc != 1.0) {
00550       rec_syst1   *= Lc;
00551       rec_syst2   *= Lc;
00552       rec_parity1 *= Lc;
00553       rec_parity2 *= Lc;
00554     }
00555 
00556     //Decode the block:
00557     CONTINUE = true;
00558     nrof_used_iterations_i = iterations;
00559     for (j = 0; j < iterations; j++) {
00560 
00561       rscc1.log_decode_n2(rec_syst1, rec_parity1, Le21, Le12, true, metric);
00562       if (logmax_scale_factor != 1.0) { Le12 *= logmax_scale_factor; }
00563       float_interleaver.interleave(Le12, Le12_int);
00564 
00565       rscc2.log_decode_n2(rec_syst2, rec_parity2, Le12_int, Le21_int, true, metric);
00566       if (logmax_scale_factor != 1.0) { Le21_int *= logmax_scale_factor; }
00567       float_interleaver.deinterleave(Le21_int, Le21);
00568 
00569       if (adaptive_stop) {
00570         L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
00571         for (l = 0; l < Nuncoded; l++) {(L(l) > 0.0) ? (temp_decoded_bits(l) = bin(0)) : (temp_decoded_bits(l) = bin(1)); }
00572         if (j == 0) { decoded_bits_previous_iteration = temp_decoded_bits; }
00573         else {
00574           if (temp_decoded_bits == decoded_bits_previous_iteration) {
00575             CONTINUE = false;
00576           }
00577           else if (j < (iterations - 1)) {
00578             decoded_bits_previous_iteration = temp_decoded_bits;
00579           }
00580         }
00581       }
00582 
00583       if (CHECK_TRUE_BITS) {
00584         L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
00585         for (l = 0; l < Nuncoded; l++) {(L(l) > 0.0) ? (temp_decoded_bits(l) = bin(0)) : (temp_decoded_bits(l) = bin(1)); }
00586         if (temp_decoded_bits == true_bits.mid(i*Nuncoded, Nuncoded)) {
00587           CONTINUE = false;
00588         }
00589       }
00590 
00591       if (CONTINUE == false) { nrof_used_iterations_i = j + 1; break; }
00592 
00593     }
00594 
00595     //Take final bit decisions
00596     L = rec_syst1.left(Nuncoded) + Le21.left(Nuncoded) + Le12.left(Nuncoded);
00597     for (l = 0; l < Nuncoded; l++) {
00598       (L(l) > 0.0) ? (decoded_bits(count_out) = bin(0)) : (decoded_bits(count_out) = bin(1));
00599       count_out++;
00600     }
00601 
00602     nrof_used_iterations(i) = nrof_used_iterations_i;
00603 
00604   }
00605 
00606 }
00607 
00608 ivec wcdma_turbo_interleaver_sequence(int interleaver_size)
00609 {
00610   const int MAX_INTERLEAVER_SIZE = 5114;
00611   const int MIN_INTERLEAVER_SIZE = 40;
00612   int K;  //Interleaver size
00613   int R;  //Number of rows of rectangular matrix
00614   int C;  //Number of columns of rectangular matrix
00615   int p;  //Prime number
00616   int v;  //Primitive root
00617   ivec s; //Base sequence for intra-row permutation
00618   ivec q; //Minimum prime integers
00619   ivec r; //Permuted prime integers
00620   ivec T; //Inter-row permutation pattern
00621   imat U; //Intra-row permutation patter
00622   ivec I; //The interleaver sequence
00623   ivec primes, roots, Pat1, Pat2, Pat3, Pat4, Isort;
00624   int i, j, qj, temp, row, col, index, count;
00625 
00626   if (interleaver_size > MAX_INTERLEAVER_SIZE) {
00627 
00628     I = sort_index(randu(interleaver_size));
00629     return I;
00630 
00631   }
00632   else {
00633 
00634     p = 0;
00635     v = 0;
00636 
00637     //Check the range of the interleaver size:
00638     it_assert(interleaver_size <= MAX_INTERLEAVER_SIZE, "wcdma_turbo_interleaver_sequence: The interleaver size is to large");
00639     it_assert(interleaver_size >= MIN_INTERLEAVER_SIZE, "wcdma_turbo_interleaver_sequence: The interleaver size is to small");
00640 
00641     K = interleaver_size;
00642 
00643     //Definitions of primes and associated primitive roots:
00644     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";
00645     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";
00646 
00647     //Determine R
00648     if ((K >= 40) && (K <= 159)) {
00649       R = 5;
00650     }
00651     else if (((K >= 160) && (K <= 200)) || ((K >= 481) && (K <= 530))) {
00652       R = 10;
00653     }
00654     else {
00655       R = 20;
00656     }
00657 
00658     //Determine C
00659     if ((K >= 481) && (K <= 530)) {
00660       p = 53;
00661       v = 2;
00662       C = p;
00663     }
00664     else {
00665       //Find minimum prime p such that (p+1) - K/R >= 0 ...
00666       for (i = 0; i < primes.length(); i++) {
00667         if ((double(primes(i) + 1) - double(K) / double(R)) >= 0.0) {
00668           p = primes(i);
00669           v = roots(i);
00670           break;
00671         }
00672       }
00673       //... and etermine C such that
00674       if ((double(p) - double(K) / double(R)) >= 0.0) {
00675         if ((double(p) - 1.0 - double(K) / double(R)) >= 0.0) {
00676           C = p - 1;
00677         }
00678         else {
00679           C = p;
00680         }
00681       }
00682       else {
00683         C = p + 1;
00684       }
00685     }
00686 
00687     //Construct the base sequencs s for intra-row permutaions
00688     s.set_size(p - 1, false);
00689     s.clear();
00690     s(0) = 1;
00691     for (i = 1; i <= (p - 2); i++) {
00692       s(i) = mod(v * s(i - 1), p);
00693     }
00694 
00695     //Let q(0) = 1 be the first prime integer in {q(j)}, and select the consecutive
00696     //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)
00697     q.set_size(R, false);
00698     q.clear();
00699     q(0) = 1;
00700     for (j = 1; j <= (R - 1); j++) {
00701       for (i = 0; i < primes.length(); i++) {
00702         qj = primes(i);
00703         if ((qj > 6) && (qj > q(j - 1))) {
00704           if (gcd(qj, p - 1) == 1) {
00705             q(j) = qj;
00706             break;
00707           }
00708         }
00709       }
00710     }
00711 
00712     //Definitions of Pat1, Pat2, Pat3, and Pat4:
00713     Pat1 = "19 9 14 4 0 2 5 7 12 18 10 8 13 17 3 1 16 6 15 11";
00714     Pat2 = "19 9 14 4 0 2 5 7 12 18 16 13 17 15 3 1 6 11 8 10";
00715     Pat3 = "9 8 7 6 5 4 3 2 1 0";
00716     Pat4 = "4 3 2 1 0";
00717 
00718     //T(j) is the inter-row permutation patters defined as one of the following four
00719     //kinds of patterns: Pat1, Pat2, Pat3, and Pat4 depending on the number of input bits K
00720     if (K >= 3211) {
00721       T = Pat1;
00722     }
00723     else if (K >= 3161) {
00724       T = Pat2;
00725     }
00726     else if (K >= 2481) {
00727       T = Pat1;
00728     }
00729     else if (K >= 2281) {
00730       T = Pat2;
00731     }
00732     else if (K >= 531) {
00733       T = Pat1;
00734     }
00735     else if (K >= 481) {
00736       T = Pat3;
00737     }
00738     else if (K >= 201) {
00739       T = Pat1;
00740     }
00741     else if (K >= 160) {
00742       T = Pat3;
00743     }
00744     else {
00745       T = Pat4;
00746     }
00747 
00748     //Permute {q(j)} to make {r(j)} such that r(T(j)) = q(j), j = 0, 1, ..., (R-1),
00749     //where T(j) indicates the original row position of the j-th permuted row
00750     r.set_size(R, false);
00751     r.clear();
00752     for (j = 0; j <= (R - 1); j++) {
00753       r(T(j)) = q(j);
00754     }
00755 
00756     //U(j,i) is the input bit position of i-th output after the permutation of j-th row
00757     //Perform the j-th (j=0, 1, 2, ..., (R-1)) intra-row permutation as
00758     U.set_size(R, C, false);
00759     U.clear();
00760     if (C == p) {
00761       for (j = 0; j <= (R - 1); j++) {
00762         for (i = 0; i <= (p - 2); i++) {
00763           U(j, i) = s(mod(i * r(j), p - 1));
00764         }
00765         U(j, p - 1) = 0;
00766       }
00767     }
00768     else if (C == (p + 1)) {
00769       for (j = 0; j <= (R - 1); j++) {
00770         for (i = 0; i <= (p - 2); i++) {
00771           U(j, i) = s(mod(i * r(j), p - 1));
00772         }
00773         U(j, p - 1) = 0;
00774         U(j, p) = p;
00775       }
00776       if (K == (C*R)) {
00777         temp = U(R - 1, p);
00778         U(R - 1, p) = U(R - 1, 0);
00779         U(R - 1, 0) = temp;
00780       }
00781     }
00782     else if (C == (p - 1)) {
00783       for (j = 0; j <= (R - 1); j++) {
00784         for (i = 0; i <= (p - 2); i++) {
00785           U(j, i) = s(mod(i * r(j), p - 1)) - 1;
00786         }
00787       }
00788     }
00789 
00790     //Calculate the interleaver sequence:
00791     I.set_size(K, false);
00792     I.clear();
00793     count = 0;
00794     for (i = 0; i < C; i++) {
00795       for (j = 0; j < R; j++) {
00796         row = T(j);
00797         col = U(row, i);
00798         index = row * C + col;
00799         if (index < K) {
00800           I(count) = index;
00801           count++;
00802         }
00803       }
00804     }
00805 
00806     return I;
00807   }
00808 }
00809 
00810 } // namespace itpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Tue Nov 23 08:45:11 2010 for IT++ by Doxygen 1.6.1