template <class GF_q, class real> void sum_prod_alg_abstract<GF_q, real>::compute_probs( array1vd_t& ro) { //ensure the output vector has the right length ro.init(this->length_n); //initialise some helper variables int num_of_elements = GF_q::elements(); real a_n = real(0.0); int size_of_M_n = 0; int pos_m; for (int loop_n = 0; loop_n < this->length_n; loop_n++) { ro(loop_n) = this->received_probs(loop_n); size_of_M_n = this->M_n(loop_n).size(); for (int loop_e = 0; loop_e < num_of_elements; loop_e++) { for (int loop_m = 0; loop_m < size_of_M_n; loop_m++) { pos_m = this->M_n(loop_n)(loop_m) - 1;//we count from 0 ro(loop_n)(loop_e) *= this->marginal_probs(pos_m, loop_n).r_mxn( loop_e); } //Use appropriate clipping method perform_clipping(ro(loop_n)(loop_e)); } //Note the following step is not strictly necessary apart from making the result //look neater - however it only adds a small overhead //normalise the result so that q_n_0+q_n_1=1 a_n = ro(loop_n).sum(); assertalways(a_n!=real(0.0)); ro(loop_n) /= a_n; } }
template <class GF_q, class real> void linear_code_utils<GF_q, real>::encode_cw( const matrix<GF_q> & mat_G, const array1i_t & source, array1i_t & encoded) { #if DEBUG>=2 libbase::trace << std::endl << "encoding"; #endif //initialise encoded int length_n = mat_G.size().cols(); int dim_k = mat_G.size().rows(); assertalways(dim_k == source.size().length()); encoded.init(length_n); for (int i = 0; i < length_n; i++) { GF_q val = GF_q(0); for (int j = 0; j < dim_k; j++) { val += GF_q(source(j)) * mat_G(j, i); } encoded(i) = val; } #if DEBUG>=2 libbase::trace << std::endl << "finished encoding"; #endif }
void sum_prod_alg_trad<GF_q, real>::compute_q_mn(int m, int n, const array1i_t & M_n) { //initialise some helper variables int num_of_elements = GF_q::elements(); array1d_t q_mn(this -> received_probs(n)); int m_dash = 0; int pos_m = M_n(m) - 1;//we count from 1; //compute q_mn(sym) = a_mxn * P_n(sym) * \prod_{m'\in M(n)\m} r_m'xn(0) for all sym in GF_q int size_of_M_n = M_n.size().length(); for (int loop_m = 0; loop_m < size_of_M_n; loop_m++) { if (m != loop_m) { m_dash = M_n(loop_m) - 1; //we start counting from zero for (int loop_e = 0; loop_e < num_of_elements; loop_e++) { q_mn(loop_e) *= this->marginal_probs(m_dash, n).r_mxn(loop_e); } } } //normalise the q_mxn's so that q_mxn_0+q_mxn_1=1 real a_nxm = q_mn.sum();//sum up the values in q_mn assertalways(a_nxm!=real(0)); q_mn /= a_nxm; //normalise //store the values this->marginal_probs(pos_m, n).q_mxn = q_mn; }
void sum_prod_alg_trad<GF_q, real>::spa_init(const array1vd_t& recvd_probs) { //initialise the marginal prob values int num_of_elements = GF_q::elements(); real tmp_prob = real(0.0); real alpha = real(0.0); //ensure we don't have zero probabilities //and normalise the probs at the same time this->received_probs.init(recvd_probs.size()); for (int loop_n = 0; loop_n < this->length_n; loop_n++) { this->received_probs(loop_n).init(num_of_elements); alpha = real(0.0); for (int loop_e = 0; loop_e < num_of_elements; loop_e++) { tmp_prob = recvd_probs(loop_n)(loop_e); //Clipping HACK perform_clipping(tmp_prob); this->received_probs(loop_n)(loop_e) = tmp_prob; alpha += tmp_prob; } assertalways(alpha!=real(0.0)); this->received_probs(loop_n) /= alpha; } //this uses the description of the algorithm as given by //MacKay in Information Theory, Inference and Learning Algorithms(2003) //on page 560 - chapter 47.3 //some helper variables int pos = 0; int non_zeros = 0; //simply set q_mxn(0)=P_n(0)=P(x_n=0) and q_mxn(1)=P_n(1)=P(x_n=1) for (int loop_m = 0; loop_m < this->dim_m; loop_m++) { non_zeros = this->N_m(loop_m).size(); for (int loop_n = 0; loop_n < non_zeros; loop_n++) { pos = this->N_m(loop_m)(loop_n) - 1;//we count from zero; this->marginal_probs(loop_m, pos).q_mxn = this->received_probs(pos); this->marginal_probs(loop_m, pos).r_mxn.init(num_of_elements); this->marginal_probs(loop_m, pos).r_mxn = 0.0; } } #if DEBUG>=2 libbase::trace << " Memory Usage:\n "; libbase::trace << this->marginal_probs.size() * sizeof(sum_prod_alg_abstract<GF_q,real>::marginals) / double(1 << 20) << " MB" << std::endl; libbase::trace << std::endl << "The marginal matrix is given by:" << std::endl; this->print_marginal_probs(libbase::trace); #endif }
stream_lut<real>::stream_lut(const char *filename, FILE *file, const int tau, const int m) { stream_lut::m = m; const char *s = strrchr(filename, libbase::DIR_SEPARATOR); const char *p = (s == NULL) ? filename : s + 1; this->lutname = p; this->lut.init(tau); char buf[256]; for (int i = 0; i < tau - m; i++) { do { assertalways(fscanf(file, "%[^\n]\n", buf) == 1); } while (buf[0] == '#'); int y; sscanf(buf, "%d", &y); this->lut(i) = y; } for (int t = tau - m; t < tau; t++) this->lut(t) = fsm::tail; }
gf_fast<m, poly> gf_fast<m, poly>::inverse() const { //0 does not have an inverse assertalways(0!=this->value); int tmp = (this->elements() - 1 - this->pow_of_alpha); return gf_fast<m, poly> (gf_fast<m, poly>::pow_lut[tmp]); }
template <class GF_q, class real> bool linear_code_utils<GF_q, real>::compute_syndrome( const matrix<GF_q> & parMat, const array1gfq_t & received_word_hd, array1gfq_t & syndrome_vec) { bool dec_success = true; int dim_m = parMat.size().rows(); int length_n = parMat.size().cols(); //check that we have compatible lengths assertalways(received_word_hd.size().length() == length_n); syndrome_vec.init(dim_m); GF_q tmp_val = GF_q(0); for (int rows = 0; rows < dim_m; rows++) { tmp_val = GF_q(0); for (int cols = 0; cols < length_n; cols++) { tmp_val += parMat(rows, cols) * received_word_hd(cols); } if (tmp_val != GF_q(0)) { //the syndrome is non-zero dec_success = false; } syndrome_vec(rows) = tmp_val; } return dec_success; }
void map_dividing<libbase::vector, dbl, dbl2>::doinverse(const array1vd_t& pin, array1vd_t& pout) const { // Confirm input sequence to be of the correct length assertalways(pin.size() == This::output_block_size()); // Create converter object and perform necessary transform libbase::symbol_converter<dbl,dbl2> converter(Base::M, Base::q); converter.aggregate_probabilities(pin, pout); }
void map_dividing<libbase::vector, dbl, dbl2>::dotransform(const array1i_t& in, array1i_t& out) const { // Confirm input sequence to be of the correct length assertalways(in.size() == this->input_block_size()); // Create converter object and perform necessary transform libbase::symbol_converter<dbl,dbl2> converter(Base::M, Base::q); converter.divide_symbols(in, out); }
void map_punctured<libbase::vector, dbl>::dotransform(const array1i_t& in, array1i_t& out) const { // final vector size depends on the number of set positions assertalways(in.size() == pattern.size()); out.init(This::output_block_size()); // puncture the results for (int i = 0, ii = 0; i < in.size(); i++) if (pattern(i)) out(ii++) = in(i); }
void map_punctured<libbase::vector, dbl>::advance() const { assertalways(Base::size > 0); // check if matrix is already set if (pattern.size() == Base::size.length()) return; // shorthand for puncturing matrix rate (p of P) const int p = libbase::matrix<int>(punc_matrix).sum(); const int P = punc_matrix.size(); assertalways(P > 0); assertalways(p > 0); // find out how many times the puncturing matrix fits const int n = Base::size.length() / P; assert(Base::size.length() == n * P); // initialise the pattern matrix pattern.init(Base::size.length()); for (int t = 0, k = 0; k < n; k++) for (int i = 0; i < punc_matrix.size().rows(); i++) for (int j = 0; j < punc_matrix.size().cols(); j++, t++) pattern(t) = punc_matrix(i, j); }
void lut_interleaver<real>::transform(const libbase::vector<int>& in, libbase::vector<int>& out) const { const int tau = lut.size(); assertalways(in.size() == tau); out.init(in.size()); for (int t = 0; t < tau; t++) if (lut(t) == fsm::tail) out(t) = fsm::tail; else out(t) = in(lut(t)); }
void lut_interleaver<real>::inverse(const libbase::matrix<real>& in, libbase::matrix<real>& out) const { const int tau = lut.size(); const int K = in.size().cols(); assertalways(in.size().rows() == tau); out.init(in.size()); for (int t = 0; t < tau; t++) if (lut(t) == fsm::tail) for (int i = 0; i < K; i++) out(t, i) = real(1.0 / K); else for (int i = 0; i < K; i++) out(lut(t), i) = in(t, i); }
gf_fast<m, poly>& gf_fast<m, poly>::operator/=(const gf_fast<m, poly>& x) { //ensure we do not divide by 0 assertalways(0!=x); //only need to do any work if we are not 0 if (0 != this->value) { this->pow_of_alpha += (this->elements() - 1); this->pow_of_alpha = (this->pow_of_alpha - x.log_gf()) % (this->elements() - 1); this->value = gf_fast<m, poly>::pow_lut[this->pow_of_alpha]; } return *this; }
anneal_puncturing::anneal_puncturing(const char *fname, const int tau, const int s) { // store user parameters anneal_puncturing::tau = tau; anneal_puncturing::s = s; // initialise contribution matrix and load contribution matrix from file contrib.init(s, tau, tau); FILE *file = fopen(fname, "rb"); if (file == NULL) { std::cerr << "FATAL ERROR (anneal_puncturing): Cannot open contribution file (" << fname << ")." << std::endl; exit(1); } for (int i = 0; i < tau; i++) for (int j = 0; j < s; j++) for (int k = 0; k < tau; k++) { double temp; if (fscanf(file, "%lf", &temp) == 0) assertalways(fscanf(file, "%*[^\n]\n") == 0); contrib(j, i, k) = temp; } fclose(file); // initialise the puncturing pattern as odd-even (and transmitting all data bits) { pattern.init(s, tau); for (int i = 0; i < s; i++) for (int j = 0; j < tau; j++) pattern(i, j) = (i == 0 || (i - 1) % 2 == j % 2); } // initialise the working vectors res.init(tau); res = 0; // now work the energy { for (int i = 0; i < s; i++) for (int j = 0; j < tau; j++) if (!pattern(i, j)) energy_function(1, i, j); } // work out the system's initial energy E = work_energy(); }
vale96int<real>::vale96int() { // set name and forced tail length this->lutname = "vale96int"; this->m = 0; // build LUT const int tau = 34; const int a[] = {16, 29, 9, 10, 14, 6, 31, 8, 12, 22, 17, 33, 34, 23, 24, 19, 32, 30, 13, 2, 21, 25, 26, 3, 28, 20, 27, 7, 5, 15, 4, 11, 18, 1}; this->lut.init(tau); this->lut = -1; for (int i = 0; i < tau; i++) { const int ndx = a[i] - 1; // check for duplicate entries assertalways(this->lut(ndx) == -1); this->lut(ndx) = i; } }
void padded<real>::advance() { assertalways(otp); otp->advance(); }
void padded<real>::seedfrom(libbase::random& r) { assertalways(otp); otp->seedfrom(r); }
template <class GF_q, class real> void linear_code_utils<GF_q, real>::compute_dual_code( const matrix<GF_q> & orgMat, matrix<GF_q> & dualCodeGenMatrix, array1i_t & systematic_perm) { int length_n = orgMat.size().cols(); int dim_k = orgMat.size().rows(); int dim_m = length_n - dim_k; matrix<GF_q> refOrgMat; #if DEBUG>=2 std::cout << "The original matrix is given by:" << std::endl; orgMat.serialize(std::cout, '\n'); #endif linear_code_utils::compute_row_dim(orgMat, refOrgMat); dim_k = refOrgMat.size().rows(); dim_m = length_n - dim_k; // Now we need to check that the columns are systematic //if they aren't then we need to perform some column permutation //otherwise the permutation is simple the identy map systematic_perm.init(length_n); for (int loop1 = 0; loop1 < length_n; loop1++) { //the identity permutation systematic_perm(loop1) = loop1; } bool needsPermutation = !(libbase::linear_code_utils<GF_q, real>::is_systematic(refOrgMat)); if (needsPermutation) { //matrix needs its columns permuted before it is in systematic form //find the pivots int col_pos = 0; for (int loop1 = 0; loop1 < dim_k; loop1++) { while ((GF_q(1)) != refOrgMat(loop1, col_pos)) { col_pos++; } std::swap(systematic_perm(loop1), systematic_perm(col_pos)); col_pos++; } #if DEBUG>=2 std::cout << std::endl << "The permutation is given by:" << std::endl; systematic_perm.serialize(std::cout, ' '); #endif if (needsPermutation) { //rejig the matrix matrix<GF_q> tmprefMatrix; tmprefMatrix.init(dim_k, length_n); int col_index; for (int loop1 = 0; loop1 < length_n; loop1++) { col_index = systematic_perm(loop1); tmprefMatrix.insertcol(refOrgMat.extractcol(col_index), loop1); } refOrgMat = tmprefMatrix; } } //the matrix should now be in the right format #if DEBUG>=2 std::cout << "After permuting any columns, the matrix is now given by:" << std::endl; refOrgMat.serialize(std::cout, '\n'); #endif //extract the P part of G'=(I_k|P) matrix<GF_q> tmp_p_mat; tmp_p_mat.init(dim_k, dim_m); for (int loop = dim_k; loop < length_n; loop++) { tmp_p_mat.insertcol(refOrgMat.extractcol(loop), loop - dim_k); } //this will hold -P^t=P^t (as we are in char GF(q)=2) matrix<GF_q> tmp_p_mat_t; tmp_p_mat_t.init(dim_m, length_n - dim_m); //now transpose yourself tmp_p_mat_t = tmp_p_mat.transpose(); matrix<GF_q> id_m = matrix<GF_q>::eye(dim_m); //Construct the dual code gen matrix which is of the form //H=(-P^t|I_m) dualCodeGenMatrix.init(dim_m, length_n); //insert the transposed matrix for (int loop = 0; loop < (length_n - dim_m); loop++) { dualCodeGenMatrix.insertcol(tmp_p_mat_t.extractcol(loop), loop); } //now add the identity matrix int counter = 0; for (int loop = (length_n - dim_m); loop < length_n; loop++) { dualCodeGenMatrix.insertcol(id_m.extractcol(counter), loop); counter++; } #if DEBUG>=2 std::cout << "The generator matrix of the permuted dual code is given by:" << std::endl; dualCodeGenMatrix.serialize(std::cout, '\n'); #endif //undo any permutation that we did if (needsPermutation) { matrix<GF_q> tmpdualCodeGenMatrix; tmpdualCodeGenMatrix.init(dim_m, length_n); int col_index; for (int loop1 = 0; loop1 < length_n; loop1++) { col_index = systematic_perm(loop1); tmpdualCodeGenMatrix.insertcol(dualCodeGenMatrix.extractcol(loop1), col_index); } dualCodeGenMatrix = tmpdualCodeGenMatrix; } #if DEBUG>=2 std::cout << "After undoing the permutation, the generator matrix of the dual code is given by:" << std::endl; dualCodeGenMatrix.serialize(std::cout, '\n'); #endif #if DEBUG>=2 std::cout << "we now multiply the generator matrix by the transpose of the original matrix, ie:" << std::endl; std::cout << "the transpose of:" << std::endl; orgMat.serialize(std::cout, '\n'); std::cout << "is:" << std::endl; matrix<GF_q> trans(orgMat.transpose()); trans.serialize(std::cout, '\n'); matrix<GF_q> zeroTest(dualCodeGenMatrix*trans); std::cout << "the result is:" << std::endl; zeroTest.serialize(std::cout, '\n'); assertalways(GF_q(0)==zeroTest.max()); #endif }