From deb6ede15fc9fe49d24d77f18016da6eb0f623f4 Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Sat, 22 Sep 2018 10:52:55 +0200 Subject: [PATCH] keep non-bitpacked BCH decoder as reference --- bose_chaudhuri_hocquenghem_decoder.hh | 103 ++++++++++++++------------ tests/bch_decoder_test.cc | 45 +++++++++++ 2 files changed, 102 insertions(+), 46 deletions(-) diff --git a/bose_chaudhuri_hocquenghem_decoder.hh b/bose_chaudhuri_hocquenghem_decoder.hh index e169ef8..65e95f2 100644 --- a/bose_chaudhuri_hocquenghem_decoder.hh +++ b/bose_chaudhuri_hocquenghem_decoder.hh @@ -14,6 +14,63 @@ namespace CODE { template class BoseChaudhuriHocquenghemDecoder { +public: + typedef typename GF::value_type value_type; + typedef typename GF::ValueType ValueType; + typedef typename GF::IndexType IndexType; + static const int N = GF::N, K = MSG, NP = N - K; + ReedSolomonErrorCorrection algorithm; + int compute_syndromes(uint8_t *code, ValueType *syndromes) + { + // $syndromes_i = code(pe^{FCR+i})$ + for (int i = 0; i < NR; ++i) + syndromes[i] = ValueType((code[0] >> 7) & 1); + for (int j = 1; j < N; ++j) { + IndexType root(FCR), pe(1); + for (int i = 0; i < NR; ++i) { + syndromes[i] = fma(root, syndromes[i], ValueType((code[j / 8] >> (7 - j % 8)) & 1)); + root *= pe; + } + } + int nonzero = 0; + for (int i = 0; i < NR; ++i) + nonzero += !!syndromes[i]; + return nonzero; + } + int compute_syndromes(uint8_t *code, value_type *syndromes) + { + return compute_syndromes(code, reinterpret_cast(syndromes)); + } + int operator()(uint8_t *code, value_type *erasures = 0, int erasures_count = 0) + { + assert(0 <= erasures_count && erasures_count <= NR); + if (0) { + for (int i = 0; i < erasures_count; ++i) + code[erasures[i] / 8] &= ~(128 >> (erasures[i] % 8)); + } + ValueType syndromes[NR]; + if (!compute_syndromes(code, syndromes)) + return 0; + IndexType locations[NR]; + ValueType magnitudes[NR]; + int count = algorithm(syndromes, locations, magnitudes, reinterpret_cast(erasures), erasures_count); + if (count <= 0) + return count; + for (int i = 0; i < count; ++i) + if (1 < (int)magnitudes[i]) + return -1; + for (int i = 0; i < count; ++i) + code[(int)locations[i] / 8] ^= (int)magnitudes[i] << (7 - (int)locations[i] % 8); + int corrections_count = 0; + for (int i = 0; i < count; ++i) + corrections_count += !!magnitudes[i]; + return corrections_count; + } +}; + +template +class BoseChaudhuriHocquenghemDecoderReference +{ public: typedef typename GF::value_type value_type; typedef typename GF::ValueType ValueType; @@ -62,52 +119,6 @@ public: corrections_count += !!magnitudes[i]; return corrections_count; } - int compute_syndromes(uint8_t *code, ValueType *syndromes) - { - // $syndromes_i = code(pe^{FCR+i})$ - for (int i = 0; i < NR; ++i) - syndromes[i] = ValueType((code[0] >> 7) & 1); - for (int j = 1; j < N; ++j) { - IndexType root(FCR), pe(1); - for (int i = 0; i < NR; ++i) { - syndromes[i] = fma(root, syndromes[i], ValueType((code[j / 8] >> (7 - j % 8)) & 1)); - root *= pe; - } - } - int nonzero = 0; - for (int i = 0; i < NR; ++i) - nonzero += !!syndromes[i]; - return nonzero; - } - int compute_syndromes(uint8_t *code, value_type *syndromes) - { - return compute_syndromes(code, reinterpret_cast(syndromes)); - } - int operator()(uint8_t *code, value_type *erasures = 0, int erasures_count = 0) - { - assert(0 <= erasures_count && erasures_count <= NR); - if (0) { - for (int i = 0; i < erasures_count; ++i) - code[erasures[i] / 8] &= ~(128 >> (erasures[i] % 8)); - } - ValueType syndromes[NR]; - if (!compute_syndromes(code, syndromes)) - return 0; - IndexType locations[NR]; - ValueType magnitudes[NR]; - int count = algorithm(syndromes, locations, magnitudes, reinterpret_cast(erasures), erasures_count); - if (count <= 0) - return count; - for (int i = 0; i < count; ++i) - if (1 < (int)magnitudes[i]) - return -1; - for (int i = 0; i < count; ++i) - code[(int)locations[i] / 8] ^= (int)magnitudes[i] << (7 - (int)locations[i] % 8); - int corrections_count = 0; - for (int i = 0; i < count; ++i) - corrections_count += !!magnitudes[i]; - return corrections_count; - } }; } diff --git a/tests/bch_decoder_test.cc b/tests/bch_decoder_test.cc index 5f7aac6..2404870 100644 --- a/tests/bch_decoder_test.cc +++ b/tests/bch_decoder_test.cc @@ -67,6 +67,51 @@ int main() delete decode; delete instance; } + if (0) { + // NASA INTRO BCH(15, 5) T=3 + typedef CODE::GaloisField<4, 0b10011, uint8_t> GF; + typedef CODE::BoseChaudhuriHocquenghemDecoderReference<6, 1, 5, GF> BCH; + GF instance; + BCH decode; + uint8_t target[BCH::N] = { 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0 }; + uint8_t code[BCH::N]; + for (int i = 0; i < BCH::N; ++i) + code[i] = target[i]; + std::uniform_int_distribution distribution(0, BCH::N-1); + auto noise = std::bind(distribution, generator); + for (int i = 0; i < 3; ++i) + code[noise()] ^= 1; + decode(reinterpret_cast(code)); + for (int i = 0; i < BCH::N; ++i) + assert(code[i] == target[i]); + } + if (0) { + // DVB-S2 FULL BCH(65535, 65343) T=12 + typedef CODE::GaloisField<16, 0b10000000000101101, uint16_t> GF; + typedef CODE::BoseChaudhuriHocquenghemDecoderReference<24, 1, 65343, GF> BCH; + GF *instance = new GF(); + BCH *decode = new BCH(); + uint16_t *target = new uint16_t[BCH::N]; + for (int i = 0, s = 0; i < BCH::K; ++i, s=(s*(s*s*51767+71287)+35149)&0xffffff) + target[i] = (s^=s>>7)&1; + uint16_t parity[BCH::NP] = { 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0 }; + for (int i = 0; i < BCH::NP; ++i) + target[BCH::K+i] = parity[i]; + uint16_t *code = new uint16_t[BCH::N]; + for (int i = 0; i < BCH::N; ++i) + code[i] = target[i]; + std::uniform_int_distribution distribution(0, BCH::N-1); + auto noise = std::bind(distribution, generator); + for (int i = 0; i < 12; ++i) + code[noise()] ^= 1; + (*decode)(reinterpret_cast(code)); + for (int i = 0; i < BCH::N; ++i) + assert(code[i] == target[i]); + delete[] target; + delete[] code; + delete decode; + delete instance; + } std::cerr << "Bose Chaudhuri Hocquenghem Decoder test passed!" << std::endl; return 0; }