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 }); }
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); }
internal GF256Poly multiply(GF256Poly other) { if (!field.Equals(other.field)) { throw new System.ArgumentException("GF256Polys do not have same GF256 field"); } if (Zero || other.Zero) { return(field.Zero); } int[] aCoefficients = this.coefficients; int aLength = aCoefficients.Length; int[] bCoefficients = other.coefficients; int bLength = bCoefficients.Length; int[] product = new int[aLength + bLength - 1]; for (int i = 0; i < aLength; i++) { int aCoeff = aCoefficients[i]; for (int j = 0; j < bLength; j++) { product[i + j] = GF256.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j])); } } return(new GF256Poly(field, product)); }
private GF256Poly buildGenerator(int degree) { if (degree >= cachedGenerators.Count) { GF256Poly lastGenerator = (GF256Poly)cachedGenerators[cachedGenerators.Count - 1]; for (int d = cachedGenerators.Count; d <= degree; d++) { GF256Poly nextGenerator = lastGenerator.multiply(new GF256Poly(field, new int[] { 1, field.exp(d - 1) })); cachedGenerators.Add(nextGenerator); lastGenerator = nextGenerator; } } return((GF256Poly)cachedGenerators[degree]); }
/// <summary> Create a representation of GF(256) using the given primitive polynomial. /// /// </summary> /// <param name="primitive">irreducible polynomial whose coefficients are represented by /// the bits of an int, where the least-significant bit represents the constant /// coefficient /// </param> private GF256(int primitive) { expTable = new int[256]; logTable = new int[256]; int x = 1; for (int i = 0; i < 256; i++) { expTable[i] = x; x <<= 1; // x = x * 2; we're assuming the generator alpha is 2 if (x >= 0x100) { x ^= primitive; } } for (int i = 0; i < 255; i++) { logTable[expTable[i]] = i; } // logTable[0] == 0 but this should never be used zero = new GF256Poly(this, new int[]{0}); one = new GF256Poly(this, new int[]{1}); }
/// <summary> Create a representation of GF(256) using the given primitive polynomial. /// /// </summary> /// <param name="primitive">irreducible polynomial whose coefficients are represented by /// the bits of an int, where the least-significant bit represents the constant /// coefficient /// </param> private GF256(int primitive) { expTable = new int[256]; logTable = new int[256]; int x = 1; for (int i = 0; i < 256; i++) { expTable[i] = x; x <<= 1; // x = x * 2; we're assuming the generator alpha is 2 if (x >= 0x100) { x ^= primitive; } } for (int i = 0; i < 255; i++) { logTable[expTable[i]] = i; } // logTable[0] == 0 but this should never be used zero = new GF256Poly(this, new int[] { 0 }); one = new GF256Poly(this, new int[] { 1 }); }
internal GF256Poly addOrSubtract(GF256Poly other) { if (!field.Equals(other.field)) { throw new System.ArgumentException("GF256Polys do not have same GF256 field"); } if (Zero) { return(other); } if (other.Zero) { return(this); } int[] smallerCoefficients = this.coefficients; int[] largerCoefficients = other.coefficients; if (smallerCoefficients.Length > largerCoefficients.Length) { int[] temp = smallerCoefficients; smallerCoefficients = largerCoefficients; largerCoefficients = temp; } int[] sumDiff = new int[largerCoefficients.Length]; int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length; // Copy high-order terms only found in higher-degree polynomial's coefficients Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff); for (int i = lengthDiff; i < largerCoefficients.Length; i++) { sumDiff[i] = GF256.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); } return(new GF256Poly(field, sumDiff)); }
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}; }
internal GF256Poly multiply(GF256Poly other) { if (!field.Equals(other.field)) { throw new System.ArgumentException("GF256Polys do not have same GF256 field"); } if (Zero || other.Zero) { return field.Zero; } int[] aCoefficients = this.coefficients; int aLength = aCoefficients.Length; int[] bCoefficients = other.coefficients; int bLength = bCoefficients.Length; int[] product = new int[aLength + bLength - 1]; for (int i = 0; i < aLength; i++) { int aCoeff = aCoefficients[i]; for (int j = 0; j < bLength; j++) { product[i + j] = GF256.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j])); } } return new GF256Poly(field, product); }
internal GF256Poly addOrSubtract(GF256Poly other) { if (!field.Equals(other.field)) { throw new System.ArgumentException("GF256Polys do not have same GF256 field"); } if (Zero) { return other; } if (other.Zero) { return this; } int[] smallerCoefficients = this.coefficients; int[] largerCoefficients = other.coefficients; if (smallerCoefficients.Length > largerCoefficients.Length) { int[] temp = smallerCoefficients; smallerCoefficients = largerCoefficients; largerCoefficients = temp; } int[] sumDiff = new int[largerCoefficients.Length]; int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length; // Copy high-order terms only found in higher-degree polynomial's coefficients Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff); for (int i = lengthDiff; i < largerCoefficients.Length; i++) { sumDiff[i] = GF256.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); } return new GF256Poly(field, sumDiff); }