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 }