def findErrors(self, forney_syndromes: Polynomial, length_message: int) -> list: """ Berlekamp-Massey + Chien search to find the 0s of the error locator polynomial :param forney_syndromes: the polynomial representation of the Forney syndromes :param length_message: the length of the message + parity bits :return: the error locator polynomial """ error_loc_polynomial = Polynomial([1]) last_known = Polynomial([1]) # generate the error locator polynomial # - Berklekamp-Massey algorithm for i in range(0, len(forney_syndromes)): # d = S[k] + C[1]*S[k-1] + C[2]*S[k-2] + ... + C[l]*S[k-L] # This is the discrepancy delta delta = forney_syndromes[i] for j in range(1, len(error_loc_polynomial)): delta ^= self.GF.gfMul(error_loc_polynomial[-(j + 1)], forney_syndromes[i - j]) # Calculate the next degree of the polynomial last_known.append(0) # If delta is not 0, correct for it if delta != 0: if len(last_known) > len(error_loc_polynomial): new_polynomial = last_known.scale(delta) last_known = error_loc_polynomial.scale( self.GF.gfInv(delta)) error_loc_polynomial = new_polynomial error_loc_polynomial += last_known.scale(delta) error_loc_polynomial = error_loc_polynomial[::-1] # Stop if too many errors error_count = len(error_loc_polynomial) - 1 if error_count * 2 > len(forney_syndromes): raise ReedSolomonError("Too many errors to correct") # Find the zeros of the polynomial using Chien search error_list = [] for i in range(self.GF.lowSize): error_z = error_loc_polynomial.eval(self.GF.gfPow(2, i)) if error_z == 0: error_list.append(length_message - i - 1) # Sanity checking if len(error_list) != error_count: raise ReedSolomonError("Too many errors to correct") else: return error_list
def correct(self, message, syndrome_polynomial: Polynomial, errors: list) -> Polynomial: """ Using the calculated erasures and errors, recover the original message :param message: the transmitted message + parity bits :param syndrome_polynomial: the syndrome polynomial :param errors: a list of erasures + errors :return: the decoded and corrected message """ # Calculate error locator polynomial for both erasures and errors coefficient_pos = [len(message) - 1 - p for p in errors] error_locator = Polynomial.errorLocatorPolynomial(coefficient_pos) # Calculate the error evaluator polynomial error_eval = Polynomial.errorEvaluatorPolynomial( syndrome_polynomial[::-1], error_locator, len(error_locator)) # Calculate the error positions polynomial error_positions = [] for i in range(len(coefficient_pos)): x = self.GF.lowSize - coefficient_pos[i] error_positions.append(self.GF.gfPow(2, -x)) # This is the Forney algorithm error_magnitudes = Polynomial([0] * len(message)) for i, error in enumerate(error_positions): error_inv = self.GF.gfInv(error) # Formal derivative of the error locator polynomial error_loc_derivative_tmp = Polynomial([]) for j in range(len(error_positions)): if j != i: error_loc_derivative_tmp.append( 1 ^ self.GF.gfMul(error_inv, error_positions[j])) # Error locator derivative error_loc_derivative = 1 for coef in error_loc_derivative_tmp: error_loc_derivative = self.GF.gfMul(error_loc_derivative, coef) # Evaluate the error evaluation polynomial according to the inverse of the error y = error_eval.eval(error_inv) # Compute the magnitude of error magnitude = self.GF.gfDiv(y, error_loc_derivative) error_magnitudes[errors[i]] = magnitude # Correct the message using the error magnitudes message_polynomial = Polynomial(message) message_polynomial += error_magnitudes return message_polynomial
def findErrors(self, forney_syndromes: Polynomial, length_message: int) -> list: """ BM算法和Chien钱搜索找到0的错误定位多项式 :param forney_syndromes: 表示forney伴随式的多项式 :param length_message: 信息长度和校验位长度之和 :return: 错误定位多项式 """ error_loc_polynomial = Polynomial([1]) last_known = Polynomial([1]) # 生成错误定位多项式 # BM算法 for i in range(0, len(forney_syndromes)): # d = S[k] + C[1]*S[k-1] + C[2]*S[k-2] + ... + C[l]*S[k-L] # 偏差delta delta = forney_syndromes[i] for j in range(1, len(error_loc_polynomial)): delta ^= self.GF.gfMul(error_loc_polynomial[-(j+1)], forney_syndromes[i - j]) # 计算多项式次幂 last_known.append(0) # 如果偏差delta不为0 改正 if delta != 0: if len(last_known) > len(error_loc_polynomial): new_polynomial = last_known.scale(delta) last_known = error_loc_polynomial.scale(self.GF.gfInv(delta)) error_loc_polynomial = new_polynomial error_loc_polynomial += last_known.scale(delta) error_loc_polynomial = error_loc_polynomial[::-1] # 如果错误太多 停止 error_count = len(error_loc_polynomial) - 1 if error_count * 2 > len(forney_syndromes): raise ReedSolomonError("Too many errors to correct") # 用钱(Chien)搜索找到多项式的零点 error_list = [] for i in range(self.GF.lowSize): error_z = error_loc_polynomial.eval(self.GF.gfPow(2, i)) if error_z == 0: error_list.append(length_message - i - 1) # 完整性检查 if len(error_list) != error_count: raise ReedSolomonError("Too many errors to correct") else: return error_list
def correct(self, message, syndrome_polynomial: Polynomial, errors: list) -> Polynomial: """ 使用计算过的擦除和错误,恢复原始信息 :param message: 传输的信息+校验位 :param syndrome_polynomial: 伴随多项式 :param errors: 一个擦除+错误的列表 :return:解码并改正的信息 """ # 为擦除和错误计算错误定位多项式 coefficient_pos = [len(message) - 1 - p for p in errors] error_locator = Polynomial.errorLocatorPolynomial(coefficient_pos) # 计算误差评估多项式 error_eval = Polynomial.errorEvaluatorPolynomial(syndrome_polynomial[::-1], error_locator, len(error_locator)) # 计算误差位置多项式 error_positions = [] for i in range(len(coefficient_pos)): x = self.GF.lowSize - coefficient_pos[i] error_positions.append(self.GF.gfPow(2, -x)) # 这是福尼算法 error_magnitudes = Polynomial([0] * len(message)) for i, error in enumerate(error_positions): error_inv = self.GF.gfInv(error) # 错误定位多项式的形式导数(Formal derivative of the error locator polynomial) error_loc_derivative_tmp = Polynomial([]) for j in range(len(error_positions)): if j != i: error_loc_derivative_tmp.append(1 ^ self.GF.gfMul(error_inv, error_positions[j])) # 错误定位导数 Error locator derivative error_loc_derivative = 1 for coef in error_loc_derivative_tmp: error_loc_derivative = self.GF.gfMul(error_loc_derivative, coef) # 根据误差的倒数求出误差评价多项式 y = error_eval.eval(error_inv) # 计算误差的大小 magnitude = self.GF.gfDiv(y, error_loc_derivative) error_magnitudes[errors[i]] = magnitude # 使用错误大小纠正消息 message_polynomial = Polynomial(message) message_polynomial += error_magnitudes return message_polynomial