private void MultRowWithElementThis(int[] Row, int Element) { for (int i = Row.Length - 1; i >= 0; i--) { Row[i] = FieldG.Multiply(Row[i], Element); } }
/// <summary> /// Evaluate this polynomial <c>p</c> at a value <c>e</c> (in <c>GF(2^m)</c>) with the Horner scheme /// </summary> /// /// <param name="E">The element of the finite field GF(2^m)</param> /// /// <returns>Returns <c>this(e)</c></returns> public int EvaluateAt(int E) { int result = _coefficients[_degree]; for (int i = _degree - 1; i >= 0; i--) { result = _field.Multiply(result, E) ^ _coefficients[i]; } return(result); }
/// <summary> /// Compute the result of the division of two polynomials over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">he first polynomial</param> /// <param name="F">he second polynomial</param> /// /// <returns>Returns <c>int[][] {q,r}</c>, where <c>a = q*f+r</c> and <c>deg(r) < deg(f)</c></returns> private static int[][] Divide(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); int da = ComputeDegree(A) + 1; if (df == -1) { throw new ArithmeticException("Division by zero."); } int[][] result = new int[2][]; result[0] = new int[1]; result[1] = new int[da]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); result[0][0] = 0; Array.Copy(A, 0, result[1], 0, result[1].Length); while (df <= ComputeDegree(result[1])) { int[] q; int[] coeff = new int[1]; coeff[0] = GF2.Multiply(HeadCoefficient(result[1]), hc); q = MultWithElement(F, coeff[0], GF2); int n = ComputeDegree(result[1]) - df; q = MultWithMonomial(q, n); coeff = MultWithMonomial(coeff, n); result[0] = Add(coeff, result[0], GF2); result[1] = Add(q, result[1], GF2); } return(result); }
/// <summary> /// Reduce a polynomial modulo another polynomial /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="F">The reduction polynomial</param> /// /// <returns>Returns <c>a mod f</c></returns> private static int[] Mod(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); if (df == -1) { throw new ArithmeticException("Division by zero"); } int[] result = new int[A.Length]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); Array.Copy(A, 0, result, 0, result.Length); while (df <= ComputeDegree(result)) { int[] q; int coeff = GF2.Multiply(HeadCoefficient(result), hc); q = MultWithMonomial(F, ComputeDegree(result) - df); q = MultWithElement(q, coeff, GF2); result = Add(q, result, GF2); } return(result); }
/// <summary> /// Compute the product of a polynomial a with an element from the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="Element">An element of the finite field GF(2^m)</param> /// /// <returns>Return <c>a * element</c></returns> private static int[] MultWithElement(int[] A, int Element, GF2mField GF2) { int degree = ComputeDegree(A); if (degree == -1 || Element == 0) { return(new int[1]); } if (Element == 1) { return(IntUtils.DeepCopy(A)); } int[] result = new int[degree + 1]; for (int i = degree; i >= 0; i--) { result[i] = GF2.Multiply(A[i], Element); } return(result); }
/// <summary> /// Construct the check matrix of a Goppa code in canonical form from the irreducible Goppa polynomial over the finite field <c>GF(2^m)</c>. /// </summary> /// /// <param name="Field">The finite field</param> /// <param name="Gp">The irreducible Goppa polynomial</param> /// /// <returns>The new GF2Matrix</returns> public static GF2Matrix CreateCanonicalCheckMatrix(GF2mField Field, PolynomialGF2mSmallM Gp) { int m = Field.Degree; int n = 1 << m; int t = Gp.Degree; // create matrix H over GF(2^m) int[][] hArray = ArrayUtils.CreateJagged <int[][]>(t, n); // create matrix YZ int[][] yz = ArrayUtils.CreateJagged <int[][]>(t, n); if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => yz[0][j] = Field.Inverse(Gp.EvaluateAt(j))); } else { // here j is used as index and as element of field GF(2^m) for (int j = 0; j < n; j++) { yz[0][j] = Field.Inverse(Gp.EvaluateAt(j)); } } for (int i = 1; i < t; i++) { // here j is used as index and as element of field GF(2^m) if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { yz[i][j] = Field.Multiply(yz[i - 1][j], j); }); } else { for (int j = 0; j < n; j++) { yz[i][j] = Field.Multiply(yz[i - 1][j], j); } } } // create matrix H = XYZ for (int i = 0; i < t; i++) { if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { for (int k = 0; k <= i; k++) { hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); } }); } else { for (int j = 0; j < n; j++) { for (int k = 0; k <= i; k++) { hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); } } } } // convert to matrix over GF(2) int[][] result = ArrayUtils.CreateJagged <int[][]>(t * m, IntUtils.URShift((n + 31), 5)); if (ParallelUtils.IsParallel) { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; Parallel.For(0, m, u => { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } }); } } } else { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; for (int u = 0; u < m; u++) { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } } } } } return(new GF2Matrix(n, result)); }
/// <summary> /// Reduce a polynomial modulo another polynomial /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="F">The reduction polynomial</param> /// /// <returns>Returns <c>a mod f</c></returns> private static int[] Mod(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); if (df == -1) throw new ArithmeticException("Division by zero"); int[] result = new int[A.Length]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); Array.Copy(A, 0, result, 0, result.Length); while (df <= ComputeDegree(result)) { int[] q; int coeff = GF2.Multiply(HeadCoefficient(result), hc); q = MultWithMonomial(F, ComputeDegree(result) - df); q = MultWithElement(q, coeff, GF2); result = Add(q, result, GF2); } return result; }
/// <summary> /// Compute the result of the division of two polynomials over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">he first polynomial</param> /// <param name="F">he second polynomial</param> /// /// <returns>Returns <c>int[][] {q,r}</c>, where <c>a = q*f+r</c> and <c>deg(r) < deg(f)</c></returns> private static int[][] Divide(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); int da = ComputeDegree(A) + 1; if (df == -1) throw new ArithmeticException("Division by zero."); int[][] result = new int[2][]; result[0] = new int[1]; result[1] = new int[da]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); result[0][0] = 0; Array.Copy(A, 0, result[1], 0, result[1].Length); while (df <= ComputeDegree(result[1])) { int[] q; int[] coeff = new int[1]; coeff[0] = GF2.Multiply(HeadCoefficient(result[1]), hc); q = MultWithElement(F, coeff[0], GF2); int n = ComputeDegree(result[1]) - df; q = MultWithMonomial(q, n); coeff = MultWithMonomial(coeff, n); result[0] = Add(coeff, result[0], GF2); result[1] = Add(q, result[1], GF2); } return result; }
/// <summary> /// Compute the product of a polynomial a with an element from the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="Element">An element of the finite field GF(2^m)</param> /// /// <returns>Return <c>a * element</c></returns> private static int[] MultWithElement(int[] A, int Element, GF2mField GF2) { int degree = ComputeDegree(A); if (degree == -1 || Element == 0) return new int[1]; if (Element == 1) return IntUtils.DeepCopy(A); int[] result = new int[degree + 1]; for (int i = degree; i >= 0; i--) result[i] = GF2.Multiply(A[i], Element); return result; }
/// <summary> /// Construct the check matrix of a Goppa code in canonical form from the irreducible Goppa polynomial over the finite field <c>GF(2^m)</c>. /// </summary> /// /// <param name="Field">The finite field</param> /// <param name="Gp">The irreducible Goppa polynomial</param> /// /// <returns>The new GF2Matrix</returns> public static GF2Matrix CreateCanonicalCheckMatrix(GF2mField Field, PolynomialGF2mSmallM Gp) { int m = Field.Degree; int n = 1 << m; int t = Gp.Degree; // create matrix H over GF(2^m) int[][] hArray = ArrayUtils.CreateJagged<int[][]>(t, n); // create matrix YZ int[][] yz = ArrayUtils.CreateJagged<int[][]>(t, n); if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => yz[0][j] = Field.Inverse(Gp.EvaluateAt(j))); } else { // here j is used as index and as element of field GF(2^m) for (int j = 0; j < n; j++) yz[0][j] = Field.Inverse(Gp.EvaluateAt(j)); } for (int i = 1; i < t; i++) { // here j is used as index and as element of field GF(2^m) if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { yz[i][j] = Field.Multiply(yz[i - 1][j], j); }); } else { for (int j = 0; j < n; j++) yz[i][j] = Field.Multiply(yz[i - 1][j], j); } } // create matrix H = XYZ for (int i = 0; i < t; i++) { if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { for (int k = 0; k <= i; k++) hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); }); } else { for (int j = 0; j < n; j++) { for (int k = 0; k <= i; k++) hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); } } } // convert to matrix over GF(2) int[][] result = ArrayUtils.CreateJagged<int[][]>(t * m, IntUtils.URShift((n + 31), 5)); if (ParallelUtils.IsParallel) { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; Parallel.For(0, m, u => { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } }); } } } else { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; for (int u = 0; u < m; u++) { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } } } } } return new GF2Matrix(n, result); }