void Packet_Generator::set_parameters(const int Packet_size, const unsigned long int Max_packets) { it_assert(Packet_size > 0, "Packet_Generator::set_parameters(): "); packet_size = Packet_size; max_packets = Max_packets; id = 0; }
void CRC_Code::set_generator(const bvec &poly) { //it_assert(poly(0) == 1 && poly(poly.size()-1) == 1, "CRC_Code::set_polynomial: not a valid polynomial"); it_assert(poly(0) == 1, "CRC_Code::set_polynomial: not a valid polynomial"); polynomial = poly; no_parity = polynomial.size() - 1; }
// m=m-m*v*v' void sub_m_v_vT(mat &m, const vec &v) { vec v2(m.rows()); double tmp, *v2p; const double *vp; int i, j; it_assert(v.size() == m.cols(), "sub_m_v_vT()"); v2p = v2._data(); for (i = 0; i < m.rows(); i++) { tmp = 0.0; vp = v._data(); for (j = 0; j < m.cols(); j++) tmp += *(vp++) * m._elem(i, j); *(v2p++) = tmp; } v2p = v2._data(); for (i = 0; i < m.rows(); i++) { vp = v._data(); for (j = 0; j < m.cols(); j++) m._elem(i, j) -= *v2p * *(vp++); v2p++; } }
Sink::Sink(const unsigned long int Max_packets) { it_assert(Max_packets > 0, "Sink::Sink(): "); max_packets = Max_packets; Ncp = 0; Nbytes = 0; packet_input.forward(this, &Sink::handle_packet_input); start_time = Event_Queue::now(); }
void Poisson_Packet_Generator::set_parameters(const double Avg_bit_rate, const int Packet_size, const unsigned long int Max_packets) { Packet_Generator::set_parameters(Packet_size, Max_packets); it_assert(Avg_bit_rate > 0.0, "Packet_Generator::set_parameters(): "); avg_bit_rate = Avg_bit_rate; avg_delta_t = 8.0 * get_packet_size() / avg_bit_rate; ee.setup(1.0); }
Array1D<T> zero_pad(const Array1D<T>& v, int n) { it_assert(n>=v.size(), "zero_pad() cannot shrink the vector!"); Array1D<T> v2(n); v2.set_subvector(0, v.size()-1, v); if (n > v.size()) v2.set_subvector(v.size(), n-1, T(0)); return v2; }
void xcorr_old(const vec &x, const vec &y, vec &out, const int max_lag, const std::string scaleopt) { int m, n; double s_plus, s_minus, M_double, coeff_scale = 0.0; int M, N; M = x.size(); M = std::max(x.size(), y.size()); M_double = double(M); if (max_lag == -1) { N = std::max(x.size(), y.size()); } else { N = max_lag + 1; } out.set_size(2*N - 1, false); it_assert(N <= std::max(x.size(), y.size()), "max_lag cannot be as large as, or larger than, the maximum length of x and y."); if (scaleopt == "coeff") { coeff_scale = std::sqrt(energy(x)) * std::sqrt(energy(y)); } for (m = 0; m < N; m++) { s_plus = 0; s_minus = 0; for (n = 0;n < M - m;n++) { s_minus += index_zero_pad(x, n) * index_zero_pad(y, n + m); s_plus += index_zero_pad(x, n + m) * index_zero_pad(y, n); } if (scaleopt == "none") { out(N + m - 1) = s_plus; out(N - m - 1) = s_minus; } else if (scaleopt == "biased") { out(N + m - 1) = s_plus / M_double; out(N - m - 1) = s_minus / M_double; } else if (scaleopt == "unbiased") { out(N + m - 1) = s_plus / double(M - m); out(N - m - 1) = s_minus / double(M - m); } else if (scaleopt == "coeff") { out(N + m - 1) = s_plus / coeff_scale; out(N - m - 1) = s_minus / coeff_scale; } else it_error("Incorrect scaleopt specified."); } }
void Sink::handle_packet_input(Packet *P) { it_assert(P != NULL, "Sink::handle_packet_input(): "); Ncp++; Nbytes += (P->bit_size() / 8); delete P; if (Ncp >= max_packets) { std::cout << "Time = " << Event_Queue::now() << ", Sink : " << std::endl; std::cout << "Simulation stopped because : Ncp > max_packets" << std::endl; Event_Queue::stop(); } }
Array1D<T> cross(const Array1D<T>& v1, const Array1D<T>& v2) { it_assert( v1.size() == 3 && v2.size() == 3, "cross: vectors should be of size 3"); Array1D<T> r(3); r(0) = v1(1) * v2(2) - v1(2) * v2(1); r(1) = v1(2) * v2(0) - v1(0) * v2(2); r(2) = v1(0) * v2(1) - v1(1) * v2(0); return r; }
double cheb(int n, double x) { it_assert((n >= 0), "cheb(): need a non-negative order n!"); if (x < 1.0 && x > -1.0) { return std::cos(n * std::acos(x)); } else if (x <= -1) { return (is_even(n) ? std::cosh(n * ::acosh(-x)) : -std::cosh(n * ::acosh(-x))); } return std::cosh(n * ::acosh(x)); }
void BLERC::count(const bvec &in1, const bvec &in2) { it_assert(setup_done == true, "BLERC::count(): Block size has to be setup before counting errors."); int min_input_length = std::min(in1.length(), in2.length()); it_assert(blocksize <= min_input_length, "BLERC::count(): Block size must not be longer than input vectors."); for (int i = 0; i < (min_input_length / blocksize); i++) { CORR = true; for (int j = 0; j < blocksize; j++) { if (in1(i * blocksize + j) != in2(i * blocksize + j)) { CORR = false; break; } } if (CORR) { corrects++; } else { errors++; } } }
void CRC_Code::set_code(const std::string &code) { bvec poly; for (int i = 0; i < 18;i++) { if (crccode[i][0] == code) poly = bvec(crccode[i][1]); } if ((code == "WCDMA-8") || (code == "WCDMA-12") || (code == "WCDMA-16") || (code == "WCDMA-24")) { reverse_parity = true; } it_assert(poly.size() > 0, "This CRC code doesn't exist in the tables"); set_generator(poly); }
//-------------------- Reed-Solomon ---------------------------- //A Reed-Solomon code is a q^m-ary BCH code of length n = pow(q,m)-1. //k = pow(q,m)-1-t. This class works for q==2. Reed_Solomon::Reed_Solomon(int in_m, int in_t, bool sys, int in_b): m(in_m), t(in_t), b(in_b), systematic(sys) { n = pow2i(m) - 1; k = pow2i(m) - 1 - 2 * t; q = pow2i(m); it_assert( (b >= 0) && (b < n), "Reed_Solomon::Reed_Solomon: narrow-sense parameter restricted to 0 <= b <= n."); GFX x(q, (char *)"-1 0"); ivec alphapow(1); g.set(q, (char *)"0"); for (int i = 1; i <= 2 * t; i++) { alphapow(0) = b + i - 1; g *= (x - GFX(q, alphapow)); } }
void STC::Hassibi_block_code(void) /* This function generates the A and B matrices needed for Space-Time block codes * generation following Hassibi's approach: * S = sum_{q=1}^symb_block (A_q alpha_q + jB_q beta_q), * where s_q = alpha_q+jbeta_q is the symbol after modulation * each A_q and B_q matrix has dimension TxM * different A_q and B_q matrices are stacked one below the other, e.g. * [A_1;A_2;...;A_Q] * input: code_name - code name whose generator matrices are to be generated * const_size - constellation size (used in Damen code) * outputs: symb_block - number of symbols per block * A, B - generator matrices * inputs/outputs: for some codes these are inputs for others they are * predefined, so they are outputs only * em_antennas - number of emission antenna * channel_uses - channel uses */ { if (code_name=="V-BLAST_MxN")//classical V-BLAST { it_assert(channel_uses > 0, "Channel uses should be strictly positive"); it_assert(em_antenna > 0, "Number of emission antenna should be strictly positive"); symb_block = channel_uses*em_antenna;//number of symbols/block A.set_size(symb_block*channel_uses, em_antenna); A.zeros(); itpp::mat temp(channel_uses, em_antenna); temp.zeros(); register int tau,m; for (tau=0; tau<channel_uses; tau++) { for (m=0; m<em_antenna; m++) { temp(tau,m) = 1; A.set_submatrix(symb_block*tau+channel_uses*m, 0, itpp::to_cmat(temp)); temp(tau,m) = 0; } } B = A; } else if (code_name=="imp_V-BLAST_MxN")//improved V-BLAST (code (31) in Hassibi's paper) { it_assert(em_antenna > 0, "Number of emission antenna should be strictly positive"); it_assert(channel_uses == em_antenna, "Channel uses and the number of emission antenna must be equal"); symb_block = channel_uses*em_antenna;//number of symbols/block std::complex<double> j(0,1); itpp::cmat D = itpp::diag(exp(j*(2*itpp::pi/em_antenna)* itpp::linspace(0, em_antenna-1, em_antenna))); itpp::mat P = itpp::diag(itpp::ones(em_antenna-1), -1); P(0,em_antenna-1) = 1; A.set_size(symb_block*channel_uses, em_antenna); A.zeros(); register int k,l; for (k=0; k<channel_uses; k++) { for (l=0; l<em_antenna; l++) { A.set_submatrix(symb_block*k+l*channel_uses, 0, diag_pow(D, k)*itpp::to_cmat(mat_pow(P, l))/ std::sqrt(double(em_antenna))); } } B = A; } else if (code_name=="Alamouti_2xN")//Alamouti's orthogonal code { em_antenna = 2;//emission antenna channel_uses = 2;//channel uses symb_block = 2;//number of symbols/block A = "1 0;" "0 1;" "0 1;" "-1 0";//A_1; A_2 B = "1 0;" "0 -1;" "0 1;" "1 0";//B_1; B_2 } else if (code_name=="Switched_Alamouti_4xN") { em_antenna = 4;//emission antenna channel_uses = 4;//channel uses symb_block = 4;//number of symbols/block A = "1 0 0 0;" "0 1 0 0;" "0 0 0 0;" "0 0 0 0;" "0 1 0 0;" "-1 0 0 0;" "0 0 0 0;" "0 0 0 0;" "0 0 0 0;" "0 0 0 0;" "0 0 1 0;" "0 0 0 1;" "0 0 0 0;" "0 0 0 0;" "0 0 0 1;" "0 0 -1 0";//A_1; A_2; A_3; A_4 A *= std::sqrt(2.0);//normalization B = "1 0 0 0;" "0 -1 0 0;" "0 0 0 0;" "0 0 0 0;" "0 1 0 0;" "1 0 0 0;" "0 0 0 0;" "0 0 0 0;" "0 0 0 0;" "0 0 0 0;" "0 0 1 0;" "0 0 0 -1;" "0 0 0 0;" "0 0 0 0;" "0 0 0 1;" "0 0 1 0";//B_1; B_2; B_3; B_4 B *= std::sqrt(2.0); } else if (code_name=="Double_Alamouti_4xN") { em_antenna = 4;//emission antenna channel_uses = 2;//channel uses symb_block = 4;//number of symbols/block A = "1 0 0 0;" "0 1 0 0;" "0 0 1 0;" "0 0 0 1;" "0 1 0 0;" "-1 0 0 0;" "0 0 0 1;" "0 0 -1 0";//A_1; A_2; A_3; A_4 B = "1 0 0 0;" "0 -1 0 0;" "0 0 1 0;" "0 0 0 -1;" "0 1 0 0;" "1 0 0 0;" "0 0 0 1;" "0 0 1 0";//B_1; B_2; B_3; B_4 } else if (code_name=="Jafarkhani_4xN")//Jafarkhani's quasi-orthogonal code { em_antenna = 4;//emission antenna channel_uses = 4;//channel uses symb_block = 4;//number of symbols/block A = "1 0 0 0;" "0 1 0 0;" "0 0 1 0;" "0 0 0 1;" "0 1 0 0;" "-1 0 0 0;" "0 0 0 1;" "0 0 -1 0;" "0 0 1 0;" "0 0 0 1;" "-1 0 0 0;" "0 -1 0 0;" "0 0 0 1;" "0 0 -1 0;" "0 -1 0 0;" "1 0 0 0";//A_1; A_2; A_3; A_4 B = "1 0 0 0;" "0 -1 0 0;" "0 0 -1 0;" "0 0 0 1;" "0 1 0 0;" "1 0 0 0;" "0 0 0 -1;" "0 0 -1 0;" "0 0 1 0;" "0 0 0 -1;" "1 0 0 0;" "0 -1 0 0;" "0 0 0 1;" "0 0 1 0;" "0 1 0 0;" "1 0 0 0";//B_1; B_2; B_3; B_4 } else if (code_name=="Golden_2x2")//Golden code as proposed by Belfiore { em_antenna = 2;//emission antenna channel_uses = 2;//channel uses symb_block = 4;//number of symbols/block std::complex<double> theta((1+std::sqrt(5.0))/2,0); std::complex<double> theta_b((1-std::sqrt(5.0))/2,0); std::complex<double> j(0,1); std::complex<double> one(1,0); std::complex<double> alpha = one+j*(one-theta); std::complex<double> alpha_b = one+j*(one-theta_b); std::complex<double> gamma = j; A.set_size(8,2); A(0,0) = alpha/std::sqrt(5.0); A(0,1) = 0; A(1,0) = 0; A(1,1) = alpha_b/std::sqrt(5.0);//A_1 A(2,0) = alpha*theta/std::sqrt(5.0); A(2,1) = 0; A(3,0) = 0; A(3,1) = alpha_b*theta_b/std::sqrt(5.0);//A_2 A(4,0) = 0; A(4,1) = gamma*alpha_b/std::sqrt(5.0); A(5,0) = alpha/std::sqrt(5.0); A(5,1) = 0;//A_3 A(6,0) = 0; A(6,1) = gamma*alpha_b*theta_b/std::sqrt(5.0); A(7,0) = alpha*theta/std::sqrt(5.0); A(7,1) = 0;//A_4 B = A; } else if (code_name=="Damen_2x2")//ST code based on number theory as proposed by Damen { em_antenna = 2;//emission antenna channel_uses = 2;//channel uses symb_block = 4;//number of symbols/block double lambda; if (const_size==4) lambda = 0.5; else if (const_size==16) lambda = 0.521; else if (const_size>=256) lambda = itpp::pi/4; else { lambda = itpp::pi/4; std::cout << "STC::LDcode: Warning! For " << code_name << " and const. size " << const_size << ", lambda has the " "value " << lambda << std::endl; } std::complex<double> j(0,1); std::complex<double> phi = std::exp(j*lambda); std::complex<double> theta = std::exp(j*(lambda/2)); A.set_size(8, 2); A(0,0) = 1/std::sqrt(2.0); A(0,1) = 0; A(1,0) = 0; A(1,1) = 1/std::sqrt(2.0);//A_1 A(2,0) = phi/std::sqrt(2.0); A(2,1) = 0; A(3,0) = 0; A(3,1) = -phi/std::sqrt(2.0);//A_2 A(4,0) = 0; A(4,1) = theta/std::sqrt(2.0); A(5,0) = theta/std::sqrt(2.0); A(5,1) = 0;//A_3 A(6,0) = 0; A(6,1) = -theta*phi/std::sqrt(2.0); A(7,0) = theta*phi/std::sqrt(2.0); A(7,1) = 0;//A_4 B = A; } else if (code_name=="34ortho_3xN")//rate 3/4 orthogonal code (mutual information 5.13 bits/channel use at rho=20 dB) { em_antenna = 3;//emission antenna channel_uses = 4;//channel uses symb_block = 3;//number of symbols/block A = "1 0 0;" "0 1 0;" "0 0 1;" "0 0 0;" "0 1 0;" "-1 0 0;" "0 0 0;" "0 0 1;" "0 0 1;" "0 0 0;" "-1 0 0;" "0 -1 0";//A_1; A_2; A_3 A /= std::sqrt(double(4)/double(3)); B = "1 0 0;" "0 -1 0;" "0 0 -1;" "0 0 0;" "0 1 0;" "1 0 0;" "0 0 0;" "0 0 -1;" "0 0 1;" "0 0 0;" "1 0 0;" "0 1 0";//B_1; B_2; B_3 B /= std::sqrt(double(4)/double(3)); } else if (code_name=="36LD_3xN")//(36) LD code with mutual info. 6.25bits/channel use at rho=20dB { em_antenna = 3;//emission antenna channel_uses = 4;//channel uses symb_block = 4;//number of symbols/block A.set_size(16, 3); A(0,0) = 1; A(0,1) = 0; A(0,2) = 0; A(1,0) = 1; A(1,1) = 1; A(1,2) = 0; A(2,0) = 0; A(2,1) = 0; A(2,2) = 1; A(3,0) = 0; A(3,1) = 0; A(3,2) = 0;//A_1 A(4,0) = 0; A(4,1) = 1/std::sqrt(2.0); A(4,2) = 0; A(5,0) = -1/std::sqrt(2.0); A(5,1) = 0; A(5,2) = -1/std::sqrt(2.0); A(6,0) = 0; A(6,1) = 1/std::sqrt(2.0); A(6,2) = 0; A(7,0) = 1/std::sqrt(2.0); A(7,1) = 0; A(7,2) = -1/std::sqrt(2.0);//A_2 A(8,0) = 1; A(8,1) = 0; A(8,2) = 0; A(9,0) = 0; A(9,1) = 0; A(9,2) = 0; A(10,0) = 0; A(10,1) = 0; A(10,2) = -1; A(11,0) = 0; A(11,1) = -1; A(11,2) = 0;//A_3 A(12,0) = 0; A(12,1) = -1/std::sqrt(2.0); A(12,2) = 0; A(13,0) = 1/std::sqrt(2.0); A(13,1) = 0; A(13,2) = -1/std::sqrt(2.0); A(14,0) = 0; A(14,1) = 1/std::sqrt(2.0); A(14,2) = 0; A(15,0) = -1/std::sqrt(2.0); A(15,1) = 0; A(15,2) = -1/std::sqrt(2.0);//A_4 B.set_size(16, 3); B(0,0) = 0; B(0,1) = -1/std::sqrt(2.0); B(0,2) = 0; B(1,0) = -1/std::sqrt(2.0); B(1,1) = 0; B(1,2) = 1/std::sqrt(2.0); B(2,0) = 0; B(2,1) = 1/std::sqrt(2.0); B(2,2) = 0; B(3,0) = 1/std::sqrt(2.0); B(3,1) = 0; B(3,2) = 1/std::sqrt(2.0);//B_1 B(4,0) = 1/std::sqrt(2.0); B(4,1) = double(-1)/double(2); B(4,2) = 0; B(5,0) = double(-1)/double(2); B(5,1) = -1/std::sqrt(2.0); B(5,2) = double(-1)/double(2); B(6,0) = 0; B(6,1) = double(-1)/double(2); B(6,2) = 1/std::sqrt(2.0); B(7,0) = double(1)/double(2); B(7,1) = 0; B(7,2) = double(-1)/double(2);//B_2 B(8,0) = 1/std::sqrt(2.0); B(8,1) = double(1)/double(2); B(8,2) = 0; B(9,0) = double(1)/double(2); B(9,1) = -1/std::sqrt(2.0); B(9,2) = double(1)/double(2); B(10,0) = 0; B(10,1) = double(1)/double(2); B(10,2) = 1/std::sqrt(2.0); B(11,0) = double(-1)/double(2); B(11,1) = 0; B(11,2) = double(1)/double(2);//B_3 B(12,0) = 1; B(12,1) = 0; B(12,2) = 0; B(13,0) = 0; B(13,1) = 0; B(13,2) = 0; B(14,0) = 0; B(14,1) = 0; B(14,2) = -1; B(15,0) = 0; B(15,1) = 1; B(15,2) = 0;//B_4 } else if (code_name=="37LD_3xN")//(37) LD code 3-antenna LD code obtained from the symetrical concatenation of 3 2-antenna orthogonal design { em_antenna = 3;//emission antenna channel_uses = 6;//channel uses symb_block = 6;//number of symbols/block A = "1 0 0;" "0 1 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 1 0;" "-1 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 1 0;" "0 0 1;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 1;" "0 -1 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "1 0 0;" "0 0 1;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 1;" "-1 0 0";//A_1; A_2; A_3; A_4; A_5; A_6 A *= std::sqrt(double(3)/double(2)); B = "1 0 0;" "0 -1 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 1 0;" "1 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 1 0;" "0 0 -1;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 1;" "0 1 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "1 0 0;" "0 0 -1;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 0;" "0 0 1;" "1 0 0";//B_1; B_2; B_3; B_4; B_5; B_6 B *= std::sqrt(double(3)/double(2)); } else if (code_name=="39LD_3xN") { em_antenna = 3;//emission antenna channel_uses = 6;//channel uses symb_block = 6;//number of symbols/block A.set_size(36, 3); A(0,0) = 1/std::sqrt(2.0); A(0,1) = 0; A(0,2) = 0; A(1,0) = 0; A(1,1) = 1/std::sqrt(2.0); A(1,2) = 0; A(2,0) = 0; A(2,1) = 1/std::sqrt(2.0); A(2,2) = 0; A(3,0) = 0; A(3,1) = 0; A(3,2) = 1/std::sqrt(2.0); A(4,0) = 1/std::sqrt(2.0); A(4,1) = 0; A(4,2) = 0; A(5,0) = 0; A(5,1) = 0; A(5,2) = 1/std::sqrt(2.0);//A_1 A(6,0) = 0; A(6,1) = 1/std::sqrt(2.0); A(6,2) = 0; A(7,0) = -1/std::sqrt(2.0); A(7,1) = 0; A(7,2) = 0; A(8,0) = 0; A(8,1) = 0; A(8,2) = 1/std::sqrt(2.0); A(9,0) = 0; A(9,1) = -1/std::sqrt(2.0); A(9,2) = 0; A(10,0) = 0; A(10,1) = 0; A(10,2) = 1/std::sqrt(2.0); A(11,0) = -1/std::sqrt(2.0); A(11,1) = 0; A(11,2) = 0;//A_2 A(12,0) = 1/std::sqrt(2.0); A(12,1) = 0; A(12,2) = 0; A(13,0) = 0; A(13,1) = 1/std::sqrt(2.0); A(13,2) = 0; A(14,0) = 0; A(14,1) = -1/(2*std::sqrt(2.0)); A(14,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); A(15,0) = 0; A(15,1) = std::sqrt(3.0)/(2*std::sqrt(2.0)); A(15,2) = -1/(2*std::sqrt(2.0)); A(16,0) = -1/(2*std::sqrt(2.0)); A(16,1) = 0; A(16,2) = std::sqrt(3.0)/(2*std::sqrt(2.0)); A(17,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); A(17,1) = 0; A(17,2) = -1/(2*std::sqrt(2.0));//A_3 A(18,0) = 0; A(18,1) = 1/std::sqrt(2.0); A(18,2) = 0; A(19,0) = -1/std::sqrt(2.0); A(19,1) = 0; A(19,2) = 0; A(20,0) = 0; A(20,1) = std::sqrt(3.0)/(2*std::sqrt(2.0)); A(20,2) = -1/(2*std::sqrt(2.0)); A(21,0) = 0; A(21,1) = 1/(2*std::sqrt(2.0)); A(21,2) = std::sqrt(3.0)/(2*std::sqrt(2.0)); A(22,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); A(22,1) = 0; A(22,2) = -1/(2*std::sqrt(2.0)); A(23,0) = 1/(2*std::sqrt(2.0)); A(23,1) = 0; A(23,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));//A_4 A(24,0) = 1/std::sqrt(2.0); A(24,1) = 0; A(24,2) = 0; A(25,0) = 0; A(25,1) = 1/std::sqrt(2.0); A(25,2) = 0; A(26,0) = 0; A(26,1) = -1/(2*std::sqrt(2.0)); A(26,2) = std::sqrt(3.0)/(2*std::sqrt(2.0)); A(27,0) = 0; A(27,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); A(27,2) = -1/(2*std::sqrt(2.0)); A(28,0) = -1/(2*std::sqrt(2.0)); A(28,1) = 0; A(28,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); A(29,0) = std::sqrt(3.0)/(2*std::sqrt(2.0)); A(29,1) = 0; A(29,2) = -1/(2*std::sqrt(2.0));//A_5 A(30,0) = 0; A(30,1) = 1/std::sqrt(2.0); A(30,2) = 0; A(31,0) = -1/std::sqrt(2.0); A(31,1) = 0; A(31,2) = 0; A(32,0) = 0; A(32,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); A(32,2) = -1/(2*std::sqrt(2.0)); A(33,0) = 0; A(33,1) = 1/(2*std::sqrt(2.0)); A(33,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); A(34,0) = std::sqrt(3.0)/(2*std::sqrt(2.0)); A(34,1) = 0; A(34,2) = -1/(2*std::sqrt(2.0)); A(35,0) = 1/(2*std::sqrt(2.0)); A(35,1) = 0; A(35,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));//A_6 B.set_size(36, 3); B(0,0) = 1/std::sqrt(2.0); B(0,1) = 0; B(0,2) = 0; B(1,0) = 0; B(1,1) = -1/std::sqrt(2.0); B(1,2) = 0; B(2,0) = 0; B(2,1) = 1/std::sqrt(2.0); B(2,2) = 0; B(3,0) = 0; B(3,1) = 0; B(3,2) = -1/std::sqrt(2.0); B(4,0) = 1/std::sqrt(2.0); B(4,1) = 0; B(4,2) = 0; B(5,0) = 0; B(5,1) = 0; B(5,2) = -1/std::sqrt(2.0);//B_1 B(6,0) = 0; B(6,1) = 1/std::sqrt(2.0); B(6,2) = 0; B(7,0) = 1/std::sqrt(2.0); B(7,1) = 0; B(7,2) = 0; B(8,0) = 0; B(8,1) = 0; B(8,2) = 1/std::sqrt(2.0); B(9,0) = 0; B(9,1) = 1/std::sqrt(2.0); B(9,2) = 0; B(10,0) = 0; B(10,1) = 0; B(10,2) = 1/std::sqrt(2.0); B(11,0) = 1/std::sqrt(2.0); B(11,1) = 0; B(11,2) = 0;//B_2 B(12,0) = 1/std::sqrt(2.0); B(12,1) = 0; B(12,2) = 0; B(13,0) = 0; B(13,1) = -1/std::sqrt(2.0); B(13,2) = 0; B(14,0) = 0; B(14,1) = -1/(2*std::sqrt(2.0)); B(14,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); B(15,0) = 0; B(15,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); B(15,2) = 1/(2*std::sqrt(2.0)); B(16,0) = -1/(2*std::sqrt(2.0)); B(16,1) = 0; B(16,2) = std::sqrt(3.0)/(2*std::sqrt(2.0)); B(17,0) = std::sqrt(3.0)/(2*std::sqrt(2.0)); B(17,1) = 0; B(17,2) = 1/(2*std::sqrt(2.0));//B_3 B(18,0) = 0; B(18,1) = 1/std::sqrt(2.0); B(18,2) = 0; B(19,0) = 1/std::sqrt(2.0); B(19,1) = 0; B(19,2) = 0; B(20,0) = 0; B(20,1) = std::sqrt(3.0)/(2*std::sqrt(2.0)); B(20,2) = -1/(2*std::sqrt(2.0)); B(21,0) = 0; B(21,1) = -1/(2*std::sqrt(2.0)); B(21,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); B(22,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); B(22,1) = 0; B(22,2) = -1/(2*std::sqrt(2.0)); B(23,0) = -1/(2*std::sqrt(2.0)); B(23,1) = 0; B(23,2) = std::sqrt(3.0)/(2*std::sqrt(2.0));//B_4 B(24,0) = 1/std::sqrt(2.0); B(24,1) = 0; B(24,2) = 0; B(25,0) = 0; B(25,1) = -1/std::sqrt(2.0); B(25,2) = 0; B(26,0) = 0; B(26,1) = -1/(2*std::sqrt(2.0)); B(26,2) = std::sqrt(3.0)/(2*std::sqrt(2.0)); B(27,0) = 0; B(27,1) = std::sqrt(3.0)/(2*std::sqrt(2.0)); B(27,2) = 1/(2*std::sqrt(2.0)); B(28,0) = -1/(2*std::sqrt(2.0)); B(28,1) = 0; B(28,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); B(29,0) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); B(29,1) = 0; B(29,2) = 1/(2*std::sqrt(2.0));//B_5 B(30,0) = 0; B(30,1) = 1/std::sqrt(2.0); B(30,2) = 0; B(31,0) = 1/std::sqrt(2.0); B(31,1) = 0; B(31,2) = 0; B(32,0) = 0; B(32,1) = -std::sqrt(3.0)/(2*std::sqrt(2.0)); B(32,2) = -1/(2*std::sqrt(2.0)); B(33,0) = 0; B(33,1) = -1/(2*std::sqrt(2.0)); B(33,2) = std::sqrt(3.0)/(2*std::sqrt(2.0)); B(34,0) = std::sqrt(3.0)/(2*std::sqrt(2.0)); B(34,1) = 0; B(34,2) = -1/(2*std::sqrt(2.0)); B(35,0) = -1/(2*std::sqrt(2.0)); B(35,1) = 0; B(35,2) = -std::sqrt(3.0)/(2*std::sqrt(2.0));//B_6 } else { it_assert(false, "Unknown code name."); } }
bool Reed_Solomon::decode(const bvec &coded_bits, const ivec &erasure_positions, bvec &decoded_message, bvec &cw_isvalid) { bool decoderfailure, no_dec_failure; int j, i, kk, l, L, foundzeros, iterations = floor_i(static_cast<double>(coded_bits.length()) / (n * m)); bvec mbit(m * k); decoded_message.set_size(iterations * k * m, false); cw_isvalid.set_length(iterations); GFX rx(q, n - 1), cx(q, n - 1), mx(q, k - 1), ex(q, n - 1), S(q, 2 * t), Xi(q, 2 * t), Gamma(q), Lambda(q), Psiprime(q), OldLambda(q), T(q), Omega(q); GFX dummy(q), One(q, (char*)"0"), Omegatemp(q); GF delta(q), tempsum(q), rtemp(q), temp(q), Xk(q), Xkinv(q); ivec errorpos; if ( erasure_positions.length() ) { it_assert(max(erasure_positions) < iterations*n, "Reed_Solomon::decode: erasure position is invalid."); } no_dec_failure = true; for (i = 0; i < iterations; i++) { decoderfailure = false; //Fix the received polynomial r(x) for (j = 0; j < n; j++) { rtemp.set(q, coded_bits.mid(i * n * m + j * m, m)); rx[j] = rtemp; } // Fix the Erasure polynomial Gamma(x) // and replace erased coordinates with zeros rtemp.set(q, -1); ivec alphapow = - ones_i(2); Gamma = One; for (j = 0; j < erasure_positions.length(); j++) { rx[erasure_positions(j)] = rtemp; alphapow(1) = erasure_positions(j); Gamma *= (One - GFX(q, alphapow)); } //Fix the syndrome polynomial S(x). S.clear(); for (j = 1; j <= 2 * t; j++) { S[j] = rx(GF(q, b + j - 1)); } // calculate the modified syndrome polynomial Xi(x) = Gamma * (1+S) - 1 Xi = Gamma * (One + S) - One; // Apply Berlekam-Massey algorithm if (Xi.get_true_degree() >= 1) { //Errors in the received word // Iterate to find Lambda(x), which hold all error locations kk = 0; Lambda = One; L = 0; T = GFX(q, (char*)"-1 0"); while (kk < 2 * t) { kk = kk + 1; tempsum = GF(q, -1); for (l = 1; l <= L; l++) { tempsum += Lambda[l] * Xi[kk - l]; } delta = Xi[kk] - tempsum; if (delta != GF(q, -1)) { OldLambda = Lambda; Lambda -= delta * T; if (2 * L < kk) { L = kk - L; T = OldLambda / delta; } } T = GFX(q, (char*)"-1 0") * T; } // Find the zeros to Lambda(x) errorpos.set_size(Lambda.get_true_degree()); foundzeros = 0; for (j = q - 2; j >= 0; j--) { if (Lambda(GF(q, j)) == GF(q, -1)) { errorpos(foundzeros) = (n - j) % n; foundzeros += 1; if (foundzeros >= Lambda.get_true_degree()) { break; } } } if (foundzeros != Lambda.get_true_degree()) { decoderfailure = true; } else { // Forney algorithm... //Compute Omega(x) using the key equation for RS-decoding Omega.set_degree(2 * t); Omegatemp = Lambda * (One + Xi); for (j = 0; j <= 2 * t; j++) { Omega[j] = Omegatemp[j]; } //Find the error/erasure magnitude polynomial by treating them the same Psiprime = formal_derivate(Lambda*Gamma); errorpos = concat(errorpos, erasure_positions); ex.clear(); for (j = 0; j < errorpos.length(); j++) { Xk = GF(q, errorpos(j)); Xkinv = GF(q, 0) / Xk; // we calculate ex = - error polynomial, in order to avoid the // subtraction when recunstructing the corrected codeword ex[errorpos(j)] = (Xk * Omega(Xkinv)) / Psiprime(Xkinv); if (b != 1) { // non-narrow-sense code needs corrected error magnitudes int correction_exp = ( errorpos(j)*(1-b) ) % n; ex[errorpos(j)] *= GF(q, correction_exp + ( (correction_exp < 0) ? n : 0 )); } } //Reconstruct the corrected codeword. // instead of subtracting the error/erasures, we calculated // the negative error with 'ex' above cx = rx + ex; //Code word validation S.clear(); for (j = 1; j <= 2 * t; j++) { S[j] = cx(GF(q, b + j - 1)); } if (S.get_true_degree() >= 1) { decoderfailure = true; } } } else { cx = rx; decoderfailure = false; } //Find the message polynomial mbit.clear(); if (decoderfailure == false) { if (cx.get_true_degree() >= 1) { // A nonzero codeword was transmitted if (systematic) { for (j = 0; j < k; j++) { mx[j] = cx[j]; } } else { mx = divgfx(cx, g); } for (j = 0; j <= mx.get_true_degree(); j++) { mbit.replace_mid(j * m, mx[j].get_vectorspace()); } } } else { //Decoder failure. // for a systematic code it is better to extract the undecoded message // from the received code word, i.e. obtaining a bit error // prob. p_b << 1/2, than setting all-zero (p_b = 1/2) if (systematic) { mbit = coded_bits.mid(i * n * m, k * m); } else { mbit = zeros_b(k); } no_dec_failure = false; } decoded_message.replace_mid(i * m * k, mbit); cw_isvalid(i) = (!decoderfailure); } return no_dec_failure; }