/// <summary> /// Calculates the multiplicative inverse of <c>this</c> and returns the result in a new GF2nPolynomialElement /// </summary> /// /// <returns>Returns <c>this</c>^(-1)</returns> public GF2nPolynomialElement InvertEEA() { if (IsZero()) throw new ArithmeticException(); GF2Polynomial b = new GF2Polynomial(mDegree + 32, "ONE"); b.ReduceN(); GF2Polynomial c = new GF2Polynomial(mDegree + 32); c.ReduceN(); GF2Polynomial u = GetGF2Polynomial(); GF2Polynomial v = mField.FieldPolynomial; GF2Polynomial h; int j; u.ReduceN(); while (!u.IsOne()) { u.ReduceN(); v.ReduceN(); j = u.Length - v.Length; if (j < 0) { h = u; u = v; v = h; h = b; b = c; c = h; j = -j; c.ReduceN(); // this increases the performance } u.ShiftLeftAddThis(v, j); b.ShiftLeftAddThis(c, j); } b.ReduceN(); return new GF2nPolynomialElement((GF2nPolynomialField)mField, b); }
/// <summary> /// Returns the remainder of <c>this</c> divided by <c>G</c> in a new GF2Polynomial /// </summary> /// /// <param name="G">A GF2Polynomial != 0</param> /// /// <returns>Returns a new GF2Polynomial (<c>this</c> % <c>G</c>)</returns> public GF2Polynomial Remainder(GF2Polynomial G) { // a div b = q / r GF2Polynomial a = new GF2Polynomial(this); GF2Polynomial b = new GF2Polynomial(G); GF2Polynomial j; int i; if (b.IsZero()) throw new Exception(); a.ReduceN(); b.ReduceN(); if (a._length < b._length) return a; i = a._length - b._length; while (i >= 0) { j = b.ShiftLeft(i); a.SubtractFromThis(j); a.ReduceN(); i = a._length - b._length; } return a; }
/// <summary> /// Checks if <c>this</c> is irreducible, according to IEEE P1363, A.5.5, p103. /// <para>Note: The algorithm from IEEE P1363, A5.5 can be used to check a polynomial with coefficients in GF(2^r) for irreducibility. /// As this class only represents polynomials with coefficients in GF(2), the algorithm is adapted to the case r=1.</para> /// </summary> /// /// <returns>Returns true if <c>this</c> is irreducible</returns> public bool IsIrreducible() { if (IsZero()) return false; GF2Polynomial f = new GF2Polynomial(this); int d, i; GF2Polynomial u, g; GF2Polynomial dummy; f.ReduceN(); d = f._length - 1; u = new GF2Polynomial(f._length, "X"); for (i = 1; i <= (d >> 1); i++) { u.SquareThisPreCalc(); u = u.Remainder(f); dummy = u.Add(new GF2Polynomial(32, "X")); if (!dummy.IsZero()) { g = f.Gcd(dummy); if (!g.IsOne()) return false; } else { return false; } } return true; }
/// <summary> /// Returns the absolute quotient of <c>this</c> divided by <c>G</c> in a new GF2Polynomial /// </summary> /// /// <param name="G">A GF2Polynomial != 0</param> /// /// <returns>Returns a new GF2Polynomial |_ <c>this</c> / <c>G</c></returns> public GF2Polynomial Quotient(GF2Polynomial G) { // a div b = q / r GF2Polynomial q = new GF2Polynomial(_length); GF2Polynomial a = new GF2Polynomial(this); GF2Polynomial b = new GF2Polynomial(G); GF2Polynomial j; int i; if (b.IsZero()) throw new Exception(); a.ReduceN(); b.ReduceN(); if (a._length < b._length) return new GF2Polynomial(0); i = a._length - b._length; q.ExpandN(i + 1); while (i >= 0) { j = b.ShiftLeft(i); a.SubtractFromThis(j); a.ReduceN(); q.XorBit(i); i = a._length - b._length; } return q; }
/// <summary> /// Divides <c>this</c> by <c>G</c> and returns the quotient and remainder in a new GF2Polynomial[2], quotient in [0], remainder in [1] /// </summary> /// /// <param name="G">A GF2Polynomial != 0</param> /// /// <returns>Returns a new GF2Polynomial[2] containing quotient and remainder</returns> public GF2Polynomial[] Divide(GF2Polynomial G) { // a div b = q / r GF2Polynomial[] result = new GF2Polynomial[2]; GF2Polynomial q = new GF2Polynomial(_length); GF2Polynomial a = new GF2Polynomial(this); GF2Polynomial b = new GF2Polynomial(G); GF2Polynomial j; int i; if (b.IsZero()) throw new Exception(); a.ReduceN(); b.ReduceN(); if (a._length < b._length) { result[0] = new GF2Polynomial(0); result[1] = a; return result; } i = a._length - b._length; q.ExpandN(i + 1); while (i >= 0) { j = b.ShiftLeft(i); a.SubtractFromThis(j); a.ReduceN(); q.XorBit(i); i = a._length - b._length; } result[0] = q; result[1] = a; return result; }