/// <summary> /// Runs the euclidean algorithm (Greatest Common Divisor) until r's degree is less than R/2 /// </summary> /// <returns>The euclidean algorithm.</returns> private ModulusPoly[] RunEuclideanAlgorithm(ModulusPoly a, ModulusPoly b, int R) { // Assume a's degree is >= b's if (a.Degree < b.Degree) { ModulusPoly temp = a; a = b; b = temp; } ModulusPoly rLast = a; ModulusPoly r = b; ModulusPoly tLast = field.Zero; ModulusPoly t = field.One; // Run Euclidean algorithm until r's degree is less than R/2 while (r.Degree >= R / 2) { ModulusPoly rLastLast = rLast; ModulusPoly tLastLast = tLast; rLast = r; tLast = t; // Divide rLastLast by rLast, with quotient in q and remainder in r if (rLast.IsZero) { // Oops, Euclidean algorithm already terminated? return(null); } r = rLastLast; ModulusPoly q = field.Zero; int denominatorLeadingTerm = rLast.GetCoefficient(rLast.Degree); int dltInverse = field.Inverse(denominatorLeadingTerm); while (r.Degree >= rLast.Degree && !r.IsZero) { int degreeDiff = r.Degree - rLast.Degree; int scale = field.Multiply(r.GetCoefficient(r.Degree), dltInverse); q = q.Add(field.BuildMonomial(degreeDiff, scale)); r = r.Subtract(rLast.MultiplyByMonomial(degreeDiff, scale)); } t = q.Multiply(tLast).Subtract(tLastLast).GetNegative(); } int sigmaTildeAtZero = t.GetCoefficient(0); if (sigmaTildeAtZero == 0) { return(null); } int inverse = field.Inverse(sigmaTildeAtZero); ModulusPoly sigma = t.Multiply(inverse); ModulusPoly omega = r.Multiply(inverse); return(new ModulusPoly[] { sigma, omega }); }
/// <summary> /// Decodes the specified received. /// </summary> /// <param name="received">The received.</param> /// <param name="numECCodewords">The num EC codewords.</param> /// <param name="erasures">The erasures.</param> /// <returns></returns> public int Decode(int[] received, int numECCodewords, int[] erasures) { ModulusPoly poly = new ModulusPoly(field, received); int[] S = new int[numECCodewords]; bool error = false; for (int i = numECCodewords; i > 0; i--) { int eval = poly.EvaluateAt(field.Exp(i)); S[numECCodewords - i] = eval; if (eval != 0) { error = true; } } if (!error) { return(0); } ModulusPoly knownErrors = field.One; foreach (int erasure in erasures) { int b = field.Exp(received.Length - 1 - erasure); // Add (1 - bx) term: ModulusPoly term = new ModulusPoly(field, new int[] { field.Subtract(0, b), 1 }); knownErrors = knownErrors.Multiply(term); } ModulusPoly syndrome = new ModulusPoly(field, S); //syndrome = syndrome.multiply(knownErrors); ModulusPoly[] sigmaOmega = RunEuclideanAlgorithm(field.BuildMonomial(numECCodewords, 1), syndrome, numECCodewords); if (sigmaOmega == null) { throw ReaderException.Instance; } ModulusPoly sigma = sigmaOmega[0]; ModulusPoly omega = sigmaOmega[1]; if (sigma == null || omega == null) { throw ReaderException.Instance; } //sigma = sigma.multiply(knownErrors); int[] errorLocations = FindErrorLocations(sigma); if (errorLocations == null) { throw ReaderException.Instance; } int[] errorMagnitudes = FindErrorMagnitudes(omega, sigma, errorLocations); for (int i = 0; i < errorLocations.Length; i++) { int position = received.Length - 1 - field.Log(errorLocations[i]); if (position < 0) { throw ReaderException.Instance; // return -3; // don't throw } received[position] = field.Subtract(received[position], errorMagnitudes[i]); } return(errorLocations.Length); }