diff options
Diffstat (limited to 'gr-fec/lib/ldpc_G_matrix_impl.cc')
-rw-r--r-- | gr-fec/lib/ldpc_G_matrix_impl.cc | 454 |
1 files changed, 222 insertions, 232 deletions
diff --git a/gr-fec/lib/ldpc_G_matrix_impl.cc b/gr-fec/lib/ldpc_G_matrix_impl.cc index 0ea76f2ef4..a17c571ec9 100644 --- a/gr-fec/lib/ldpc_G_matrix_impl.cc +++ b/gr-fec/lib/ldpc_G_matrix_impl.cc @@ -29,270 +29,260 @@ #include <iostream> namespace gr { - namespace fec { - namespace code { - - ldpc_G_matrix::sptr - ldpc_G_matrix::make(const std::string filename) - { - return ldpc_G_matrix::sptr - (new ldpc_G_matrix_impl(filename)); - } - - ldpc_G_matrix_impl::ldpc_G_matrix_impl(const std::string filename) - : fec_mtrx_impl() - { - configure_default_loggers(d_logger, d_debug_logger, "ldpc_G_matrix"); - - // Read the matrix from a file in alist format - matrix_sptr x = read_matrix_from_file(filename); - d_num_cols = x->size2; - d_num_rows = x->size1; - - // Make an actual copy so we guarantee that we're not sharing - // memory with another class that reads the same alist file. - gsl_matrix *G = gsl_matrix_alloc(d_num_rows, d_num_cols); - gsl_matrix_memcpy(G, (gsl_matrix*)(x.get())); - - unsigned int row_index, col_index; - - // First, check if we have a generator matrix G in systematic - // form, G = [I P], where I is a k x k identity matrix and P - // is the parity submatrix. - - // Length of codeword = # of columns of generator matrix - d_n = d_num_cols; - // Length of information word = # of rows of generator matrix - d_k = d_num_rows; - - gsl_matrix *I_test = gsl_matrix_alloc(d_k, d_k); - gsl_matrix *identity = gsl_matrix_alloc(d_k, d_k); - gsl_matrix_set_identity(identity); - - for(row_index = 0; row_index < d_k; row_index++) { - for(col_index = 0; col_index < d_k; col_index++) { - int value = gsl_matrix_get(G, row_index, col_index); - gsl_matrix_set(I_test, row_index, col_index, value); - } - } +namespace fec { +namespace code { - // Check if the identity matrix exists in the right spot. - //int test_if_equal = gsl_matrix_equal(identity, I_test); - gsl_matrix_sub(identity, I_test); // should be null set if equal - double test_if_not_equal = gsl_matrix_max(identity); - - // Free memory - gsl_matrix_free(identity); - gsl_matrix_free(I_test); - - //if(!test_if_equal) { - if(test_if_not_equal > 0) { - GR_LOG_ERROR(d_logger, - "Error in ldpc_G_matrix_impl constructor. It appears " - "that the given alist file did not contain either a " - "valid parity check matrix of the form H = [P' I] or " - "a generator matrix of the form G = [I P].\n"); - throw std::runtime_error("ldpc_G_matrix: Bad matrix definition"); - } - - // Our G matrix is verified as correct, now convert it to the - // parity check matrix. +ldpc_G_matrix::sptr ldpc_G_matrix::make(const std::string filename) +{ + return ldpc_G_matrix::sptr(new ldpc_G_matrix_impl(filename)); +} - // Grab P matrix - gsl_matrix *P = gsl_matrix_alloc(d_k, d_n-d_k); - for(row_index = 0; row_index < d_k; row_index++) { - for(col_index = 0; col_index < d_n-d_k; col_index++) { - int value = gsl_matrix_get(G, row_index, col_index + d_k); - gsl_matrix_set(P, row_index, col_index, value); - } - } +ldpc_G_matrix_impl::ldpc_G_matrix_impl(const std::string filename) : fec_mtrx_impl() +{ + configure_default_loggers(d_logger, d_debug_logger, "ldpc_G_matrix"); - // Calculate P transpose - gsl_matrix *P_transpose = gsl_matrix_alloc(d_n-d_k, d_k); - gsl_matrix_transpose_memcpy(P_transpose, P); + // Read the matrix from a file in alist format + matrix_sptr x = read_matrix_from_file(filename); + d_num_cols = x->size2; + d_num_rows = x->size1; - // Set H matrix. H = [-P' I] but since we are doing mod 2, - // -P = P, so H = [P' I] - gsl_matrix *H_ptr = gsl_matrix_alloc(d_n-d_k, d_n); - gsl_matrix_set_zero(H_ptr); - for(row_index = 0; row_index < d_n-d_k; row_index++) { - for(col_index = 0; col_index < d_k; col_index++) { - int value = gsl_matrix_get(P_transpose, row_index, col_index); - gsl_matrix_set(H_ptr, row_index, col_index, value); - } - } + // Make an actual copy so we guarantee that we're not sharing + // memory with another class that reads the same alist file. + gsl_matrix* G = gsl_matrix_alloc(d_num_rows, d_num_cols); + gsl_matrix_memcpy(G, (gsl_matrix*)(x.get())); - for(row_index = 0; row_index < (d_n-d_k); row_index++) { - col_index = row_index + d_k; - gsl_matrix_set(H_ptr, row_index, col_index, 1); - } + unsigned int row_index, col_index; - // Calculate G transpose (used for encoding) - d_G_transp_ptr = gsl_matrix_alloc(d_n, d_k); - gsl_matrix_transpose_memcpy(d_G_transp_ptr, G); + // First, check if we have a generator matrix G in systematic + // form, G = [I P], where I is a k x k identity matrix and P + // is the parity submatrix. - d_H_sptr = matrix_sptr((matrix*)H_ptr); + // Length of codeword = # of columns of generator matrix + d_n = d_num_cols; + // Length of information word = # of rows of generator matrix + d_k = d_num_rows; - // Free memory - gsl_matrix_free(P); - gsl_matrix_free(P_transpose); - gsl_matrix_free(G); - } + gsl_matrix* I_test = gsl_matrix_alloc(d_k, d_k); + gsl_matrix* identity = gsl_matrix_alloc(d_k, d_k); + gsl_matrix_set_identity(identity); - - const gsl_matrix* - ldpc_G_matrix_impl::G_transpose() const - { - const gsl_matrix *G_trans_ptr = d_G_transp_ptr; - return G_trans_ptr; - } - - void - ldpc_G_matrix_impl::encode(unsigned char *outbuffer, - const unsigned char *inbuffer) const - { - - unsigned int index, k = d_k, n = d_n; - gsl_matrix *s = gsl_matrix_alloc(k, 1); - for(index = 0; index < k; index++) { - double value = static_cast<double>(inbuffer[index]); - gsl_matrix_set(s, index, 0, value); - } - - // Simple matrix multiplication to get codeword - gsl_matrix *codeword = gsl_matrix_alloc(G_transpose()->size1, s->size2); - mult_matrices_mod2(codeword, G_transpose(), s); - - // Output - for(index = 0; index < n; index++) { - outbuffer[index] = gsl_matrix_get(codeword, index, 0); + for (row_index = 0; row_index < d_k; row_index++) { + for (col_index = 0; col_index < d_k; col_index++) { + int value = gsl_matrix_get(G, row_index, col_index); + gsl_matrix_set(I_test, row_index, col_index, value); } - - // Free memory - gsl_matrix_free(s); - gsl_matrix_free(codeword); - } - - - void - ldpc_G_matrix_impl::decode(unsigned char *outbuffer, - const float *inbuffer, - unsigned int frame_size, - unsigned int max_iterations) const - { - unsigned int index, n = d_n; - gsl_matrix *x = gsl_matrix_alloc(n, 1); - for (index = 0; index < n; index++) { - double value = inbuffer[index] > 0 ? 1.0 : 0.0; - gsl_matrix_set(x, index, 0, value); + } + + // Check if the identity matrix exists in the right spot. + // int test_if_equal = gsl_matrix_equal(identity, I_test); + gsl_matrix_sub(identity, I_test); // should be null set if equal + double test_if_not_equal = gsl_matrix_max(identity); + + // Free memory + gsl_matrix_free(identity); + gsl_matrix_free(I_test); + + // if(!test_if_equal) { + if (test_if_not_equal > 0) { + GR_LOG_ERROR(d_logger, + "Error in ldpc_G_matrix_impl constructor. It appears " + "that the given alist file did not contain either a " + "valid parity check matrix of the form H = [P' I] or " + "a generator matrix of the form G = [I P].\n"); + throw std::runtime_error("ldpc_G_matrix: Bad matrix definition"); + } + + // Our G matrix is verified as correct, now convert it to the + // parity check matrix. + + // Grab P matrix + gsl_matrix* P = gsl_matrix_alloc(d_k, d_n - d_k); + for (row_index = 0; row_index < d_k; row_index++) { + for (col_index = 0; col_index < d_n - d_k; col_index++) { + int value = gsl_matrix_get(G, row_index, col_index + d_k); + gsl_matrix_set(P, row_index, col_index, value); } - - // Initialize counter - unsigned int count = 0; - - // Calculate syndrome - gsl_matrix *syndrome = gsl_matrix_alloc(H()->size1, x->size2); - mult_matrices_mod2(syndrome, H(), x); - - // Flag for finding a valid codeword - bool found_word = false; - - // If the syndrome is all 0s, then codeword is valid and we - // don't need to loop; we're done. - if (gsl_matrix_isnull(syndrome)) { - found_word = true; + } + + // Calculate P transpose + gsl_matrix* P_transpose = gsl_matrix_alloc(d_n - d_k, d_k); + gsl_matrix_transpose_memcpy(P_transpose, P); + + // Set H matrix. H = [-P' I] but since we are doing mod 2, + // -P = P, so H = [P' I] + gsl_matrix* H_ptr = gsl_matrix_alloc(d_n - d_k, d_n); + gsl_matrix_set_zero(H_ptr); + for (row_index = 0; row_index < d_n - d_k; row_index++) { + for (col_index = 0; col_index < d_k; col_index++) { + int value = gsl_matrix_get(P_transpose, row_index, col_index); + gsl_matrix_set(H_ptr, row_index, col_index, value); } - - // Loop until valid codeword is found, or max number of - // iterations is reached, whichever comes first - while ((count < max_iterations) && !found_word) { - // For each of the n bits in the codeword, determine how - // many of the unsatisfied parity checks involve that bit. - // To do this, first find the nonzero entries in the - // syndrome. The entry numbers correspond to the rows of - // interest in H. - std::vector<int> rows_of_interest_in_H; - for (index = 0; index < (*syndrome).size1; index++) { + } + + for (row_index = 0; row_index < (d_n - d_k); row_index++) { + col_index = row_index + d_k; + gsl_matrix_set(H_ptr, row_index, col_index, 1); + } + + // Calculate G transpose (used for encoding) + d_G_transp_ptr = gsl_matrix_alloc(d_n, d_k); + gsl_matrix_transpose_memcpy(d_G_transp_ptr, G); + + d_H_sptr = matrix_sptr((matrix*)H_ptr); + + // Free memory + gsl_matrix_free(P); + gsl_matrix_free(P_transpose); + gsl_matrix_free(G); +} + + +const gsl_matrix* ldpc_G_matrix_impl::G_transpose() const +{ + const gsl_matrix* G_trans_ptr = d_G_transp_ptr; + return G_trans_ptr; +} + +void ldpc_G_matrix_impl::encode(unsigned char* outbuffer, + const unsigned char* inbuffer) const +{ + + unsigned int index, k = d_k, n = d_n; + gsl_matrix* s = gsl_matrix_alloc(k, 1); + for (index = 0; index < k; index++) { + double value = static_cast<double>(inbuffer[index]); + gsl_matrix_set(s, index, 0, value); + } + + // Simple matrix multiplication to get codeword + gsl_matrix* codeword = gsl_matrix_alloc(G_transpose()->size1, s->size2); + mult_matrices_mod2(codeword, G_transpose(), s); + + // Output + for (index = 0; index < n; index++) { + outbuffer[index] = gsl_matrix_get(codeword, index, 0); + } + + // Free memory + gsl_matrix_free(s); + gsl_matrix_free(codeword); +} + + +void ldpc_G_matrix_impl::decode(unsigned char* outbuffer, + const float* inbuffer, + unsigned int frame_size, + unsigned int max_iterations) const +{ + unsigned int index, n = d_n; + gsl_matrix* x = gsl_matrix_alloc(n, 1); + for (index = 0; index < n; index++) { + double value = inbuffer[index] > 0 ? 1.0 : 0.0; + gsl_matrix_set(x, index, 0, value); + } + + // Initialize counter + unsigned int count = 0; + + // Calculate syndrome + gsl_matrix* syndrome = gsl_matrix_alloc(H()->size1, x->size2); + mult_matrices_mod2(syndrome, H(), x); + + // Flag for finding a valid codeword + bool found_word = false; + + // If the syndrome is all 0s, then codeword is valid and we + // don't need to loop; we're done. + if (gsl_matrix_isnull(syndrome)) { + found_word = true; + } + + // Loop until valid codeword is found, or max number of + // iterations is reached, whichever comes first + while ((count < max_iterations) && !found_word) { + // For each of the n bits in the codeword, determine how + // many of the unsatisfied parity checks involve that bit. + // To do this, first find the nonzero entries in the + // syndrome. The entry numbers correspond to the rows of + // interest in H. + std::vector<int> rows_of_interest_in_H; + for (index = 0; index < (*syndrome).size1; index++) { if (gsl_matrix_get(syndrome, index, 0)) { - rows_of_interest_in_H.push_back(index); + rows_of_interest_in_H.push_back(index); } - } - - // Second, for each bit, determine how many of the - // unsatisfied parity checks involve this bit and store - // the count. - unsigned int i, col_num, n = d_n; - std::vector<int> counts(n,0); - for (i = 0; i < rows_of_interest_in_H.size(); i++) { + } + + // Second, for each bit, determine how many of the + // unsatisfied parity checks involve this bit and store + // the count. + unsigned int i, col_num, n = d_n; + std::vector<int> counts(n, 0); + for (i = 0; i < rows_of_interest_in_H.size(); i++) { unsigned int row_num = rows_of_interest_in_H[i]; for (col_num = 0; col_num < n; col_num++) { - double value = gsl_matrix_get(H(), - row_num, - col_num); - if (value > 0) { - counts[col_num] = counts[col_num] + 1; - } + double value = gsl_matrix_get(H(), row_num, col_num); + if (value > 0) { + counts[col_num] = counts[col_num] + 1; + } } - } + } - // Next, determine which bit(s) is associated with the most - // unsatisfied parity checks, and flip it/them. - int max = 0; - for (index = 0; index < n; index++) { + // Next, determine which bit(s) is associated with the most + // unsatisfied parity checks, and flip it/them. + int max = 0; + for (index = 0; index < n; index++) { if (counts[index] > max) { - max = counts[index]; + max = counts[index]; } - } + } - for (index = 0; index < n; index++) { + for (index = 0; index < n; index++) { if (counts[index] == max) { - unsigned int value = gsl_matrix_get(x, index, 0); - unsigned int new_value = value ^ 1; - gsl_matrix_set(x, index, 0, new_value); + unsigned int value = gsl_matrix_get(x, index, 0); + unsigned int new_value = value ^ 1; + gsl_matrix_set(x, index, 0, new_value); } - } + } - // Check the syndrome; see if valid codeword has been found - mult_matrices_mod2(syndrome, H(), x); - if (gsl_matrix_isnull(syndrome)) { + // Check the syndrome; see if valid codeword has been found + mult_matrices_mod2(syndrome, H(), x); + if (gsl_matrix_isnull(syndrome)) { found_word = true; break; - } - count++; } + count++; + } - // Extract the info word and assign to output. This will - // happen regardless of if a valid codeword was found. - if(parity_bits_come_last()) { - for(index = 0; index < frame_size; index++) { + // Extract the info word and assign to output. This will + // happen regardless of if a valid codeword was found. + if (parity_bits_come_last()) { + for (index = 0; index < frame_size; index++) { outbuffer[index] = gsl_matrix_get(x, index, 0); - } } - else { - for(index = 0; index < frame_size; index++) { + } else { + for (index = 0; index < frame_size; index++) { unsigned int i = index + n - frame_size; int value = gsl_matrix_get(x, i, 0); outbuffer[index] = value; - } } - - // Free memory - gsl_matrix_free(syndrome); - gsl_matrix_free(x); - } - - gr::fec::code::fec_mtrx_sptr - ldpc_G_matrix_impl::get_base_sptr() - { - return shared_from_this(); - } - - ldpc_G_matrix_impl::~ldpc_G_matrix_impl() - { - // Call the gsl_matrix_free function to free memory. - gsl_matrix_free(d_G_transp_ptr); - gsl_matrix_free(d_H_obj); - } - } /* namespace code */ - } /* namespace fec */ + } + + // Free memory + gsl_matrix_free(syndrome); + gsl_matrix_free(x); +} + +gr::fec::code::fec_mtrx_sptr ldpc_G_matrix_impl::get_base_sptr() +{ + return shared_from_this(); +} + +ldpc_G_matrix_impl::~ldpc_G_matrix_impl() +{ + // Call the gsl_matrix_free function to free memory. + gsl_matrix_free(d_G_transp_ptr); + gsl_matrix_free(d_H_obj); +} +} /* namespace code */ +} /* namespace fec */ } /* namespace gr */ |