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

Generated on Sat Apr 19 11:01:26 2008 for IT++ by Doxygen 1.5.5