/// <summary> /// Multiplies <c>this</c> by <c>P</c> and returns the result in a new PolynomialGF2n /// </summary> /// /// <param name="P">The PolynomialGF2n to multiply</param> /// /// <returns>Returns <c>this</c> * <c>P</c></returns> public GF2nPolynomial Multiply(GF2nPolynomial P) { int i, j; int aDegree = Size; int bDegree = P.Size; if (aDegree != bDegree) { throw new ArgumentException("PolynomialGF2n.Multiply: this and b must have the same size!"); } GF2nPolynomial result = new GF2nPolynomial((aDegree << 1) - 1); for (i = 0; i < Size; i++) { for (j = 0; j < P.Size; j++) { if (result._coeff[i + j] == null) { result._coeff[i + j] = (GF2nElement)_coeff[i].Multiply(P._coeff[j]); } else { result._coeff[i + j] = (GF2nElement)result._coeff[i + j].Add(_coeff[i].Multiply(P._coeff[j])); } } } return(result); }
/// <summary> /// Divides <c>this</c> by <c>B</c> and stores the quotient in a new PolynomialGF2n /// </summary> /// /// <param name="B">The divisor</param> /// /// <returns>Returns the quotient <c>this</c> / <c>B</c></returns> public GF2nPolynomial Quotient(GF2nPolynomial B) { GF2nPolynomial[] result = new GF2nPolynomial[2]; result = Divide(B); return(result[0]); }
/// <summary> /// Divides <c>this</c> by <c>b</c> and stores the remainder in a new PolynomialGF2n /// </summary> /// /// <param name="B">The divisor</param> /// /// <returns>Returns The remainder <c>this</c> % <c>b</c></returns> public GF2nPolynomial Remainder(GF2nPolynomial B) { GF2nPolynomial[] result = new GF2nPolynomial[2]; result = Divide(B); return(result[1]); }
/// <summary> /// Adds the PolynomialGF2n <c>G</c> to <c>this</c> and returns the result in a new <c>PolynomialGF2n</c> /// </summary> /// /// <param name="P">The <c>PolynomialGF2n</c> to add</param> /// /// <returns>Returns <c>this + b</c></returns> public GF2nPolynomial Add(GF2nPolynomial P) { GF2nPolynomial result; if (Size >= P.Size) { result = new GF2nPolynomial(Size); int i; for (i = 0; i < P.Size; i++) { result._coeff[i] = (GF2nElement)_coeff[i].Add(P._coeff[i]); } for (; i < Size; i++) { result._coeff[i] = _coeff[i]; } } else { result = new GF2nPolynomial(P.Size); int i; for (i = 0; i < Size; i++) { result._coeff[i] = (GF2nElement)_coeff[i].Add(P._coeff[i]); } for (; i < P.Size; i++) { result._coeff[i] = P._coeff[i]; } } return(result); }
/// <summary> /// Creates a new PolynomialGF2n by cloning the given PolynomialGF2n <c>G</c> /// </summary> /// /// <param name="G">The PolynomialGF2n to clone</param> public GF2nPolynomial(GF2nPolynomial G) { int i; _coeff = new GF2nElement[G._size]; _size = G._size; for (i = 0; i < _size; i++) _coeff[i] = (GF2nElement)G._coeff[i].Clone(); }
/// <summary> /// Compute a random root of the given GF2Polynomial /// </summary> /// /// <param name="G">The polynomial</param> /// /// <returns>Returns a random root of <c>G</c></returns> public override GF2nElement RandomRoot(GF2Polynomial G) { // We are in B1!!! GF2nPolynomial c; GF2nPolynomial ut; GF2nElement u; GF2nPolynomial h; int hDegree; // 1. Set g(t) <- f(t) GF2nPolynomial g = new GF2nPolynomial(G, this); int gDegree = g.Degree; int i; // 2. while deg(g) > 1 while (gDegree > 1) { do { // 2.1 choose random u (element of) GF(2^m) u = new GF2nPolynomialElement(this, new Random()); ut = new GF2nPolynomial(2, GF2nPolynomialElement.Zero(this)); // 2.2 Set c(t) <- ut ut.Set(1, u); c = new GF2nPolynomial(ut); // 2.3 For i from 1 to m-1 do for (i = 1; i <= DegreeN - 1; i++) { // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t) c = c.MultiplyAndReduce(c, g); c = c.Add(ut); } // 2.4 set h(t) <- GCD(c(t), g(t)) h = c.Gcd(g); // 2.5 if h(t) is constant or deg(g) = deg(h) then go to // step 2.1 hDegree = h.Degree; gDegree = g.Degree; }while ((hDegree == 0) || (hDegree == gDegree)); // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ... if ((hDegree << 1) > gDegree) { g = g.Quotient(h); } else { g = new GF2nPolynomial(h); // ... else g(t) <- h(t) } gDegree = g.Degree; } // 3. Output g(0) return(g.At(0)); }
/// <summary> /// Multiplies the scalar <c>E</c> to each coefficient of this PolynomialGF2n and returns the result in a new PolynomialGF2n /// </summary> /// /// <param name="E">The scalar to multiply</param> /// /// <returns>Returns <c>this</c> x <c>E</c></returns> public GF2nPolynomial ScalarMultiply(GF2nElement E) { GF2nPolynomial result = new GF2nPolynomial(Size); for (int i = 0; i < Size; i++) { result._coeff[i] = (GF2nElement)_coeff[i].Multiply(E); } return(result); }
/// <summary> /// Creates a new PolynomialGF2n by cloning the given PolynomialGF2n <c>G</c> /// </summary> /// /// <param name="G">The PolynomialGF2n to clone</param> public GF2nPolynomial(GF2nPolynomial G) { int i; _coeff = new GF2nElement[G._size]; _size = G._size; for (i = 0; i < _size; i++) { _coeff[i] = (GF2nElement)G._coeff[i].Clone(); } }
/// <summary> /// Creates a new PolynomialGF2n by cloning the given PolynomialGF2n <c>G</c> /// </summary> /// /// <param name="G">The PolynomialGF2n to clone</param> public GF2nPolynomial(GF2nPolynomial G) { int i; m_coeff = new GF2nElement[G.m_Size]; m_Size = G.m_Size; for (i = 0; i < m_Size; i++) { m_coeff[i] = (GF2nElement)G.m_coeff[i].Clone(); } }
/// <summary> /// Shifts left <c>this</c> by <c>N</c> and stores the result in <c>this</c> PolynomialGF2n /// </summary> /// /// <param name="N">The amount the amount to shift the coefficients</param> /// /// <returns>The shifted polynomial</returns> public GF2nPolynomial ShiftLeft(int N) { if (N <= 0) { return(new GF2nPolynomial(this)); } GF2nPolynomial result = new GF2nPolynomial(_size + N, _coeff[0]); result.AssignZeroToElements(); for (int i = 0; i < _size; i++) { result._coeff[i + N] = _coeff[i]; } return(result); }
/// <summary> /// Divides <c>this</c> by <c>b</c> and stores the result in a new PolynomialGF2n[2], quotient in result[0] and remainder in result[1] /// </summary> /// /// <param name="B">The divisor</param> /// /// <returns>Retuens the quotient and remainder of <c>this</c> / <c>b</c></returns> public GF2nPolynomial[] Divide(GF2nPolynomial B) { GF2nPolynomial[] result = new GF2nPolynomial[2]; GF2nPolynomial a = new GF2nPolynomial(this); a.Shrink(); GF2nPolynomial shift; GF2nElement factor; int bDegree = B.Degree; GF2nElement inv = (GF2nElement)B._coeff[bDegree].Invert(); if (a.Degree < bDegree) { result[0] = new GF2nPolynomial(this); result[0].AssignZeroToElements(); result[0].Shrink(); result[1] = new GF2nPolynomial(this); result[1].Shrink(); return(result); } result[0] = new GF2nPolynomial(this); result[0].AssignZeroToElements(); int i = a.Degree - bDegree; while (i >= 0) { factor = (GF2nElement)a._coeff[a.Degree].Multiply(inv); shift = B.ScalarMultiply(factor); shift.ShiftThisLeft(i); a = a.Add(shift); a.Shrink(); result[0]._coeff[i] = (GF2nElement)factor.Clone(); i = a.Degree - bDegree; } result[1] = a; result[0].Shrink(); return(result); }
/// <summary> /// Computes the greatest common divisor of <c>this</c> and <c>g</c> and returns the result in a new PolynomialGF2n /// </summary> /// /// <param name="G">The GF2nPolynomial</param> /// /// <returns>Returns gcd(<c>this</c>, <c>g</c>)</returns> public GF2nPolynomial Gcd(GF2nPolynomial G) { GF2nPolynomial a = new GF2nPolynomial(this); GF2nPolynomial b = new GF2nPolynomial(G); a.Shrink(); b.Shrink(); GF2nPolynomial c; GF2nPolynomial result; GF2nElement alpha; while (!b.IsZero()) { c = a.Remainder(b); a = b; b = c; } alpha = a._coeff[a.Degree]; result = a.ScalarMultiply((GF2nElement)alpha.Invert()); return(result); }
/// <summary> /// Compare this element with another object /// </summary> /// /// <param name="Obj">The object for comprison</param> /// /// <returns>Returns <c>true</c> if the two objects are equal, <c>false</c> otherwise</returns> public override bool Equals(Object Obj) { if (Obj == null || !(Obj is GF2nPolynomial)) { return(false); } GF2nPolynomial otherPol = (GF2nPolynomial)Obj; if (Degree != otherPol.Degree) { return(false); } for (int i = 0; i < _size; i++) { if (!_coeff[i].Equals(otherPol._coeff[i])) { return(false); } } return(true); }
/// <summary> /// Reduces <c>this</c> by <c>G</c> and returns the result in a newPolynomialGF2n /// </summary> /// /// <param name="G">The modulus</param> /// /// <returns>Returns <c>this</c> % <c>G</c></returns> public GF2nPolynomial Reduce(GF2nPolynomial G) { return Remainder(G); }
/// <summary> /// Multiplies <c>this</c> by <c>P</c> and returns the result in a new PolynomialGF2n /// </summary> /// /// <param name="P">The PolynomialGF2n to multiply</param> /// /// <returns>Returns <c>this</c> * <c>P</c></returns> public GF2nPolynomial Multiply(GF2nPolynomial P) { int i, j; int aDegree = Size; int bDegree = P.Size; if (aDegree != bDegree) throw new ArgumentException("PolynomialGF2n.Multiply: this and b must have the same size!"); GF2nPolynomial result = new GF2nPolynomial((aDegree << 1) - 1); for (i = 0; i < Size; i++) { for (j = 0; j < P.Size; j++) { if (result._coeff[i + j] == null) result._coeff[i + j] = (GF2nElement)_coeff[i].Multiply(P._coeff[j]); else result._coeff[i + j] = (GF2nElement)result._coeff[i + j].Add(_coeff[i].Multiply(P._coeff[j])); } } return result; }
/// <summary> /// Divides <c>this</c> by <c>b</c> and stores the result in a new PolynomialGF2n[2], quotient in result[0] and remainder in result[1] /// </summary> /// /// <param name="B">The divisor</param> /// /// <returns>Retuens the quotient and remainder of <c>this</c> / <c>b</c></returns> public GF2nPolynomial[] Divide(GF2nPolynomial B) { GF2nPolynomial[] result = new GF2nPolynomial[2]; GF2nPolynomial a = new GF2nPolynomial(this); a.Shrink(); GF2nPolynomial shift; GF2nElement factor; int bDegree = B.Degree; GF2nElement inv = (GF2nElement)B._coeff[bDegree].Invert(); if (a.Degree < bDegree) { result[0] = new GF2nPolynomial(this); result[0].AssignZeroToElements(); result[0].Shrink(); result[1] = new GF2nPolynomial(this); result[1].Shrink(); return result; } result[0] = new GF2nPolynomial(this); result[0].AssignZeroToElements(); int i = a.Degree - bDegree; while (i >= 0) { factor = (GF2nElement)a._coeff[a.Degree].Multiply(inv); shift = B.ScalarMultiply(factor); shift.ShiftThisLeft(i); a = a.Add(shift); a.Shrink(); result[0]._coeff[i] = (GF2nElement)factor.Clone(); i = a.Degree - bDegree; } result[1] = a; result[0].Shrink(); return result; }
/// <summary> /// Divides <c>this</c> by <c>b</c> and stores the remainder in a new PolynomialGF2n /// </summary> /// /// <param name="B">The divisor</param> /// /// <returns>Returns The remainder <c>this</c> % <c>b</c></returns> public GF2nPolynomial Remainder(GF2nPolynomial B) { GF2nPolynomial[] result = new GF2nPolynomial[2]; result = Divide(B); return result[1]; }
/// <summary> /// Computes the greatest common divisor of <c>this</c> and <c>g</c> and returns the result in a new PolynomialGF2n /// </summary> /// /// <param name="G">The GF2nPolynomial</param> /// /// <returns>Returns gcd(<c>this</c>, <c>g</c>)</returns> public GF2nPolynomial Gcd(GF2nPolynomial G) { GF2nPolynomial a = new GF2nPolynomial(this); GF2nPolynomial b = new GF2nPolynomial(G); a.Shrink(); b.Shrink(); GF2nPolynomial c; GF2nPolynomial result; GF2nElement alpha; while (!b.IsZero()) { c = a.Remainder(b); a = b; b = c; } alpha = a._coeff[a.Degree]; result = a.ScalarMultiply((GF2nElement)alpha.Invert()); return result; }
/// <summary> /// Reduces <c>this</c> by <c>G</c> and returns the result in a newPolynomialGF2n /// </summary> /// /// <param name="G">The modulus</param> /// /// <returns>Returns <c>this</c> % <c>G</c></returns> public GF2nPolynomial Reduce(GF2nPolynomial G) { return(Remainder(G)); }
/// <summary> /// Multiplies <c>this</c> by <c>B</c>, reduces the result by <c>G</c> and returns it in a new PolynomialGF2n /// </summary> /// /// <param name="B">The PolynomialGF2n to multiply</param> /// <param name="G">The modulus</param> /// /// <returns>Returns <c>this</c> * <c>B</c> mod <c>G</c></returns> public GF2nPolynomial MultiplyAndReduce(GF2nPolynomial B, GF2nPolynomial G) { return(Multiply(B).Reduce(G)); }
/// <summary> /// Multiplies <c>this</c> by <c>B</c>, reduces the result by <c>G</c> and returns it in a new PolynomialGF2n /// </summary> /// /// <param name="B">The PolynomialGF2n to multiply</param> /// <param name="G">The modulus</param> /// /// <returns>Returns <c>this</c> * <c>B</c> mod <c>G</c></returns> public GF2nPolynomial MultiplyAndReduce(GF2nPolynomial B, GF2nPolynomial G) { return Multiply(B).Reduce(G); }
/// <summary> /// Multiplies the scalar <c>E</c> to each coefficient of this PolynomialGF2n and returns the result in a new PolynomialGF2n /// </summary> /// /// <param name="E">The scalar to multiply</param> /// /// <returns>Returns <c>this</c> x <c>E</c></returns> public GF2nPolynomial ScalarMultiply(GF2nElement E) { GF2nPolynomial result = new GF2nPolynomial(Size); for (int i = 0; i < Size; i++) result._coeff[i] = (GF2nElement)_coeff[i].Multiply(E); return result; }
/// <summary> /// Shifts left <c>this</c> by <c>N</c> and stores the result in <c>this</c> PolynomialGF2n /// </summary> /// /// <param name="N">The amount the amount to shift the coefficients</param> /// /// <returns>The shifted polynomial</returns> public GF2nPolynomial ShiftLeft(int N) { if (N <= 0) return new GF2nPolynomial(this); GF2nPolynomial result = new GF2nPolynomial(_size + N, _coeff[0]); result.AssignZeroToElements(); for (int i = 0; i < _size; i++) result._coeff[i + N] = _coeff[i]; return result; }
/// <summary> /// Adds the PolynomialGF2n <c>G</c> to <c>this</c> and returns the result in a new <c>PolynomialGF2n</c> /// </summary> /// /// <param name="P">The <c>PolynomialGF2n</c> to add</param> /// /// <returns>Returns <c>this + b</c></returns> public GF2nPolynomial Add(GF2nPolynomial P) { GF2nPolynomial result; if (Size >= P.Size) { result = new GF2nPolynomial(Size); int i; for (i = 0; i < P.Size; i++) result._coeff[i] = (GF2nElement)_coeff[i].Add(P._coeff[i]); for (; i < Size; i++) result._coeff[i] = _coeff[i]; } else { result = new GF2nPolynomial(P.Size); int i; for (i = 0; i < Size; i++) result._coeff[i] = (GF2nElement)_coeff[i].Add(P._coeff[i]); for (; i < P.Size; i++) result._coeff[i] = P._coeff[i]; } return result; }
/// <summary> /// Compute a random root of the given GF2Polynomial /// </summary> /// /// <param name="G">The polynomial</param> /// /// <returns>Returns a random root of <c>G</c></returns> public override GF2nElement RandomRoot(GF2Polynomial G) { // We are in B1!!! GF2nPolynomial c; GF2nPolynomial ut; GF2nElement u; GF2nPolynomial h; int hDegree; // 1. Set g(t) <- f(t) GF2nPolynomial g = new GF2nPolynomial(G, this); int gDegree = g.Degree; int i; // 2. while deg(g) > 1 while (gDegree > 1) { do { // 2.1 choose random u (element of) GF(2^m) u = new GF2nPolynomialElement(this, new Random()); ut = new GF2nPolynomial(2, GF2nPolynomialElement.Zero(this)); // 2.2 Set c(t) <- ut ut.Set(1, u); c = new GF2nPolynomial(ut); // 2.3 For i from 1 to m-1 do for (i = 1; i <= DegreeN - 1; i++) { // 2.3.1 c(t) <- (c(t)^2 + ut) mod g(t) c = c.MultiplyAndReduce(c, g); c = c.Add(ut); } // 2.4 set h(t) <- GCD(c(t), g(t)) h = c.Gcd(g); // 2.5 if h(t) is constant or deg(g) = deg(h) then go to // step 2.1 hDegree = h.Degree; gDegree = g.Degree; } while ((hDegree == 0) || (hDegree == gDegree)); // 2.6 If 2deg(h) > deg(g) then set g(t) <- g(t)/h(t) ... if ((hDegree << 1) > gDegree) g = g.Quotient(h); else g = new GF2nPolynomial(h); // ... else g(t) <- h(t) gDegree = g.Degree; } // 3. Output g(0) return g.At(0); }
/// <summary> /// Divides <c>this</c> by <c>B</c> and stores the quotient in a new PolynomialGF2n /// </summary> /// /// <param name="B">The divisor</param> /// /// <returns>Returns the quotient <c>this</c> / <c>B</c></returns> public GF2nPolynomial Quotient(GF2nPolynomial B) { GF2nPolynomial[] result = new GF2nPolynomial[2]; result = Divide(B); return result[0]; }