public void Encode(int[] toEncode, int ecBytes) { if (ecBytes == 0) { throw new ArgumentException("No error correction bytes"); } int dataBytes = toEncode.Length - ecBytes; if (dataBytes <= 0) { throw new ArgumentException("No data bytes provided"); } GenericGFPoly generator = BuildGenerator(ecBytes); var infoCoefficients = new int[dataBytes]; Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes); var info = new GenericGFPoly(field, infoCoefficients); info = info.MultiplyByMonomial(ecBytes, 1); GenericGFPoly remainder = info.Divide(generator)[1]; int[] coefficients = remainder.Coefficients; int numZeroCoefficients = ecBytes - coefficients.Length; for (var i = 0; i < numZeroCoefficients; i++) { toEncode[dataBytes + i] = 0; } Array.Copy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.Length); }
// this method has been added by Sebastien ROBERT // this implementation makes the mathematician-friendly approach programmer-friendly public byte[] EncodeEx(byte[] toEncode, int ecBytes) { if (ecBytes == 0) { throw new ArgumentException("No error correction bytes"); } int dataBytes = toEncode.Length - ecBytes; if (dataBytes <= 0) { throw new ArgumentException("No data bytes provided"); } GenericGFPoly generator = BuildGenerator(ecBytes); int[] infoCoefficients = toEncode.Select(x => (int)x).ToArray(); var info = new GenericGFPoly(field, infoCoefficients); info = info.MultiplyByMonomial(ecBytes, 1); GenericGFPoly remainder = info.Divide(generator)[1]; int[] coefficients = remainder.Coefficients; int numZeroCoefficients = ecBytes - coefficients.Length; return(Enumerable.Repeat <byte>(0, numZeroCoefficients) .Concat(coefficients.Select(x => (byte)x)) .ToArray()); }
internal GenericGFPoly[] Divide(GenericGFPoly other) { if (field.Equals(other.field) == false) { throw new ArgumentException("GenericGFPolys do not have same GenericGF field"); } if (other.IsZero) { throw new ArgumentException("Divide by 0"); } GenericGFPoly quotient = field.Zero; GenericGFPoly remainder = this; int denominatorLeadingTerm = other.GetCoefficient(other.Degree); int inverseDenominatorLeadingTerm = field.Inverse(denominatorLeadingTerm); while (remainder.Degree >= other.Degree && !remainder.IsZero) { int degreeDifference = remainder.Degree - other.Degree; int scale = field.Multiply(remainder.GetCoefficient(remainder.Degree), inverseDenominatorLeadingTerm); GenericGFPoly term = other.MultiplyByMonomial(degreeDifference, scale); GenericGFPoly iterationQuotient = field.BuildMonomial(degreeDifference, scale); quotient = quotient.AddOrSubtract(iterationQuotient); remainder = remainder.AddOrSubtract(term); } return(new GenericGFPoly[] { quotient, remainder }); }
internal GenericGFPoly[] RunEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R) { // Assume a's degree is >= b's if (a.Degree < b.Degree) { GenericGFPoly temp = a; a = b; b = temp; } GenericGFPoly rLast = a; GenericGFPoly r = b; GenericGFPoly tLast = field.Zero; GenericGFPoly t = field.One; int halfR = R / 2; // Run Euclidean algorithm until r's degree is less than R/2 while (r.Degree >= halfR) { GenericGFPoly rLastLast = rLast; GenericGFPoly 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? // throw new ReedSolomonException("r_{i-1} was zero"); return(null); } r = rLastLast; GenericGFPoly 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.AddOrSubtract(field.BuildMonomial(degreeDiff, scale)); r = r.AddOrSubtract(rLast.MultiplyByMonomial(degreeDiff, scale)); } t = q.Multiply(tLast).AddOrSubtract(tLastLast); if (r.Degree >= rLast.Degree) { // throw new IllegalStateException("Division algorithm failed to reduce polynomial?"); return(null); } } int sigmaTildeAtZero = t.GetCoefficient(0); if (sigmaTildeAtZero == 0) { // throw new ReedSolomonException("sigmaTilde(0) was zero"); return(null); } int inverse = field.Inverse(sigmaTildeAtZero); GenericGFPoly sigma = t.Multiply(inverse); GenericGFPoly omega = r.Multiply(inverse); return(new GenericGFPoly[] { sigma, omega }); }