Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
    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