/// <summary> /// Calculates <c>this</c> to the power of <c>K</c> and returns the result in a new GF2nPolynomialElement /// </summary> /// /// <param name="K">The power</param> /// /// <returns>Returns <c>this</c>^<c>K</c> in a new GF2nPolynomialElement</returns> public GF2nPolynomialElement Power(int K) { if (K == 1) { return(new GF2nPolynomialElement(this)); } GF2nPolynomialElement result = GF2nPolynomialElement.One((GF2nPolynomialField)m_Field); if (K == 0) { return(result); } GF2nPolynomialElement x = new GF2nPolynomialElement(this); x.m_polynomial.ExpandN((x.m_Degree << 1) + 32); // increase performance x.m_polynomial.ReduceN(); for (int i = 0; i < m_Degree; i++) { if ((K & (1 << i)) != 0) { result.MultiplyThisBy(x); } x.Square(); } return(result); }
/// <summary> /// Enlarges the size of this PolynomialGF2n to <c>k</c> + 1 /// </summary> /// /// <param name="K">The new maximum degree</param> public void Enlarge(int K) { if (K <= _size) { return; } int i; GF2nElement[] res = new GF2nElement[K]; Array.Copy(_coeff, 0, res, 0, _size); GF2nField f = _coeff[0].GetField(); if (_coeff[0] is GF2nPolynomialElement) { for (i = _size; i < K; i++) { res[i] = GF2nPolynomialElement.Zero((GF2nPolynomialField)f); } } else if (_coeff[0] is GF2nONBElement) { for (i = _size; i < K; i++) { res[i] = GF2nONBElement.Zero((GF2nONBField)f); } } _size = K; _coeff = res; }
/// <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> public void ShiftThisLeft(int N) { if (N > 0) { int i; int oldSize = _size; GF2nField f = _coeff[0].GetField(); Enlarge(_size + N); for (i = oldSize - 1; i >= 0; i--) { _coeff[i + N] = _coeff[i]; } if (_coeff[0] is GF2nPolynomialElement) { for (i = N - 1; i >= 0; i--) { _coeff[i] = GF2nPolynomialElement.Zero((GF2nPolynomialField)f); } } else if (_coeff[0] is GF2nONBElement) { for (i = N - 1; i >= 0; i--) { _coeff[i] = GF2nONBElement.Zero((GF2nONBField)f); } } } }
/// <summary> /// Compute the product of this element and <c>factor</c> /// </summary> /// /// <param name="Factor">he factor</param> /// /// <returns>Returns <c>this * factor</c> </returns> public override IGFElement Multiply(IGFElement Factor) { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.MultiplyThisBy(Factor); return(result); }
/// <summary> /// Compute the sum of this element and <c>Addend</c>. /// </summary> /// /// <param name="Addend">The addend</param> /// /// <returns>Returns <c>this + other</c></returns> public override IGFElement Add(IGFElement Addend) { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.AddToThis(Addend); return(result); }
/// <summary> /// Squares this GF2nPolynomialElement using GF2nField's squaring matrix. /// <para>This is supposed to be fast when using a polynomial (no tri- or pentanomial) as fieldpolynomial. /// Use SquarePreCalc when using a tri- or pentanomial as fieldpolynomial instead.</para> /// </summary> /// /// <returns>Returns <c>this^2</c> (newly created)</returns> public GF2nPolynomialElement SquareMatrix() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareThisMatrix(); result.ReduceThis(); return(result); }
/// <summary> /// Squares this GF2nPolynomialElement by shifting left its Bitstring and reducing. /// <para>This is supposed to be the slowest method. Use SquarePreCalc or SquareMatrix instead.</para> /// </summary> /// /// <returns></returns> public GF2nPolynomialElement SquareBitwise() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareThisBitwise(); result.ReduceThis(); return(result); }
/// <summary> /// Compute the square root of this element and return the result in a new GF2nPolynomialElement /// </summary> /// /// <returns>Returns <c>this^1/2</c> (newly created)</returns> public override GF2nElement SquareRoot() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareRootThis(); return(result); }
/// <summary> /// Increase the element by one /// </summary> /// /// <returns>Returns <c>this</c> + 'one'</returns> public override GF2nElement Increase() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.IncreaseThis(); return(result); }
/// <summary> /// Squares this GF2nPolynomialElement by using precalculated values and reducing. /// <para>This is supposed to de fastest when using a trinomial or pentanomial as field polynomial. /// Use SquareMatrix when using a ordinary polynomial as field polynomial.</para> /// </summary> /// /// <returns></returns> public GF2nPolynomialElement SquarePreCalc() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareThisPreCalc(); result.ReduceThis(); 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> /// Computes the change-of-basis matrix for basis conversion according to 1363. /// The result is stored in the lists fields and matrices. /// </summary> /// /// <param name="B1">The GF2nField to convert to</param> public override void ComputeCOBMatrix(GF2nField B1) { // we are in B0 here! if (DegreeN != B1.Degree) { throw new ArgumentException("GF2nField.computeCOBMatrix: B1 has a different degree and thus cannot be coverted to!"); } int i, j; GF2nElement[] gamma; GF2nElement u; GF2Polynomial[] COBMatrix = new GF2Polynomial[DegreeN]; for (i = 0; i < DegreeN; i++) { COBMatrix[i] = new GF2Polynomial(DegreeN); } // find Random Root do { // u is in representation according to B1 u = B1.RandomRoot(FieldPoly); }while (u.IsZero()); gamma = new GF2nPolynomialElement[DegreeN]; // build gamma matrix by squaring gamma[0] = (GF2nElement)u.Clone(); for (i = 1; i < DegreeN; i++) { gamma[i] = gamma[i - 1].Square(); } // convert horizontal gamma matrix by vertical Bitstrings for (i = 0; i < DegreeN; i++) { for (j = 0; j < DegreeN; j++) { if (gamma[i].TestBit(j)) { COBMatrix[DegreeN - j - 1].SetBit(DegreeN - i - 1); } } } Fields.Add(B1); Matrices.Add(COBMatrix); B1.Fields.Add(this); B1.Matrices.Add(InvertMatrix(COBMatrix)); }
/// <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 InvertSquare() { GF2nPolynomialElement n; GF2nPolynomialElement u; int i, j, k, b; if (IsZero()) { throw new ArithmeticException(); } // b = (n-1) b = m_Field.Degree - 1; // n = a n = new GF2nPolynomialElement(this); n.m_polynomial.ExpandN((m_Degree << 1) + 32); // increase performance n.m_polynomial.ReduceN(); // k = 1 k = 1; // for i = (r-1) downto 0 do, r=bitlength(b) for (i = BigMath.FloorLog(b) - 1; i >= 0; i--) { // u = n u = new GF2nPolynomialElement(n); // for j = 1 to k do for (j = 1; j <= k; j++) { u.SquareThisPreCalc(); // u = u^2 } // n = nu n.MultiplyThisBy(u); // k = 2k k <<= 1; // if b(i)==1 if ((b & m_bitMask[i]) != 0) { // n = n^2 * b n.SquareThisPreCalc(); n.MultiplyThisBy(this); // k = k+1 k += 1; } } // outpur n^2 n.SquareThisPreCalc(); return(n); }
/// <summary> /// Returns the trace of this GF2nPolynomialElement /// </summary> /// /// <returns>The trace of this GF2nPolynomialElement</returns> public override int Trace() { GF2nPolynomialElement t = new GF2nPolynomialElement(this); int i; for (i = 1; i < m_Degree; i++) { t.SquareThis(); t.AddToThis(this); } if (t.IsOne()) { return(1); } return(0); }
/// <summary> /// Solves the quadratic equation <c>z^2 + z = this</c> if such a solution exists. /// <para>This method returns one of the two possible solutions. /// The other solution is <c>z + 1</c>. Use z.Increase() to compute this solution.</para> /// </summary> /// /// <returns>Returns a GF2nPolynomialElement representing one z satisfying the equation <c>z^2 + z = this</c></returns> public override GF2nElement SolveQuadraticEquation() { if (IsZero()) { return(Zero((GF2nPolynomialField)m_Field)); } if ((m_Degree & 1) == 1) { return(HalfTrace()); } // TODO this can be sped-up by precomputation of p and w's GF2nPolynomialElement z, w; do { // step 1. GF2nPolynomialElement p = new GF2nPolynomialElement( (GF2nPolynomialField)m_Field, new Random()); // step 2. z = Zero((GF2nPolynomialField)m_Field); w = (GF2nPolynomialElement)p.Clone(); // step 3. for (int i = 1; i < m_Degree; i++) { // compute z = z^2 + w^2 * this // and w = w^2 + p z.SquareThis(); w.SquareThis(); z.AddToThis(w.Multiply(this)); w.AddToThis(p); } }while (w.IsZero()); // step 4. if (!Equals(z.Square().Add(z))) { throw new Exception(); } // step 5. return(z); }
/// <summary> /// Returns the half-trace of this GF2nPolynomialElement /// </summary> /// /// <returns>Returns a GF2nPolynomialElement representing the half-trace of this GF2nPolynomialElement</returns> private GF2nPolynomialElement HalfTrace() { if ((m_Degree & 0x01) == 0) { throw new Exception(); } int i; GF2nPolynomialElement h = new GF2nPolynomialElement(this); for (i = 1; i <= ((m_Degree - 1) >> 1); i++) { h.SquareThis(); h.SquareThis(); h.AddToThis(this); } return(h); }
/// <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 GF2nPolynomialElement)) { return(false); } GF2nPolynomialElement otherElem = (GF2nPolynomialElement)Obj; if (m_Field != otherElem.m_Field) { if (!m_Field.FieldPolynomial.Equals(otherElem.m_Field.FieldPolynomial)) { return(false); } } return(m_polynomial.Equals(otherElem.m_polynomial)); }
/// <summary> /// Creates a new PolynomialGF2n from the given Bitstring <c>G</c> over the GF2nField <c>B1</c> /// </summary> /// /// <param name="G">The Bitstring to use</param> /// <param name="B1">The field</param> public GF2nPolynomial(GF2Polynomial G, GF2nField B1) { _size = B1.Degree + 1; _coeff = new GF2nElement[_size]; int i; if (B1 is GF2nONBField) { for (i = 0; i < _size; i++) { if (G.TestBit(i)) { _coeff[i] = GF2nONBElement.One((GF2nONBField)B1); } else { _coeff[i] = GF2nONBElement.Zero((GF2nONBField)B1); } } } else if (B1 is GF2nPolynomialField) { for (i = 0; i < _size; i++) { if (G.TestBit(i)) { _coeff[i] = GF2nPolynomialElement.One((GF2nPolynomialField)B1); } else { _coeff[i] = GF2nPolynomialElement.Zero((GF2nPolynomialField)B1); } } } else { throw new ArgumentException("GF2nPolynomial: PolynomialGF2n(Bitstring, GF2nField): B1 must be an instance of GF2nONBField or GF2nPolynomialField!"); } }
/** * . * * @param other t */ /// <summary> /// Creates a new GF2nPolynomialElement by cloning the given GF2nPolynomialElement <c>Ge</c> /// </summary> /// /// <param name="Ge">The GF2nPolynomialElement to clone</param> public GF2nPolynomialElement(GF2nPolynomialElement Ge) { mField = Ge.mField; mDegree = Ge.mDegree; polynomial = new GF2Polynomial(Ge.polynomial); }
/// <summary> /// Compute the product of this element and <c>factor</c> /// </summary> /// /// <param name="Factor">he factor</param> /// /// <returns>Returns <c>this * factor</c> </returns> public override IGFElement Multiply(IGFElement Factor) { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.MultiplyThisBy(Factor); return result; }
/// <summary> /// Returns the trace of this GF2nPolynomialElement /// </summary> /// /// <returns>The trace of this GF2nPolynomialElement</returns> public override int Trace() { GF2nPolynomialElement t = new GF2nPolynomialElement(this); int i; for (i = 1; i < mDegree; i++) { t.SquareThis(); t.AddToThis(this); } if (t.IsOne()) return 1; return 0; }
/// <summary> /// Returns the half-trace of this GF2nPolynomialElement /// </summary> /// /// <returns>Returns a GF2nPolynomialElement representing the half-trace of this GF2nPolynomialElement</returns> private GF2nPolynomialElement HalfTrace() { if ((mDegree & 0x01) == 0) throw new Exception(); int i; GF2nPolynomialElement h = new GF2nPolynomialElement(this); for (i = 1; i <= ((mDegree - 1) >> 1); i++) { h.SquareThis(); h.SquareThis(); h.AddToThis(this); } return h; }
/// <summary> /// Squares this GF2nPolynomialElement by using precalculated values and reducing. /// <para>This is supposed to de fastest when using a trinomial or pentanomial as field polynomial. /// Use SquareMatrix when using a ordinary polynomial as field polynomial.</para> /// </summary> /// /// <returns></returns> public GF2nPolynomialElement SquarePreCalc() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareThisPreCalc(); result.ReduceThis(); return result; }
/// <summary> /// Compute the square root of this element and return the result in a new GF2nPolynomialElement /// </summary> /// /// <returns>Returns <c>this^1/2</c> (newly created)</returns> public override GF2nElement SquareRoot() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareRootThis(); return result; }
/// <summary> /// Squares this GF2nPolynomialElement by shifting left its Bitstring and reducing. /// <para>This is supposed to be the slowest method. Use SquarePreCalc or SquareMatrix instead.</para> /// </summary> /// /// <returns></returns> public GF2nPolynomialElement SquareBitwise() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareThisBitwise(); result.ReduceThis(); return result; }
/// <summary> /// Squares this GF2nPolynomialElement using GF2nField's squaring matrix. /// <para>This is supposed to be fast when using a polynomial (no tri- or pentanomial) as fieldpolynomial. /// Use SquarePreCalc when using a tri- or pentanomial as fieldpolynomial instead.</para> /// </summary> /// /// <returns>Returns <c>this^2</c> (newly created)</returns> public GF2nPolynomialElement SquareMatrix() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.SquareThisMatrix(); result.ReduceThis(); return result; }
/** * . * * @param other t */ /// <summary> /// Creates a new GF2nPolynomialElement by cloning the given GF2nPolynomialElement <c>Ge</c> /// </summary> /// /// <param name="Ge">The GF2nPolynomialElement to clone</param> public GF2nPolynomialElement(GF2nPolynomialElement Ge) { m_Field = Ge.m_Field; m_Degree = Ge.m_Degree; m_polynomial = new GF2Polynomial(Ge.m_polynomial); }
/// <summary> /// Solves the quadratic equation <c>z^2 + z = this</c> if such a solution exists. /// <para>This method returns one of the two possible solutions. /// The other solution is <c>z + 1</c>. Use z.Increase() to compute this solution.</para> /// </summary> /// /// <returns>Returns a GF2nPolynomialElement representing one z satisfying the equation <c>z^2 + z = this</c></returns> public override GF2nElement SolveQuadraticEquation() { if (IsZero()) return Zero((GF2nPolynomialField)mField); if ((mDegree & 1) == 1) return HalfTrace(); // TODO this can be sped-up by precomputation of p and w's GF2nPolynomialElement z, w; do { // step 1. GF2nPolynomialElement p = new GF2nPolynomialElement( (GF2nPolynomialField)mField, new Random()); // step 2. z = Zero((GF2nPolynomialField)mField); w = (GF2nPolynomialElement)p.Clone(); // step 3. for (int i = 1; i < mDegree; i++) { // compute z = z^2 + w^2 * this // and w = w^2 + p z.SquareThis(); w.SquareThis(); z.AddToThis(w.Multiply(this)); w.AddToThis(p); } } while (w.IsZero()); // step 4. if (!Equals(z.Square().Add(z))) throw new Exception(); // step 5. return z; }
/// <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 InvertSquare() { GF2nPolynomialElement n; GF2nPolynomialElement u; int i, j, k, b; if (IsZero()) throw new ArithmeticException(); // b = (n-1) b = mField.Degree - 1; // n = a n = new GF2nPolynomialElement(this); n.polynomial.ExpandN((mDegree << 1) + 32); // increase performance n.polynomial.ReduceN(); // k = 1 k = 1; // for i = (r-1) downto 0 do, r=bitlength(b) for (i = BigMath.FloorLog(b) - 1; i >= 0; i--) { // u = n u = new GF2nPolynomialElement(n); // for j = 1 to k do for (j = 1; j <= k; j++) u.SquareThisPreCalc(); // u = u^2 // n = nu n.MultiplyThisBy(u); // k = 2k k <<= 1; // if b(i)==1 if ((b & _bitMask[i]) != 0) { // n = n^2 * b n.SquareThisPreCalc(); n.MultiplyThisBy(this); // k = k+1 k += 1; } } // outpur n^2 n.SquareThisPreCalc(); return n; }
/// <summary> /// Increase the element by one /// </summary> /// /// <returns>Returns <c>this</c> + 'one'</returns> public override GF2nElement Increase() { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.IncreaseThis(); return result; }
/// <summary> /// Compute the sum of this element and <c>Addend</c>. /// </summary> /// /// <param name="Addend">The addend</param> /// /// <returns>Returns <c>this + other</c></returns> public override IGFElement Add(IGFElement Addend) { GF2nPolynomialElement result = new GF2nPolynomialElement(this); result.AddToThis(Addend); return result; }
/// <summary> /// Computes the change-of-basis matrix for basis conversion according to 1363. /// The result is stored in the lists fields and matrices. /// </summary> /// /// <param name="B1">The GF2nField to convert to</param> public override void ComputeCOBMatrix(GF2nField B1) { // we are in B0 here! if (DegreeN != B1.Degree) throw new ArgumentException("GF2nPolynomialField.computeCOBMatrix: B1 has a different degree and thus cannot be coverted to!"); if (B1 is GF2nONBField) { // speedup (calculation is done in PolynomialElements instead of ONB) B1.ComputeCOBMatrix(this); return; } int i, j; GF2nElement[] gamma; GF2nElement u; GF2Polynomial[] COBMatrix = new GF2Polynomial[DegreeN]; for (i = 0; i < DegreeN; i++) COBMatrix[i] = new GF2Polynomial(DegreeN); // find Random Root do { // u is in representation according to B1 u = B1.RandomRoot(FieldPoly); } while (u.IsZero()); // build gamma matrix by multiplying by u if (u is GF2nONBElement) { gamma = new GF2nONBElement[DegreeN]; gamma[DegreeN - 1] = GF2nONBElement.One((GF2nONBField)B1); } else { gamma = new GF2nPolynomialElement[DegreeN]; gamma[DegreeN - 1] = GF2nPolynomialElement.One((GF2nPolynomialField)B1); } gamma[DegreeN - 2] = u; for (i = DegreeN - 3; i >= 0; i--) gamma[i] = (GF2nElement)gamma[i + 1].Multiply(u); if (B1 is GF2nONBField) { // convert horizontal gamma matrix by vertical Bitstrings for (i = 0; i < DegreeN; i++) { for (j = 0; j < DegreeN; j++) { // TODO remember: ONB treats its Bits in reverse order !!! if (gamma[i].TestBit(DegreeN - j - 1)) COBMatrix[DegreeN - j - 1].SetBit(DegreeN - i - 1); } } } else { // convert horizontal gamma matrix by vertical Bitstrings for (i = 0; i < DegreeN; i++) { for (j = 0; j < DegreeN; j++) { if (gamma[i].TestBit(j)) COBMatrix[DegreeN - j - 1].SetBit(DegreeN - i - 1); } } } // store field and matrix for further use Fields.Add(B1); Matrices.Add(COBMatrix); // store field and inverse matrix for further use in B1 B1.Fields.Add(this); B1.Matrices.Add(InvertMatrix(COBMatrix)); }
/// <summary> /// Computes the change-of-basis matrix for basis conversion according to 1363. /// The result is stored in the lists fields and matrices. /// </summary> /// /// <param name="B1">The GF2nField to convert to</param> public override void ComputeCOBMatrix(GF2nField B1) { // we are in B0 here! if (DegreeN != B1.Degree) { throw new ArgumentException("GF2nPolynomialField.computeCOBMatrix: B1 has a different degree and thus cannot be coverted to!"); } if (B1 is GF2nONBField) { // speedup (calculation is done in PolynomialElements instead of ONB) B1.ComputeCOBMatrix(this); return; } int i, j; GF2nElement[] gamma; GF2nElement u; GF2Polynomial[] COBMatrix = new GF2Polynomial[DegreeN]; for (i = 0; i < DegreeN; i++) { COBMatrix[i] = new GF2Polynomial(DegreeN); } // find Random Root do { // u is in representation according to B1 u = B1.RandomRoot(FieldPoly); }while (u.IsZero()); // build gamma matrix by multiplying by u if (u is GF2nONBElement) { gamma = new GF2nONBElement[DegreeN]; gamma[DegreeN - 1] = GF2nONBElement.One((GF2nONBField)B1); } else { gamma = new GF2nPolynomialElement[DegreeN]; gamma[DegreeN - 1] = GF2nPolynomialElement.One((GF2nPolynomialField)B1); } gamma[DegreeN - 2] = u; for (i = DegreeN - 3; i >= 0; i--) { gamma[i] = (GF2nElement)gamma[i + 1].Multiply(u); } if (B1 is GF2nONBField) { // convert horizontal gamma matrix by vertical Bitstrings for (i = 0; i < DegreeN; i++) { for (j = 0; j < DegreeN; j++) { // TODO remember: ONB treats its Bits in reverse order !!! if (gamma[i].TestBit(DegreeN - j - 1)) { COBMatrix[DegreeN - j - 1].SetBit(DegreeN - i - 1); } } } } else { // convert horizontal gamma matrix by vertical Bitstrings for (i = 0; i < DegreeN; i++) { for (j = 0; j < DegreeN; j++) { if (gamma[i].TestBit(j)) { COBMatrix[DegreeN - j - 1].SetBit(DegreeN - i - 1); } } } } // store field and matrix for further use Fields.Add(B1); Matrices.Add(COBMatrix); // store field and inverse matrix for further use in B1 B1.Fields.Add(this); B1.Matrices.Add(InvertMatrix(COBMatrix)); }
/// <summary> /// Calculates <c>this</c> to the power of <c>K</c> and returns the result in a new GF2nPolynomialElement /// </summary> /// /// <param name="K">The power</param> /// /// <returns>Returns <c>this</c>^<c>K</c> in a new GF2nPolynomialElement</returns> public GF2nPolynomialElement Power(int K) { if (K == 1) return new GF2nPolynomialElement(this); GF2nPolynomialElement result = GF2nPolynomialElement.One((GF2nPolynomialField)mField); if (K == 0) return result; GF2nPolynomialElement x = new GF2nPolynomialElement(this); x.polynomial.ExpandN((x.mDegree << 1) + 32); // increase performance x.polynomial.ReduceN(); for (int i = 0; i < mDegree; i++) { if ((K & (1 << i)) != 0) result.MultiplyThisBy(x); x.Square(); } 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> /// Computes the change-of-basis matrix for basis conversion according to 1363. /// The result is stored in the lists fields and matrices. /// </summary> /// /// <param name="B1">The GF2nField to convert to</param> public override void ComputeCOBMatrix(GF2nField B1) { // we are in B0 here! if (DegreeN != B1.Degree) throw new ArgumentException("GF2nField.computeCOBMatrix: B1 has a different degree and thus cannot be coverted to!"); int i, j; GF2nElement[] gamma; GF2nElement u; GF2Polynomial[] COBMatrix = new GF2Polynomial[DegreeN]; for (i = 0; i < DegreeN; i++) COBMatrix[i] = new GF2Polynomial(DegreeN); // find Random Root do { // u is in representation according to B1 u = B1.RandomRoot(FieldPoly); } while (u.IsZero()); gamma = new GF2nPolynomialElement[DegreeN]; // build gamma matrix by squaring gamma[0] = (GF2nElement)u.Clone(); for (i = 1; i < DegreeN; i++) gamma[i] = gamma[i - 1].Square(); // convert horizontal gamma matrix by vertical Bitstrings for (i = 0; i < DegreeN; i++) { for (j = 0; j < DegreeN; j++) { if (gamma[i].TestBit(j)) COBMatrix[DegreeN - j - 1].SetBit(DegreeN - i - 1); } } Fields.Add(B1); Matrices.Add(COBMatrix); B1.Fields.Add(this); B1.Matrices.Add(InvertMatrix(COBMatrix)); }