public void encode(int[] toEncode, int ecBytes) { if (ecBytes == 0) { throw new System.ArgumentException("No error correction bytes"); } int dataBytes = toEncode.Length - ecBytes; if (dataBytes <= 0) { throw new System.ArgumentException("No data bytes provided"); } GF256Poly generator = buildGenerator(ecBytes); int[] infoCoefficients = new int[dataBytes]; Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes); GF256Poly info = new GF256Poly(field, infoCoefficients); info = info.multiplyByMonomial(ecBytes, 1); GF256Poly remainder = info.divide(generator)[1]; int[] coefficients = remainder.Coefficients; int numZeroCoefficients = ecBytes - coefficients.Length; for (int i = 0; i < numZeroCoefficients; i++) { toEncode[dataBytes + i] = 0; } Array.Copy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.Length); }
public GF256Poly[] divide(GF256Poly other) { if (!field.Equals(other.field)) { throw new ArgumentException("GF256Polys do not have same GF256 field"); } if (other.isZero()) { throw new ArgumentException("Divide by 0"); } GF256Poly quotient = field.getZero(); GF256Poly remainder = this; int denominatorLeadingTerm = other.getCoefficient(other.getDegree()); int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) { int degreeDifference = remainder.getDegree() - other.getDegree(); int scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm); GF256Poly term = other.multiplyByMonomial(degreeDifference, scale); GF256Poly iterationQuotient = field.buildMonomial(degreeDifference, scale); quotient = quotient.addOrSubtract(iterationQuotient); remainder = remainder.addOrSubtract(term); } return(new GF256Poly[] { quotient, remainder }); }
internal void encode(int[] toEncode, int ecBytes) { if (ecBytes == 0) { throw new System.ArgumentException("No error correction bytes"); } int dataBytes = toEncode.Length - ecBytes; if (dataBytes <= 0) { throw new System.ArgumentException("No data bytes provided"); } GF256Poly generator = buildGenerator(ecBytes); int[] infoCoefficients = new int[dataBytes]; Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes); GF256Poly info = new GF256Poly(field, infoCoefficients); info = info.multiplyByMonomial(ecBytes, 1); GF256Poly remainder = info.divide(generator)[1]; int[] coefficients = remainder.Coefficients; int numZeroCoefficients = ecBytes - coefficients.Length; for (int i = 0; i < numZeroCoefficients; i++) { toEncode[dataBytes + i] = 0; } Array.Copy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.Length); }
internal GF256Poly[] divide(GF256Poly other) { if (!field.Equals(other.field)) { throw new System.ArgumentException("GF256Polys do not have same GF256 field"); } if (other.Zero) { throw new System.ArgumentException("Divide by 0"); } GF256Poly quotient = field.Zero; GF256Poly remainder = this; int denominatorLeadingTerm = other.getCoefficient(other.Degree); int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); while (remainder.Degree >= other.Degree && !remainder.Zero) { int degreeDifference = remainder.Degree - other.Degree; int scale = field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm); GF256Poly term = other.multiplyByMonomial(degreeDifference, scale); GF256Poly iterationQuotient = field.buildMonomial(degreeDifference, scale); quotient = quotient.addOrSubtract(iterationQuotient); remainder = remainder.addOrSubtract(term); } return new GF256Poly[]{quotient, remainder}; }
private GF256Poly[] runEuclideanAlgorithm(GF256Poly a, GF256Poly b, int R) { // Assume a's degree is >= b's if (a.Degree < b.Degree) { GF256Poly temp = a; a = b; b = temp; } GF256Poly rLast = a; GF256Poly r = b; GF256Poly sLast = field.One; GF256Poly s = field.Zero; GF256Poly tLast = field.Zero; GF256Poly t = field.One; // Run Euclidean algorithm until r's degree is less than R/2 while (r.Degree >= R / 2) { GF256Poly rLastLast = rLast; GF256Poly sLastLast = sLast; GF256Poly tLastLast = tLast; rLast = r; sLast = s; tLast = t; // Divide rLastLast by rLast, with quotient in q and remainder in r if (rLast.Zero) { // Oops, Euclidean algorithm already terminated? throw new ReedSolomonException("r_{i-1} was zero"); } r = rLastLast; GF256Poly q = field.Zero; int denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree); int dltInverse = field.inverse(denominatorLeadingTerm); while (r.Degree >= rLast.Degree && !r.Zero) { 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)); } s = q.multiply(sLast).addOrSubtract(sLastLast); t = q.multiply(tLast).addOrSubtract(tLastLast); } int sigmaTildeAtZero = t.getCoefficient(0); if (sigmaTildeAtZero == 0) { throw new ReedSolomonException("sigmaTilde(0) was zero"); } int inverse = field.inverse(sigmaTildeAtZero); GF256Poly sigma = t.multiply(inverse); GF256Poly omega = r.multiply(inverse); return(new GF256Poly[] { sigma, omega }); }