public static void calcv2(ref NiederReiter2CalcData data, int maxv, int px_deg, int[] px, int[,] add, int[,] mul, int[,] sub, ref int b_deg, int[] b, int[] v) //****************************************************************************80 // // Purpose: // // CALCV2 calculates the value of the constants V(J,R). // // Discussion: // // This program calculates the values of the constants V(J,R) as // described in the reference (BFN) section 3.3. It is called from CALCC2. // // Polynomials stored as arrays have the coefficient of degree N // in POLY(N). // // A polynomial which is identically 0 is given degree -1. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 March 2003 // // 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, pages 494-495, 1994. // // Parameters: // // Input, int MAXV, the dimension of the array V. // // Input, int PX_DEG, the degree of PX. // // Input, int PX[MAXDEG+1], the appropriate irreducible polynomial // for the dimension currently being considered. // // Input, int ADD[2][2], MUL[2][2], SUB[2][2], the addition, multiplication, // and subtraction tables, mod 2. // // Input/output, int *B_DEG, the degree of the polynomial B. // // Input/output, int B[MAXDEG+1]. On input, B is the polynomial // defined in section 2.3 of BFN. The degree of B implicitly defines // the parameter J of section 3.3, by degree(B) = E*(J-1). On output, // B has been multiplied by PX, so its degree is now E * J. // // Output, int V[MAXV+1], the computed V array. // // Local Parameters: // // Local, int ARBIT, indicates where the user can place // an arbitrary element of the field of order 2. This means // 0 <= ARBIT < 2. // // Local, int BIGM, is the M used in section 3.3. // It differs from the [little] m used in section 2.3, // denoted here by M. // // Local, int NONZER, shows where the user must put an arbitrary // non-zero element of the field. For the code, this means // 0 < NONZER < 2. // { int[] h = new int[MAXDEG + 1]; int i; int r; int term; // // The polynomial H is PX**(J-1), which is the value of B on arrival. // // In section 3.3, the values of Hi are defined with a minus sign: // don't forget this if you use them later! // int h_deg = b_deg; for (i = 0; i <= h_deg; i++) { h[i] = b[i]; } // // Multiply B by PX so B becomes PX**J. // In section 2.3, the values of Bi are defined with a minus sign: // don't forget this if you use them later! // int pb_deg = b_deg; plymul2(add, mul, px_deg, px, pb_deg, b, ref pb_deg, b); b_deg = pb_deg; int m = b_deg; // // Now choose a value of Kj as defined in section 3.3. // We must have 0 <= Kj < E*J = M. // The limit condition on Kj does not seem very relevant // in this program. // // // Choose values of V in accordance with the conditions in section 3.3. // for (r = 0; r < h_deg; r++) { v[r] = 0; } v[h_deg] = 1; if (h_deg < h_deg) { term = sub[0, h[h_deg]]; for (r = h_deg + 1; r <= h_deg - 1; r++) { v[r] = NiederReiter2CalcData.arbit; // // Check the condition of section 3.3, // remembering that the H's have the opposite sign. // term = sub[term, mul[h[r], v[r]]]; } // // Now V(BIGM) is anything but TERM. // v[h_deg] = add[NiederReiter2CalcData.nonzer, term]; for (r = h_deg + 1; r <= m - 1; r++) { v[r] = NiederReiter2CalcData.arbit; } } else { for (r = h_deg + 1; r <= m - 1; r++) { v[r] = NiederReiter2CalcData.arbit; } } // // Calculate the remaining V's using the recursion of section 2.3, // remembering that the B's have the opposite sign. // for (r = 0; r <= maxv - m; r++) { term = 0; for (i = 0; i <= m - 1; i++) { term = sub[term, mul[b[i], v[r + i]]]; } v[r + m] = term; } }
public static void calcc2(ref NiederReiter2CalcData data, int dim_num, ref int[,] cj) //****************************************************************************80 // // Purpose: // // CALCC2 computes values of the constants C(I,J,R). // // Discussion: // // This program calculates the values of the constants C(I,J,R). // // As far as possible, Niederreiter's notation is used. // // For each value of I, we first calculate all the corresponding // values of C. These are held in the array CI. All these // values are either 0 or 1. // // Next we pack the values into the // array CJ, in such a way that CJ(I,R) holds the values of C // for the indicated values of I and R and for every value of // J from 1 to NBITS. The most significant bit of CJ(I,R) // (not counting the sign bit) is C(I,1,R) and the least // significant bit is C(I,NBITS,R). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 29 March 2003 // // Author: // // Original FORTRAN77 version by Paul Bratley, Bennett Fox, Harald Niederreiter. // C++ version by John Burkardt. // // Reference: // // R Lidl, Harald Niederreiter, // Finite Fields, // Cambridge University Press, 1984, page 553. // // Harald Niederreiter, // Low-discrepancy and low-dispersion sequences, // Journal of Number Theory, // Volume 30, 1988, pages 51-70. // // Parameters: // // Input, int DIM_NUM, the dimension of the sequence to be generated. // // Output, int CJ[DIM_MAX][NBITS], the packed values of // Niederreiter's C(I,J,R) // // Local Parameters: // // Local, int MAXE; we need DIM_MAX irreducible polynomials over Z2. // MAXE is the highest degree among these. // // Local, int MAXV, the maximum possible index used in V. // { const int MAXE = 6; int[,] add = new int [2, 2]; int[] b = new int[MAXDEG + 1]; int[,] ci = new int[NBITS, NBITS]; int i; int[,] irred = { { 0, 1, 0, 0, 0, 0, 0 }, { 1, 1, 0, 0, 0, 0, 0 }, { 1, 1, 1, 0, 0, 0, 0 }, { 1, 1, 0, 1, 0, 0, 0 }, { 1, 0, 1, 1, 0, 0, 0 }, { 1, 1, 0, 0, 1, 0, 0 }, { 1, 0, 0, 1, 1, 0, 0 }, { 1, 1, 1, 1, 1, 0, 0 }, { 1, 0, 1, 0, 0, 1, 0 }, { 1, 0, 0, 1, 0, 1, 0 }, { 1, 1, 1, 1, 0, 1, 0 }, { 1, 1, 1, 0, 1, 1, 0 }, { 1, 1, 0, 1, 1, 1, 0 }, { 1, 0, 1, 1, 1, 1, 0 }, { 1, 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 1, 0, 0, 1 }, { 1, 1, 1, 0, 1, 0, 1 }, { 1, 1, 0, 1, 1, 0, 1 }, { 1, 0, 0, 0, 0, 1, 1 }, { 1, 1, 1, 0, 0, 1, 1 } } ; int[] irred_deg = { 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 } ; int maxv = NBITS + MAXE; int[,] mul = new int[2, 2]; int[] px = new int[MAXDEG + 1]; int[,] sub = new int[2, 2]; int[] v = new int[NBITS + MAXE + 1]; // // Prepare to work in Z2. // setfld2(add, mul, sub); for (i = 0; i < dim_num; i++) { // // For each dimension, we need to calculate powers of an // appropriate irreducible polynomial: see Niederreiter // page 65, just below equation (19). // // Copy the appropriate irreducible polynomial into PX, // and its degree into E. Set polynomial B = PX ** 0 = 1. // M is the degree of B. Subsequently B will hold higher // powers of PX. // int e = irred_deg[i]; int px_deg = irred_deg[i]; int j; for (j = 0; j <= px_deg; j++) { px[j] = irred[i, j]; } int b_deg = 0; b[0] = 1; // // Niederreiter (page 56, after equation (7), defines two // variables Q and U. We do not need Q explicitly, but we do need U. // int u = 0; int r; for (j = 0; j < NBITS; j++) { switch (u) { // // If U = 0, we need to set B to the next power of PX // and recalculate V. This is done by subroutine CALCV. // case 0: calcv2(ref data, maxv, px_deg, px, add, mul, sub, ref b_deg, b, v); break; } // // Now C is obtained from V. Niederreiter obtains A from V (page 65, // near the bottom), and then gets C from A (page 56, equation (7)). // However this can be done in one step. Here CI(J,R) corresponds to // Niederreiter's C(I,J,R). // for (r = 0; r < NBITS; r++) { ci[j, r] = v[r + u]; } // // Increment U. // // If U = E, then U = 0 and in Niederreiter's // paper Q = Q + 1. Here, however, Q is not used explicitly. // u += 1; if (u == e) { u = 0; } } // // The array CI now holds the values of C(I,J,R) for this value // of I. We pack them into array CJ so that CJ(I,R) holds all // the values of C(I,J,R) for J from 1 to NBITS. // for (r = 0; r < NBITS; r++) { int term = 0; for (j = 0; j < NBITS; j++) { term = 2 * term + ci[j, r]; } cj[i, r] = term; } } }