private static void gftab(ref Polynomial.PLY ply, ref List <string> output, int q_init) //****************************************************************************80 // // Purpose: // // GFTAB computes and writes data for a particular field size Q_INIT. // // Discussion: // // A polynomial with coefficients A(*) in the field of order Q // can also be stored in an integer I, with // // I = AN*Q**N + ... + A0. // // Polynomials stored as arrays have the // coefficient of degree n in POLY(N), and the degree of the // polynomial in POLY(-1). The parameter DEG is just to remind // us of this last fact. A polynomial which is identically 0 // is given degree -1. // // IRRPLY holds irreducible polynomials for constructing // prime-power fields. IRRPLY(-2,I) says which field this // row is used for, and then the rest of the row is a // polynomial (with the degree in IRRPLY(-1,I) as usual). // The chosen irreducible poly is copied into MODPLY for use. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 06 September 2007 // // Author: // // Paul Bratley, Bennet Fox, Harald Niederreiter. // C++ version by John Burkardt. // // Reference: // // Paul Bratley, Bennett Fox, Harald Niederreiter, // Algorithm 738: // Programs to Generate Niederreiter's Low-Discrepancy Sequences, // ACM Transactions on Mathematical Software, // Volume 20, Number 4, 1994, pages 494-495. // // Parameters: // // Input, ofstream &OUTPUT, a reference to the output stream. // // Input, int Q_INIT, the order of the field for which the // addition and multiplication tables are needed. // { int[,] gfadd = new int [Polynomial.PLY.Q_MAX, Polynomial.PLY.Q_MAX]; int[,] gfmul = new int [Polynomial.PLY.Q_MAX, Polynomial.PLY.Q_MAX]; int[,] irrply = { { 4, 2, 1, 1, 1, 0, 0, 0 }, { 8, 3, 1, 1, 0, 1, 0, 0 }, { 9, 2, 1, 0, 1, 0, 0, 0 }, { 16, 4, 1, 1, 0, 0, 1, 0 }, { 25, 2, 2, 0, 1, 0, 0, 0 }, { 27, 3, 1, 2, 0, 1, 0, 0 }, { 32, 5, 1, 0, 1, 0, 0, 1 }, { 49, 2, 1, 0, 1, 0, 0, 0 } }; int j; int[] modply = new int[Polynomial.PLY.DEG_MAX + 2]; if (q_init is <= 1 or > Polynomial.PLY.Q_MAX) { Console.WriteLine(""); Console.WriteLine("GFTAB - Fatal error!"); Console.WriteLine(" Bad value of Q_INIT."); return; } ply.P = typeMethods.i4_characteristic(q_init); // // If QIN is not a prime power, we are not interested. // if (ply.P == 0 || ply.P == q_init) { return; } Console.WriteLine(" GFTAB computing table for Q = " + q_init + " with characteristic P = " + ply.P + "."); // // Otherwise, we set up the elements of the common /FIELD/ // ready to do arithmetic mod P, the characteristic of Q_INIT. // setfld(ref ply, q_init); // // Next find a suitable irreducible polynomial and copy it to array MODPLY. // int i = 1; while (irrply[i - 1, -2 + 2] != q_init) { i += 1; } for (j = -1; j <= irrply[i - 1, -1 + 2]; j++) { modply[j + 1] = irrply[i - 1, j + 2]; } for (j = irrply[i - 1, -1 + 2] + 1; j <= Polynomial.PLY.DEG_MAX; j++) { modply[j + 1] = 0; } // // Deal with the trivial cases. // for (i = 0; i < q_init; i++) { gfadd[i, 0] = i; gfadd[0, i] = i; gfmul[i, 0] = 0; gfmul[0, i] = 0; } for (i = 1; i < q_init; i++) { gfmul[i, 1] = i; gfmul[1, i] = i; } // // Now deal with the rest. Each integer from 1 to Q-1 // is treated as a polynomial with coefficients handled mod P. // Multiplication of polynomials is mod MODPLY. // int[] pl = new int[Polynomial.PLY.DEG_MAX + 2]; for (i = 1; i < q_init; i++) { int[] pi = Polynomial.itop(i, ply.P); for (j = 1; j <= i; j++) { int[] pj = Polynomial.itop(j, ply.P); int[] pk = Polynomial.plyadd(ref ply, pi, pj); gfadd[i, j] = Polynomial.ptoi(pk, ply.P); gfadd[j, i] = gfadd[i, j]; switch (i) { case > 1 when 1 < j: pk = Polynomial.plymul(ref ply, pi, pj); Polynomial.plydiv(ref ply, pk, modply, ref pj, ref pl); gfmul[i, j] = Polynomial.ptoi(pl, ply.P); gfmul[j, i] = gfmul[i, j]; break; } } } // // Write out the tables. // output.Add(" " + q_init + ""); for (i = 0; i < q_init; i++) { string cout = ""; for (j = 0; j < q_init; j++) { cout += " " + gfadd[i, j]; } output.Add(cout); } for (i = 0; i < q_init; i++) { string cout = ""; for (j = 0; j < q_init; j++) { cout += " " + gfmul[i, j]; } output.Add(cout); } }
private static void setfld(ref Polynomial.PLY ply, int q_init) //****************************************************************************80 // // Purpose: // // SETFLD sets up the arithmetic tables for a finite field. // // Discussion: // // This subroutine sets up addition, multiplication, and // subtraction tables for the finite field of order QIN. // // A polynomial with coefficients A(*) in the field of order Q // can also be stored in an integer I, with // // I = AN*Q**N + ... + A0. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 06 September 2007 // // Author: // // Paul Bratley, Bennet Fox, Harald Niederreiter. // C++ version by John Burkardt. // // Reference: // // Paul Bratley, Bennett Fox, Harald Niederreiter, // Algorithm 738: // Programs to Generate Niederreiter's Low-Discrepancy Sequences, // ACM Transactions on Mathematical Software, // Volume 20, Number 4, 1994, pages 494-495. // // Parameters: // // Input, int Q_INIT, the order of the field. // { int i; int j; if (q_init is <= 1 or > Polynomial.PLY.Q_MAX) { Console.WriteLine(""); Console.WriteLine("SETFLD - Fatal error!"); Console.WriteLine(" Bad value of Q = " + q_init + ""); return; } ply.Q = q_init; ply.P = typeMethods.i4_characteristic(ply.Q); switch (ply.P) { case 0: Console.WriteLine(""); Console.WriteLine("SETFLD - Fatal error!"); Console.WriteLine(" There is no field of order Q = " + ply.Q + ""); return; } // // Set up to handle a field of prime or prime-power order. // Calculate the addition and multiplication tables. // for (i = 0; i < ply.P; i++) { for (j = 0; j < ply.P; j++) { ply.add[i, j] = (i + j) % ply.P; } } for (i = 0; i < ply.P; i++) { for (j = 0; j < ply.P; j++) { ply.mul[i, j] = i * j % ply.P; } } // // Use the addition table to set the subtraction table. // for (i = 0; i < ply.P; i++) { for (j = 0; j < ply.P; j++) { ply.sub[ply.add[i, j], i] = j; } } }
private static void irred(ref Polynomial.PLY ply, ref List <string> output, int q_init) //****************************************************************************80 // // Purpose: // // IRRED computes and writes out a set of irreducible polynomials. // // Discussion: // // We find the irreducible polynomials using a sieve. // // Polynomials stored as arrays have the coefficient of degree n in // POLY(N), and the degree of the polynomial in POLY(-1). The parameter // DEG is just to remind us of this last fact. A polynomial which is // identically 0 is given degree -1. // // Note that the value of NPOL controls the number of polynomials // computed, and hence the maximum spatial dimension for the // subsequence Niederreiter sequences, JVB, 07 June 2010. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 07 June 2010 // // Author: // // Original FORTRAN77 version by Paul Bratley, Bennett Fox, // Harald Niederreiter. // C++ version by John Burkardt. // // Reference: // // Paul Bratley, Bennett Fox, Harald Niederreiter, // Algorithm 738: // Programs to Generate Niederreiter's Low-Discrepancy Sequences, // ACM Transactions on Mathematical Software, // Volume 20, Number 4, 1994, pages 494-495. // // Parameters: // // Input, ofstream &OUTPUT, a reference to the output stream. // // Input, int Q_INIT, the order of the field. // // Local Parameters: // // Local, int SIEVE_MAX, the size of the sieve. // // Array MONPOL holds monic polynomials. // // Array SIEVE says whether the polynomial is still OK. // // Local, int NPOLS, the number of irreducible polynomials to // be calculated for a given field. // { const int SIEVE_MAX = 400; int[] monpol = new int[SIEVE_MAX]; int n; const int npols = 50; bool[] sieve = new bool[SIEVE_MAX]; if (q_init is <= 1 or > Polynomial.PLY.Q_MAX) { Console.WriteLine(""); Console.WriteLine("IRRED - Fatal error!"); Console.WriteLine(" Bad value of Q = " + q_init + ""); return; } ply.P = typeMethods.i4_characteristic(q_init); switch (ply.P) { // // If no field of order Q_INIT exists, there is nothing to do. // case <= 0: return; } Console.WriteLine(" IRRED setting up case for Q = " + q_init + ""); // // Set up the field arithmetic tables. // (Note that SETFLD sets Q = q_init!) // setfld(ref ply, q_init); // // Set up the sieve containing only monic polynomials. // int i = 0; int j = 1; int k = ply.Q; for (n = 1; n <= SIEVE_MAX; n++) { i += 1; if (i == j) { i = k; j = 2 * k; k = ply.Q * k; } monpol[n - 1] = i; sieve[n - 1] = true; } // // Write out the irreducible polynomials as they are found. // n = 0; output.Add(ply.Q.ToString(CultureInfo.InvariantCulture).PadLeft(3) + ""); for (i = 1; i <= SIEVE_MAX; i++) { switch (sieve[i - 1]) { case true: { int[] pi = Polynomial.itop(ref ply, monpol[i - 1]); k = pi[0]; string cout = k.ToString(CultureInfo.InvariantCulture).PadLeft(3); int l; for (l = 0; l <= k; l++) { cout += pi[l + 1].ToString(CultureInfo.InvariantCulture).PadLeft(3); } output.Add(cout); n += 1; if (n == npols) { return; } for (j = i; j <= SIEVE_MAX; j++) { int[] pj = Polynomial.itop(ref ply, monpol[j - 1]); int[] pk = Polynomial.plymul(ref ply, pi, pj); k = find(Polynomial.ptoi(ref ply, pk), monpol, j, SIEVE_MAX); if (k != -1) { sieve[k - 1] = false; } } break; } } } Console.WriteLine(""); Console.WriteLine("IRRED - Warning!"); Console.WriteLine(" The sieve size SIEVE_MAX is too small."); Console.WriteLine(" Number of irreducible polynomials found: " + n + ""); Console.WriteLine(" Number needed: " + npols + ""); }