/*---------------------------------------------------------------------------* * IT++ * *---------------------------------------------------------------------------* * Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger, * * Tobias Ringström, and Jonas Samuelsson. * * * * Permission to use, copy, modify, and distribute this software and its * * documentation under the terms of the GNU General Public License is hereby * * granted. No representations are made about the suitability of this * * software for any purpose. It is provided "as is" without expressed or * * implied warranty. See the GNU General Public License for more details. * *---------------------------------------------------------------------------*/ /*! \file \brief Implementation of a binary convolutional encoder class. \author Tony Ottosson 951019, Revised completely 980205 1.19 2004/09/03 07:47:28 */ #include "comm/convcode.h" #include "base/binary.h" #include "base/stat.h" #include "base/matfunc.h" namespace itpp { // ----------------- Protected functions ----------------------------- /* The weight of the transition from given state with the input given */ int Convolutional_Code::weight(const int state, const int input) { int i, j, temp, out, w = 0, shiftreg = state; shiftreg = shiftreg | (input << m); for (j=0; j> 1; } w += out; //w += weight_int_table(temp); } return w; } /* The weight (of the reverse code) of the transition from given state with the input given */ int Convolutional_Code::weight_reverse(const int state, const int input) { int i, j, temp, out, w = 0, shiftreg = state; shiftreg = shiftreg | (input << m); for (j=0; j> 1; } w += out; //w += weight_int_table(temp); } return w; } /* The weight of the two paths (input 0 or 1) from given state */ void Convolutional_Code::weight(const int state, int &w0, int &w1) { int i, j, temp, out, shiftreg = state; w0 = 0; w1 = 0; shiftreg = shiftreg | (1 << m); for (j=0; j> 1; } w0 += out; w1 += out ^ (temp & 1); } } /* The weight (of the reverse code) of the two paths (input 0 or 1) from given state */ void Convolutional_Code::weight_reverse(const int state, int &w0, int &w1) { int i, j, temp, out, shiftreg = state; w0 = 0; w1 = 0; shiftreg = shiftreg | (1 << m); for (j=0; j> 1; } w0 += out; w1 += out ^ (temp & 1); } } /* Output on transition (backwards) with input from state */ bvec Convolutional_Code::output_reverse(const int state, const int input) { int j, temp, temp_state; bvec output(n); temp_state = (state<<1) | input; for (j=0; j> 1; one_output(j) = xor_int_table(temp) ^ one_bit; zero_output(j) = xor_int_table(temp); } } /* Output on transition (backwards) with input from state */ void Convolutional_Code::output_reverse(const int state, int &zero_output, int &one_output) { int j, temp, temp_state; bin one_bit; zero_output=0, one_output=0; temp_state = (state<<1) | 1; for (j=0; j> 1; one_output = (one_output<<1) | int(xor_int_table(temp) ^ one_bit); zero_output = (zero_output<<1) | int(xor_int_table(temp)); } } /* Output on transition (backwards) with input from state */ void Convolutional_Code::calc_metric_reverse(const int state, const vec &rx_codeword, double &zero_metric, double &one_metric) { int j, temp, temp_state; bin one_bit; one_metric = zero_metric = 0; temp_state = (state<<1) | 1; for (j=0; j> 1; //one_output(j) = xor_int_table(temp) ^ one_bit; //zero_output(j) = xor_int_table(temp); one_metric += (2 * int(xor_int_table(temp) ^ one_bit) - 1 ) * rx_codeword(j); zero_metric += (2 * int(xor_int_table(temp)) - 1 ) * rx_codeword(j); } } // calculates metrics for all codewords (2^n of them) in natural order void Convolutional_Code::calc_metric(const vec &rx_codeword, vec &delta_metrics) { int i, j, no_outputs = pow2i(n), temp=0, no_loop = pow2i(n-1); int mask = (no_outputs-1); delta_metrics.set_size(no_outputs, false); if (no_outputs <= no_states) { for (i=0; i=0; j--) { if (temp&1) delta_metrics(i) += rx_codeword(j); else delta_metrics(i) -= rx_codeword(j); temp = temp>>1; } delta_metrics(i^mask) = -delta_metrics(i); // the inverse codeword } } else { double zero_metric=0, one_metric=0; int zero_output=0, one_output=0, temp_state; bin one_bit; for (int s=0; s> 1; if (xor_int_table(temp)) { zero_metric += rx_codeword(j); one_metric -= rx_codeword(j); } else { zero_metric -= rx_codeword(j); one_metric += rx_codeword(j); } one_output = (one_output<<1) | int(xor_int_table(temp) ^ one_bit); zero_output = (zero_output<<1) | int(xor_int_table(temp)); } delta_metrics(zero_output) = zero_metric; delta_metrics(one_output) = one_metric; } } } #ifndef DOXYGEN_SHOULD_SKIP_THIS // MFD codes R=1/2 int Conv_Code_MFD_2[15][2] = { {0,0}, {0,0}, {0,0}, {05,07}, {015,017}, {023,035}, {053,075}, {0133,0171}, {0247,0371}, {0561,0753}, {01167,01545}, {02335,03661}, {04335,05723}, {010533,017661}, {021675,027123}, }; // MFD codes R=1/3 int Conv_Code_MFD_3[15][3] = { {0,0,0}, {0,0,0}, {0,0,0}, {05,07,07}, {013,015,017}, {025,033,037}, {047,053,075}, {0133,0145,0175}, {0225,0331,0367}, {0557,0663,0711}, {0117,01365,01633}, {02353,02671,03175}, {04767,05723,06265}, {010533,010675,017661}, {021645,035661,037133}, }; // MFD codes R=1/4 int Conv_Code_MFD_4[15][4] = { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {05,07,07,07}, {013,015,015,017}, {025,027,033,037}, {053,067,071,075}, {0135,0135,0147,0163}, {0235,0275,0313,0357}, {0463,0535,0733,0745}, {0117,01365,01633,01653}, {02327,02353,02671,03175}, {04767,05723,06265,07455}, {011145,012477,015573,016727}, {021113,023175,035527,035537}, }; // MFD codes R=1/5 int Conv_Code_MFD_5[9][5] = { {0,0,0,0,0}, {0,0,0,0,0}, {0,0,0,0,0}, {07,07,07,05,05}, {017,017,013,015,015}, {037,027,033,025,035}, {075,071,073,065,057}, {0175,0131,0135,0135,0147}, {0257,0233,0323,0271,0357}, }; // MFD codes R=1/6 int Conv_Code_MFD_6[9][6] = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0}, {07,07,07,07,05,05}, {017,017,013,013,015,015}, {037,035,027,033,025,035}, {073,075,055,065,047,057}, {0173,0151,0135,0135,0163,0137}, {0253,0375,0331,0235,0313,0357}, }; // MFD codes R=1/7 int Conv_Code_MFD_7[9][7] = { {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {07,07,07,07,05,05,05}, {017,017,013,013,013,015,015}, {035,027,025,027,033,035,037}, {053,075,065,075,047,067,057}, {0165,0145,0173,0135,0135,0147,0137}, {0275,0253,0375,0331,0235,0313,0357}, }; // MFD codes R=1/8 int Conv_Code_MFD_8[9][8] = { {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {07,07,05,05,05,07,07,07}, {017,017,013,013,013,015,015,017}, {037,033,025,025,035,033,027,037}, {057,073,051,065,075,047,067,057}, {0153,0111,0165,0173,0135,0135,0147,0137}, {0275,0275,0253,0371,0331,0235,0313,0357}, }; int maxK_Conv_Code_MFD[9] = {0,0,14,14,14,8,8,8,8}; void get_MFD_gen_pol(int n, int K, ivec & gen) { gen.set_size(n); switch (n) { case 2: // Rate 1/2 it_assert(K >= 3 && K <= maxK_Conv_Code_MFD[2], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_MFD_2[K][0]; gen(1) = Conv_Code_MFD_2[K][1]; break; case 3: // Rate 1/3 it_assert(K >= 3 && K <= maxK_Conv_Code_MFD[3], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_MFD_3[K][0]; gen(1) = Conv_Code_MFD_3[K][1]; gen(2) = Conv_Code_MFD_3[K][2]; break; case 4: // Rate 1/4 it_assert(K >= 3 && K <= maxK_Conv_Code_MFD[4], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_MFD_4[K][0]; gen(1) = Conv_Code_MFD_4[K][1]; gen(2) = Conv_Code_MFD_4[K][2]; gen(3) = Conv_Code_MFD_4[K][3]; break; case 5: // Rate 1/5 it_assert(K >= 3 && K <= maxK_Conv_Code_MFD[5], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_MFD_5[K][0]; gen(1) = Conv_Code_MFD_5[K][1]; gen(2) = Conv_Code_MFD_5[K][2]; gen(3) = Conv_Code_MFD_5[K][3]; gen(4) = Conv_Code_MFD_5[K][4]; break; case 6: // Rate 1/6 it_assert(K >= 3 && K <= maxK_Conv_Code_MFD[6], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_MFD_6[K][0]; gen(1) = Conv_Code_MFD_6[K][1]; gen(2) = Conv_Code_MFD_6[K][2]; gen(3) = Conv_Code_MFD_6[K][3]; gen(4) = Conv_Code_MFD_6[K][4]; gen(5) = Conv_Code_MFD_6[K][5]; break; case 7: // Rate 1/7 it_assert(K >= 3 && K <= maxK_Conv_Code_MFD[7], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_MFD_7[K][0]; gen(1) = Conv_Code_MFD_7[K][1]; gen(2) = Conv_Code_MFD_7[K][2]; gen(3) = Conv_Code_MFD_7[K][3]; gen(4) = Conv_Code_MFD_7[K][4]; gen(5) = Conv_Code_MFD_7[K][5]; gen(6) = Conv_Code_MFD_7[K][6]; break; case 8: // Rate 1/8 it_assert(K >= 3 && K <= maxK_Conv_Code_MFD[8], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_MFD_8[K][0]; gen(1) = Conv_Code_MFD_8[K][1]; gen(2) = Conv_Code_MFD_8[K][2]; gen(3) = Conv_Code_MFD_8[K][3]; gen(4) = Conv_Code_MFD_8[K][4]; gen(5) = Conv_Code_MFD_8[K][5]; gen(6) = Conv_Code_MFD_8[K][6]; gen(7) = Conv_Code_MFD_8[K][7]; break; default: // wrong rate it_assert(false, "This convolutional code doesn't exist in the tables"); } } // ODS codes R=1/2 int Conv_Code_ODS_2[17][2] = { {0,0}, {0,0}, {0,0}, {05,07}, {015,017}, {023,035}, {053,075}, {0133,0171}, {0247,0371}, {0561,0753}, {01151,01753}, {03345,03613}, {05261,07173}, {012767,016461}, {027251,037363}, {063057,044735}, {0126723,0152711}, }; // ODS codes R=1/3 int Conv_Code_ODS_3[14][3] = { {0,0,0}, {0,0,0}, {0,0,0}, {05,07,07}, {013,015,017}, {025,033,037}, {047,053,075}, {0133,0165,0171}, {0225,0331,0367}, {0575,0623,0727}, {01233,01375,01671}, {02335,02531,03477}, {05745,06471,07553}, {013261,015167,017451}, }; // ODS codes R=1/4 int Conv_Code_ODS_4[12][4] = { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {05,05,07,07}, {013,015,015,017}, {025,027,033,037}, {051,055,067,077}, {0117,0127,0155,0171}, {0231,0273,0327,0375}, {0473,0513,0671,0765}, {01173,01325,01467,01751}, {02565,02747,03311,03723}, }; int maxK_Conv_Code_ODS[5] = {0,0,16,13,11}; void get_ODS_gen_pol(int n, int K, ivec & gen) { gen.set_size(n); switch (n) { case 2: // Rate 1/2 it_assert(K >= 3 && K <= maxK_Conv_Code_ODS[2], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_ODS_2[K][0]; gen(1) = Conv_Code_ODS_2[K][1]; break; case 3: // Rate 1/3 it_assert(K >= 3 && K <= maxK_Conv_Code_ODS[3], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_ODS_3[K][0]; gen(1) = Conv_Code_ODS_3[K][1]; gen(2) = Conv_Code_ODS_3[K][2]; break; case 4: // Rate 1/4 it_assert(K >= 3 && K <= maxK_Conv_Code_ODS[4], "This convolutional code doesn't exist in the tables"); gen(0) = Conv_Code_ODS_4[K][0]; gen(1) = Conv_Code_ODS_4[K][1]; gen(2) = Conv_Code_ODS_4[K][2]; gen(3) = Conv_Code_ODS_4[K][3]; break; default: // wrong rate it_assert(false, "This convolutional code doesn't exist in the tables"); } } #endif /* DOXYGEN_SHOULD_SKIP_THIS */ // --------------- Public functions ------------------------- void Convolutional_Code::set_code(string type_of_code, int inverse_rate, int constraint_length) { ivec gen; if (type_of_code == "MFD") get_MFD_gen_pol(inverse_rate, constraint_length, gen); else if (type_of_code == "ODS") get_ODS_gen_pol(inverse_rate, constraint_length, gen); else it_assert(false, "This convolutional code doesn't exist in the tables"); set_generator_polynomials(gen, constraint_length); } /* Set generator polynomials. Given in Proakis integer form */ void Convolutional_Code::set_generator_polynomials(const ivec &gen, int constraint_length) { it_error_if(constraint_length <= 0, "Constraint length out of range"); gen_pol = gen; n = gen.size(); it_error_if(n <= 0, "Invalid code rate"); // Generate table look-up of weight of integers of size K bits if (constraint_length != K) { K = constraint_length; xor_int_table.set_size(pow2(K), false); for (int i=0; i> 1; } } /* Encode a binary vector of inputs starting from zero state and also adds a tail of K-1 zeros to force the encoder into the zero state. Well suited for packet transmission. */ void Convolutional_Code::encode_tail(const bvec &input, bvec &output) { int ii, j, temp; output.set_size((input.size()+m)*n, false); encoder_state = 0; for (ii=0; ii> 1; } // add tail of m=K-1 zeros for (ii=input.size(); ii> 1; } } /* Encode a binary vector of inputs starting using tail biting */ void Convolutional_Code::encode_tailbite(const bvec &input, bvec &output) { int ii, j, temp; bvec last_bits(m); output.set_size(input.size()*n, false); //Set the start state equal to the end state: encoder_state = 0; last_bits = input.right(m); for (ii=0; ii> 1; } for (ii=0; ii> 1; } } /* Encode a binary bit startinf from the internal encoder state. To initialize the encoder state use set_start_state() and init_encoder() */ void Convolutional_Code::encode_bit(const bin &input, bvec &output) { int j, temp; output.set_size(n, false); encoder_state = encoder_state | (int(input) << m); for (j=0; j> 1; } /* Decode a block of encoded data where encode_tail has been used. Thus is assumes a decoder start state of zero and that a tail of K-1 zeros has been added. No memory truncation. */ void Convolutional_Code::decode_tail(const vec &received_signal, bvec &output) { int block_length = received_signal.size()/n; // no input symbols int i, l, s, min_metric_state, S0=0, S1=0; imat path_memory(no_states, block_length); vec sum_metric(no_states), temp_sum_metric(no_states), temp_rec(n); Array visited_state(no_states), temp_visited_state(no_states); double temp_metric_zero, temp_metric_one; it_error_if(block_length-m<=0, "The input sequence is to short"); output.set_length(block_length-m, false); // not include the tail in the output vec delta_metrics; for (i=0; iblock_length-1-m; l--) { // previous state calculation min_metric_state = previous_state(min_metric_state, path_memory(min_metric_state, l)); } // trace back to calculate output sequence for (l=block_length-1-m; l>=0; l--) { output(l) = get_input(min_metric_state); // previous state calculation min_metric_state = previous_state(min_metric_state, path_memory(min_metric_state, l)); } } /* Decode a block of encoded data where encode_tailbite has been used. */ void Convolutional_Code::decode_tailbite(const vec &received_signal, bvec &output) { int block_length = received_signal.size()/n; // no input symbols int i, l, s, ss, min_metric_state, S0=0, S1=0; imat path_memory(no_states, block_length); vec sum_metric(no_states), temp_sum_metric(no_states), temp_rec(n); Array visited_state(no_states), temp_visited_state(no_states); double temp_metric_zero, temp_metric_one; vec delta_metrics; bvec best_output(block_length), temp_output(block_length); double best_metric = 1e100; it_error_if(block_length<=0, "The input sequence is to short"); output.set_length(block_length, false); // not include the tail in the output //Try all start states ss for (ss=0; ss=0; l--) { temp_output(l) = get_input(min_metric_state); // previous state calculation min_metric_state = previous_state(min_metric_state, path_memory(min_metric_state, l)); } if (sum_metric(ss) visited_state(no_states), temp_visited_state(no_states); double temp_metric_zero, temp_metric_one; it_error_if(block_length-trunc_length<=0, "The input sequence is to short"); output.set_size(block_length-trunc_length, false); vec delta_metrics; for (i=0; il-trunc_length; tt--) { // previous state calculation min_metric_state = previous_state(min_metric_state, path_memory(min_metric_state, tt%trunc_length) ); } output(tt) = get_input(min_metric_state); // --------- Evolve trellis -------------- temp_rec = received_signal.mid(l*n, n); // calculate all metrics for all codewords at the same time calc_metric(temp_rec, delta_metrics); for (s=0; s> 1; } else if (coded_sequence.mid(i*n, n) == one_output) { input(i) = bin(1); state = one_state >> 1; } else return false; } return true; } /* Check if catastrophic. Returns true if catastrophic */ bool Convolutional_Code::catastrophic(void) { int start, S, W0, W1, S0, S1; bvec visited(1< 0) goto node0; if (visited(S1) == bin(1)) return true; S = S1; // goto node1 visited(S) = 1; goto node1; node0: if (S0 < start) continue; // goto end; if (W0 > 0) continue; // goto end; if (visited(S0) == bin(1)) return true; S = S0; visited(S) = 1; goto node1; //end: //void; } return false; } /* Calculate distance profile. If reverse = true calculate for the reverse code instead. */ //void Convolutional_Code::distance_profile(llvec &dist_prof, int dmax, bool reverse) void Convolutional_Code::distance_profile(ivec &dist_prof, int dmax, bool reverse) { int max_stack_size = 50000; ivec S_stack(max_stack_size), W_stack(max_stack_size), t_stack(max_stack_size); int stack_pos=-1, t, S, W, W0, w0, w1; dist_prof.set_size(K, false); dist_prof.zeros(); dist_prof += dmax; // just select a big number! if (reverse) W = weight_reverse(0, 1); else W = weight(0, 1); S = next_state(0, 1); // first state 0 and one as input, S = 1<<(m-1); t = 0; dist_prof(0) = W; node1: if (reverse) weight_reverse(S, w0, w1); else weight(S, w0, w1); if (t < m) { W0 = W + w0; if (W0 < dist_prof(m)) { // store node0 (S, W0, and t+1) stack_pos++; if (stack_pos >= max_stack_size) { max_stack_size = 2*max_stack_size; S_stack.set_size(max_stack_size, true); W_stack.set_size(max_stack_size, true); t_stack.set_size(max_stack_size, true); } S_stack(stack_pos) = next_state(S, 0); //S>>1; W_stack(stack_pos) = W0; t_stack(stack_pos) = t+1; } } else goto stack; W += w1; if (W > dist_prof(m)) goto stack; t++; S = next_state(S, 1); //S = (S>>1)|(1<<(m-1)); if (W < dist_prof(t)) dist_prof(t) = W; if(t == m) goto stack; goto node1; stack: if (stack_pos >= 0) { // get root node from stack S = S_stack(stack_pos); W = W_stack(stack_pos); t = t_stack(stack_pos); stack_pos--; if (W < dist_prof(t)) dist_prof(t) = W; if (t == m) goto stack; goto node1; } } /* Calculate spectrum Calculates both the weight spectrum (Ad) and the information weight spectrum (Cd) and returns it as ivec:s in the 0:th and 1:st component of spectrum, respectively. Suitable for calculating many terms in the spectra (uses an breadth first algorithm). It is assumed that the code is non-catastrophic or else it is a possibility for an eternal loop. dmax = an upper bound on the free distance no_terms = no_terms including the dmax term that should be calculated */ //void Convolutional_Code::calculate_spectrum(Array &spectrum, int dmax, int no_terms) void Convolutional_Code::calculate_spectrum(Array &spectrum, int dmax, int no_terms) { imat Ad_states(no_states, dmax+no_terms), Cd_states(no_states, dmax+no_terms); imat Ad_temp(no_states, dmax+no_terms), Cd_temp(no_states, dmax+no_terms); ivec mindist(no_states), mindist_temp(1<0) && (mindist(s)0) { mindist_temp(s0) = ( mindist(s)+w0 ) < mindist_temp(s0) ? mindist(s)+w0 : mindist_temp(s0); } else { mindist_temp(s0) = mindist(s)+w0; } if (mindist_temp(s1)>0) { mindist_temp(s1) = ( mindist(s)+w1 ) < mindist_temp(s1) ? mindist(s)+w1 : mindist_temp(s1); } else { mindist_temp(s1) = mindist(s)+w1; } } } Ad_states = Ad_temp; Cd_states = Cd_temp; spectrum(0) += Ad_temp.get_row(0); spectrum(1) += Cd_temp.get_row(0); visited_states = visited_states_temp; mindist = elem_mult(mindist_temp, visited_states); } } /* Cederwall's fast algorithm See IT No. 6, pp. 1146-1159, Nov. 1989 for details. Calculates both the weight spectrum (Ad) and the information weight spectrum (Cd) and returns it as ivec:s in the 0:th and 1:st component of spectrum, respectively. The FAST algorithm is good for calculating only a few terms in the spectrum. If many terms are desired, use calc_spectrum instead. The algorithm returns -1 if the code tested is worse that the input dfree and Cdfree. It returns 0 if the code MAY be catastrophic (assuming that test_catastrophic is true), and returns 1 if everything went right. \arg \c dfree the free distance of the code (or an upper bound) \arg \c no_terms including the dfree term that should be calculated \ar \c Cdfree is the best value of information weight spectrum found so far */ //int Convolutional_Code::fast(Array &spectrum, const int dfree, const int no_terms, const int Cdfree, const bool test_catastrophic) int Convolutional_Code::fast(Array &spectrum, const int dfree, const int no_terms, const int Cdfree, const bool test_catastrophic) { int cat_treshold = 7*K; // just a big number, but not to big! int i; ivec dist_prof(K), dist_prof_rev(K); //llvec dist_prof(K), dist_prof_rev(K); //calculate distance profile distance_profile(dist_prof, dfree); distance_profile(dist_prof_rev, dfree, true); // for the reverse code int dist_prof_rev0 = dist_prof_rev(0); bool reverse = false; // false = use dist_prof // is the reverse distance profile better? for (i=0; i dist_prof(i)) { reverse = true; dist_prof_rev0 = dist_prof(0); dist_prof = dist_prof_rev; break; } else if (dist_prof_rev(i) < dist_prof(i)) { break; } } int d = dfree + no_terms - 1; int max_stack_size = 50000; ivec S_stack(max_stack_size), W_stack(max_stack_size), b_stack(max_stack_size), c_stack(max_stack_size); int stack_pos=-1; // F1. int mf = 1, b = 1; spectrum.set_size(2); spectrum(0).set_size(dfree+no_terms, false); // ad spectrum(1).set_size(dfree+no_terms, false); // cd spectrum(0).zeros(); spectrum(1).zeros(); int S, S0, S1, W0, W1, w0, w1, c = 0; S = next_state(0, 1); //first state zero and one as input int W = d - dist_prof_rev0; F2: S0 = next_state(S, 0); S1 = next_state(S, 1); if (reverse) { weight(S, w0, w1); } else { weight_reverse(S, w0, w1); } W0 = W - w0; W1 = W - w1; if(mf < m) goto F6; //F3: if (W0 >= 0) { spectrum(0)(d-W0)++; spectrum(1)(d-W0) += b; // The code is worse than the best found. if ( ((d-W0) < dfree) || ( ((d-W0) == dfree) && (spectrum(1)(d-W0) > Cdfree) ) ) return -1; } F4: if ( (W1 < dist_prof(m-1)) || (W < dist_prof(m)) ) goto F5; // select node 1 if (test_catastrophic && W == W1) { c++; if (c>cat_treshold) return 0; } else { c = 0; W = W1; } S = S1; mf = 1; b++; goto F2; F5: //if (stack_pos == -1) return n_values; if (stack_pos == -1) goto end; // get node from stack S = S_stack(stack_pos); W = W_stack(stack_pos); b = b_stack(stack_pos); c = c_stack(stack_pos); stack_pos--; mf = 1; goto F2; F6: if (W0 < dist_prof(m-mf-1)) goto F4; //F7: if ( (W1 >= dist_prof(m-1)) && (W >= dist_prof(m)) ) { // save node 1 if (test_catastrophic && stack_pos > 10000) return 0; stack_pos++; if (stack_pos >= max_stack_size) { max_stack_size = 2*max_stack_size; S_stack.set_size(max_stack_size, true); W_stack.set_size(max_stack_size, true); b_stack.set_size(max_stack_size, true); c_stack.set_size(max_stack_size, true); } S_stack(stack_pos) = S1; W_stack(stack_pos) = W1; b_stack(stack_pos) = b + 1; // because gone to node 1 c_stack(stack_pos) = c; // because gone to node 1 } // select node 0 S = S0; if (test_catastrophic && W == W0) { c++; if (c>cat_treshold) return 0; } else { c = 0; W = W0; } mf++; goto F2; end: return 1; } //-------------------- These functions should be moved into some onther place ----------------- /* Reverses the bitrepresentation of in (of size length) and converts to an integer */ int reverse_int(int length, int in) { int i, j, out = 0; for (i=0; i<(length>>1); i++) { out = out | ( (in & (1<> ((j<<1)-(length&1)+1) ); //out = out | ( (in & (1<> ((j<<1)-(length&1)+1) ); old version with preecedence problems in MSC } return out; } /* Calculate the Hamming weight of the binary representation of in of size length */ int weight_int(int length, int in) { int i, w=0; for (i=0; i> i; } return w; } /* \relates Convolutional_Code Compare two distance spectra. Return 1 if v1 is less, 0 if v2 less, and -1 if equal. */ //int compare_spectra(llvec v1, llvec v2) int compare_spectra(ivec v1, ivec v2) { it_assert1(v1.size() == v2.size(), "compare_spectra: wrong sizes"); for (int i=0; i v2(i)) { return 0; } } return -1; } /* Compare two distance spectra using a weight profile. Return 1 if v1 is less, 0 if v2 less, and -1 if equal. */ int compare_spectra(ivec v1, ivec v2, vec weight_profile) { double t1=0, t2=0; for (int i=0; i t2) return 0; else return -1; } } //namespace itpp