private int[] FindErrorLocations(GenericGFPoly errorLocator) { // This is a direct application of Chien's search int numErrors = errorLocator.Degree; if (numErrors == 1) { // shortcut return(new int[] { errorLocator.GetCoefficient(1) }); } int[] result = new int[numErrors]; int e = 0; for (int i = 1; i < field.Size && e < numErrors; i++) { if (errorLocator.EvaluateAt(i) == 0) { result[e] = field.Inverse(i); e++; } } if (e != numErrors) { // throw new ReedSolomonException("Error locator degree does not match number of roots"); return(null); } return(result); }
/// <summary> /// <p>Decodes given set of received codewords, which include both data and error-correction /// codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, /// in the input.</p> /// </summary> /// <param name="received">data and error-correction codewords</param> /// <param name="twoS">number of error-correction codewords available</param> /// <returns>false: decoding fails</returns> public bool Decode(int[] received, int twoS) { var poly = new GenericGFPoly(field, received); var syndromeCoefficients = new int[twoS]; var noError = true; for (var i = 0; i < twoS; i++) { int eval = poly.EvaluateAt(field.Exp(i + field.GeneratorBase)); syndromeCoefficients[syndromeCoefficients.Length - 1 - i] = eval; if (eval != 0) { noError = false; } } if (noError) { return(true); } var syndrome = new GenericGFPoly(field, syndromeCoefficients); GenericGFPoly[] sigmaOmega = RunEuclideanAlgorithm(field.BuildMonomial(twoS, 1), syndrome, twoS); if (sigmaOmega == null) { return(false); } GenericGFPoly sigma = sigmaOmega[0]; int[] errorLocations = FindErrorLocations(sigma); if (errorLocations == null) { return(false); } GenericGFPoly omega = sigmaOmega[1]; int[] errorMagnitudes = FindErrorMagnitudes(omega, errorLocations); for (int i = 0; i < errorLocations.Length; i++) { int position = received.Length - 1 - field.Log(errorLocations[i]); if (position < 0) { // throw new ReedSolomonException("Bad error location"); return(false); } received[position] = GenericGF.AddOrSubtract(received[position], errorMagnitudes[i]); } return(true); }
private int[] FindErrorMagnitudes(GenericGFPoly errorEvaluator, int[] errorLocations) { // This is directly applying Forney's Formula int s = errorLocations.Length; int[] result = new int[s]; for (int i = 0; i < s; i++) { int xiInverse = field.Inverse(errorLocations[i]); int denominator = 1; for (int j = 0; j < s; j++) { if (i != j) { //denominator = field.multiply(denominator, // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug. // Below is a funny-looking workaround from Steven Parkes int term = field.Multiply(errorLocations[j], xiInverse); int termPlus1 = (term & 0x1) == 0 ? term | 1 : term & ~1; denominator = field.Multiply(denominator, termPlus1); // removed in java version, not sure if this is right // denominator = field.multiply(denominator, GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); } } result[i] = field.Multiply(errorEvaluator.EvaluateAt(xiInverse), field.Inverse(denominator)); if (field.GeneratorBase != 0) { result[i] = field.Multiply(result[i], xiInverse); } } return(result); }