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 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 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 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); }
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 }
void sum_prod_alg_trad<GF_q, real>::compute_r_mn(int m, int n, const array1i_t & tmpN_m) { //the number of remaining symbols that can vary int num_of_var_syms = tmpN_m.size() - 1; int num_of_elements = GF_q::elements(); //for each check node we need to consider num_of_elements^num_of_var_symbols cases int num_of_cases = int(pow(num_of_elements, num_of_var_syms)); int pos_n = tmpN_m(n) - 1;//we count from 1; int bitmask = num_of_elements - 1; //only use the entries that are variable array1i_t rel_N_m; rel_N_m.init(num_of_var_syms); int indx = 0; for (int loop = 0; loop < num_of_var_syms; loop++) { if (indx == n) { indx++; } rel_N_m(loop) = tmpN_m(indx); indx++; } //go through all cases - this will use bitwise manipulation GF_q syndrome_sym = GF_q(0); GF_q h_m_n_dash; //GF_q h_m_n; GF_q tmp_chk_val; int int_sym_val; int bits; int pos_n_dash; real q_nm_prod = real(1.0); this->marginal_probs(m, pos_n).r_mxn = 0.0; GF_q check_value = this->marginal_probs(m, pos_n).val; for (int loop1 = 0; loop1 < num_of_cases; loop1++) { bits = loop1; syndrome_sym = GF_q(0); q_nm_prod = 1.0; for (int loop2 = 0; loop2 < num_of_var_syms; loop2++) { pos_n_dash = rel_N_m(loop2) - 1;//we count from zero //extract int value of the first symbol int_sym_val = bits & bitmask; //shift bits to the right by the dimension of the finite field bits = bits >> GF_q::dimension(); //the parity check symbol at this position h_m_n_dash = this->marginal_probs(m, pos_n_dash).val; //compute the value that at this check tmp_chk_val = h_m_n_dash * GF_q(int_sym_val); //add it to the syndrome syndrome_sym = syndrome_sym + tmp_chk_val; //look up the prob that the chk_val was actually sent q_nm_prod *= this->marginal_probs(m, pos_n_dash).q_mxn(int_sym_val); } //adjust the appropriate rmn value int_sym_val = syndrome_sym / check_value; this->marginal_probs(m, pos_n).r_mxn(int_sym_val) += q_nm_prod; } }