/// <summary> /// Calculates the multiplicative inverse of <c>this</c> using the modified almost inverse algorithm and returns the result in a new GF2nPolynomialElement /// </summary> /// /// <returns>Returns <c>this</c>^(-1)</returns> public GF2nPolynomialElement InvertMAIA() { if (IsZero()) { throw new ArithmeticException(); } GF2Polynomial b = new GF2Polynomial(mDegree, "ONE"); GF2Polynomial c = new GF2Polynomial(mDegree); GF2Polynomial u = GetGF2Polynomial(); GF2Polynomial v = mField.FieldPolynomial; GF2Polynomial h; while (true) { while (!u.TestBit(0)) { // x|u (x divides u) u.ShiftRightThis(); // u = u / x if (!b.TestBit(0)) { b.ShiftRightThis(); } else { b.AddToThis(mField.FieldPolynomial); b.ShiftRightThis(); } } if (u.IsOne()) return new GF2nPolynomialElement((GF2nPolynomialField)mField, b); u.ReduceN(); v.ReduceN(); if (u.Length < v.Length) { h = u; u = v; v = h; h = b; b = c; c = h; } u.AddToThis(v); b.AddToThis(c); } }
/// <summary> /// Computes the field polynomial for a ONB according to IEEE 1363 A.7.2 /// </summary> protected override void ComputeFieldPolynomial() { if (_mType == 1) { FieldPoly = new GF2Polynomial(DegreeN + 1, "ALL"); } else if (_mType == 2) { // 1. q = 1 GF2Polynomial q = new GF2Polynomial(DegreeN + 1, "ONE"); // 2. p = t+1 GF2Polynomial p = new GF2Polynomial(DegreeN + 1, "X"); p.AddToThis(q); GF2Polynomial r; int i; // 3. for i = 1 to (m-1) do for (i = 1; i < DegreeN; i++) { // r <- q r = q; // q <- p q = p; // p = tq+r p = q.ShiftLeft(); p.AddToThis(r); } FieldPoly = p; } }
/// <summary> /// Does the recursion for Karatzuba multiplication /// </summary> /// /// <param name="B">A GF2Polynomial</param> /// /// <returns><c>this * B</c></returns> private GF2Polynomial KaraMult(GF2Polynomial B) { GF2Polynomial result = new GF2Polynomial(_length << 1); if (_length <= 32) { result._value = Mult32(_value[0], B._value[0]); return result; } if (_length <= 64) { result._value = Mult64(_value, B._value); return result; } if (_length <= 128) { result._value = Mult128(_value, B._value); return result; } if (_length <= 256) { result._value = Mult256(_value, B._value); return result; } if (_length <= 512) { result._value = Mult512(_value, B._value); return result; } int n = BigMath.FloorLog(_length - 1); n = _bitMask[n]; GF2Polynomial a0 = Lower(((n - 1) >> 5) + 1); GF2Polynomial a1 = Upper(((n - 1) >> 5) + 1); GF2Polynomial b0 = B.Lower(((n - 1) >> 5) + 1); GF2Polynomial b1 = B.Upper(((n - 1) >> 5) + 1); GF2Polynomial c = a1.KaraMult(b1); // c = a1*b1 GF2Polynomial e = a0.KaraMult(b0); // e = a0*b0 a0.AddToThis(a1); // a0 = a0 + a1 b0.AddToThis(b1); // b0 = b0 + b1 GF2Polynomial d = a0.KaraMult(b0); // d = (a0+a1)*(b0+b1) result.ShiftLeftAddThis(c, n << 1); result.ShiftLeftAddThis(c, n); result.ShiftLeftAddThis(d, n); result.ShiftLeftAddThis(e, n); result.AddToThis(e); return result; }