File indexing completed on 2024-05-12 04:01:32

0001 /*
0002     SPDX-FileCopyrightText: 2017 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #include "bitvector_p.h"
0008 #include "reedsolomon_p.h"
0009 
0010 
0011 #include <memory>
0012 
0013 using namespace Prison;
0014 
0015 // See https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders
0016 
0017 static int highestBit(int n)
0018 {
0019     int i = 0;
0020     while (n >= (1 << i)) {
0021         ++i;
0022     }
0023     return i - 1;
0024 }
0025 
0026 ReedSolomon::ReedSolomon(int polynom, int symbolCount)
0027     : m_symCount(symbolCount)
0028 {
0029     m_symSize = highestBit(polynom);
0030 
0031     // calculate the log/alog tables
0032     const auto logmod = (1 << m_symSize) - 1;
0033     m_logTable.reset(new int[logmod + 1]);
0034     m_antiLogTable.reset(new int[logmod]);
0035 
0036     for (int p = 1, v = 0; v < logmod; v++) {
0037         m_antiLogTable[v] = p;
0038         m_logTable[p] = v;
0039         p <<= 1;
0040         if (p & (1 << m_symSize)) {
0041             p ^= polynom;
0042         }
0043     }
0044 
0045     // compute the encoding polynom
0046     m_polynom.reset(new int[m_symCount + 1]);
0047     m_polynom[0] = 1;
0048     for (int i = 1; i <= m_symCount; ++i) {
0049         m_polynom[i] = 1;
0050         for (int k = i - 1; k > 0; --k) {
0051             if (m_polynom[k]) {
0052                 m_polynom[k] = m_antiLogTable[(m_logTable[m_polynom[k]] + i) % logmod];
0053             }
0054             m_polynom[k] ^= m_polynom[k - 1];
0055         }
0056         m_polynom[0] = m_antiLogTable[(m_logTable[m_polynom[0]] + i) % logmod];
0057     }
0058 }
0059 
0060 ReedSolomon::~ReedSolomon() = default;
0061 
0062 BitVector ReedSolomon::encode(const BitVector &input) const
0063 {
0064     std::unique_ptr<int[]> result(new int[m_symCount]);
0065     for (int i = 0; i < m_symCount; ++i) {
0066         result[i] = 0;
0067     }
0068 
0069     const auto logmod = (1 << m_symSize) - 1;
0070     for (int i = 0; i < input.size() / m_symSize; i++) {
0071         auto m = result[m_symCount - 1] ^ input.valueAtMSB(i * m_symSize, m_symSize);
0072         for (int k = m_symCount - 1; k > 0; --k) {
0073             if (m && m_polynom[k]) {
0074                 result[k] = result[k - 1] ^ m_antiLogTable[(m_logTable[m] + m_logTable[m_polynom[k]]) % logmod];
0075             } else {
0076                 result[k] = result[k - 1];
0077             }
0078         }
0079         if (m && m_polynom[0]) {
0080             result[0] = m_antiLogTable[(m_logTable[m] + m_logTable[m_polynom[0]]) % logmod];
0081         } else {
0082             result[0] = 0;
0083         }
0084     }
0085 
0086     BitVector v;
0087     for (int i = m_symCount - 1; i >= 0; --i) {
0088         v.appendMSB(result[i], m_symSize);
0089     }
0090     return v;
0091 }