/* SPDX-FileCopyrightText: 2017 Volker Krause SPDX-License-Identifier: MIT */ #include "bitvector_p.h" #include "reedsolomon_p.h" #include using namespace Prison; // See https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders static int highestBit(int n) { int i = 0; while (n >= (1 << i)) { ++i; } return i - 1; } ReedSolomon::ReedSolomon(int polynom, int symbolCount) : m_symCount(symbolCount) { m_symSize = highestBit(polynom); // calculate the log/alog tables const auto logmod = (1 << m_symSize) - 1; m_logTable.reset(new int[logmod + 1]); m_antiLogTable.reset(new int[logmod]); for (int p = 1, v = 0; v < logmod; v++) { m_antiLogTable[v] = p; m_logTable[p] = v; p <<= 1; if (p & (1 << m_symSize)) { p ^= polynom; } } // compute the encoding polynom m_polynom.reset(new int[m_symCount + 1]); m_polynom[0] = 1; for (int i = 1; i <= m_symCount; ++i) { m_polynom[i] = 1; for (int k = i - 1; k > 0; --k) { if (m_polynom[k]) { m_polynom[k] = m_antiLogTable[(m_logTable[m_polynom[k]] + i) % logmod]; } m_polynom[k] ^= m_polynom[k - 1]; } m_polynom[0] = m_antiLogTable[(m_logTable[m_polynom[0]] + i) % logmod]; } } ReedSolomon::~ReedSolomon() = default; BitVector ReedSolomon::encode(const BitVector &input) const { std::unique_ptr result(new int[m_symCount]); for (int i = 0; i < m_symCount; ++i) { result[i] = 0; } const auto logmod = (1 << m_symSize) - 1; for (int i = 0; i < input.size() / m_symSize; i++) { auto m = result[m_symCount - 1] ^ input.valueAtMSB(i * m_symSize, m_symSize); for (int k = m_symCount - 1; k > 0; --k) { if (m && m_polynom[k]) { result[k] = result[k - 1] ^ m_antiLogTable[(m_logTable[m] + m_logTable[m_polynom[k]]) % logmod]; } else { result[k] = result[k - 1]; } } if (m && m_polynom[0]) { result[0] = m_antiLogTable[(m_logTable[m] + m_logTable[m_polynom[0]]) % logmod]; } else { result[0] = 0; } } BitVector v; for (int i = m_symCount - 1; i >= 0; --i) { v.appendMSB(result[i], m_symSize); } return v; }