3 /* Implement Niederreiter base 2 generator.
5 * Bratley, Fox, Niederreiter, ACM Trans. Model. Comp. Sim. 2, 195 (1992)
8 #include <gsl/gsl_qrng.h>
11 #define NIED2_CHARACTERISTIC 2
14 #define NIED2_MAX_DIMENSION 12
15 #define NIED2_MAX_PRIM_DEGREE 5
16 #define NIED2_MAX_DEGREE 50
18 #define NIED2_BIT_COUNT 30
19 #define NIED2_NBITS (NIED2_BIT_COUNT+1)
21 #define MAXV (NIED2_NBITS + NIED2_MAX_DEGREE)
23 /* Z_2 field operations */
24 #define NIED2_ADD(x,y) (((x)+(y))%2)
25 #define NIED2_MUL(x,y) (((x)*(y))%2)
26 #define NIED2_SUB(x,y) NIED2_ADD((x),(y))
29 static size_t nied2_state_size(unsigned int dimension);
30 static int nied2_init(void * state, unsigned int dimension);
31 static int nied2_get(void * state, unsigned int dimension, double * v);
34 static const gsl_qrng_type nied2_type =
36 "niederreiter-base-2",
43 const gsl_qrng_type * gsl_qrng_niederreiter_2 = &nied2_type;
45 /* primitive polynomials in binary encoding */
46 static const int primitive_poly[NIED2_MAX_DIMENSION+1][NIED2_MAX_PRIM_DEGREE+1] =
48 { 1, 0, 0, 0, 0, 0 }, /* 1 */
49 { 0, 1, 0, 0, 0, 0 }, /* x */
50 { 1, 1, 0, 0, 0, 0 }, /* 1 + x */
51 { 1, 1, 1, 0, 0, 0 }, /* 1 + x + x^2 */
52 { 1, 1, 0, 1, 0, 0 }, /* 1 + x + x^3 */
53 { 1, 0, 1, 1, 0, 0 }, /* 1 + x^2 + x^3 */
54 { 1, 1, 0, 0, 1, 0 }, /* 1 + x + x^4 */
55 { 1, 0, 0, 1, 1, 0 }, /* 1 + x^3 + x^4 */
56 { 1, 1, 1, 1, 1, 0 }, /* 1 + x + x^2 + x^3 + x^4 */
57 { 1, 0, 1, 0, 0, 1 }, /* 1 + x^2 + x^5 */
58 { 1, 0, 0, 1, 0, 1 }, /* 1 + x^3 + x^5 */
59 { 1, 1, 1, 1, 0, 1 }, /* 1 + x + x^2 + x^3 + x^5 */
60 { 1, 1, 1, 0, 1, 1 } /* 1 + x + x^2 + x^4 + x^5 */
63 /* degrees of primitive polynomials */
64 static const int poly_degree[NIED2_MAX_DIMENSION+1] =
66 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5
72 unsigned int sequence_count;
73 int cj[NIED2_NBITS][NIED2_MAX_DIMENSION];
74 int nextq[NIED2_MAX_DIMENSION];
78 static size_t nied2_state_size(unsigned int dimension)
80 return sizeof(nied2_state_t);
84 /* Multiply polynomials over Z_2.
85 * Notice use of a temporary vector,
86 * side-stepping aliasing issues when
87 * one of inputs is the same as the output
88 * [especially important in the original fortran version, I guess].
90 static void poly_multiply(
91 const int pa[], int pa_degree,
92 const int pb[], int pb_degree,
93 int pc[], int * pc_degree
97 int pt[NIED2_MAX_DEGREE+1];
98 int pt_degree = pa_degree + pb_degree;
100 for(k=0; k<=pt_degree; k++) {
102 for(j=0; j<=k; j++) {
103 const int conv_term = NIED2_MUL(pa[k-j], pb[j]);
104 term = NIED2_ADD(term, conv_term);
109 for(k=0; k<=pt_degree; k++) {
112 for(k=pt_degree+1; k<=NIED2_MAX_DEGREE; k++) {
116 *pc_degree = pt_degree;
120 /* Calculate the values of the constants V(J,R) as
121 * described in BFN section 3.3.
123 * px = appropriate irreducible polynomial for current dimension
124 * pb = polynomial defined in section 2.3 of BFN.
127 static void calculate_v(
128 const int px[], int px_degree,
129 int pb[], int * pb_degree,
133 const int nonzero_element = 1; /* nonzero element of Z_2 */
134 const int arbitrary_element = 1; /* arbitray element of Z_2 */
136 /* The polynomial ph is px**(J-1), which is the value of B on arrival.
137 * In section 3.3, the values of Hi are defined with a minus sign:
138 * don't forget this if you use them later !
140 int ph[NIED2_MAX_DEGREE+1];
141 /* int ph_degree = *pb_degree; */
142 int bigm = *pb_degree; /* m from section 3.3 */
143 int m; /* m from section 2.3 */
146 for(k=0; k<=NIED2_MAX_DEGREE; k++) {
150 /* Now multiply B by PX so B becomes PX**J.
151 * In section 2.3, the values of Bi are defined with a minus sign :
152 * don't forget this if you use them later !
154 poly_multiply(px, px_degree, pb, *pb_degree, pb, pb_degree);
157 /* Now choose a value of Kj as defined in section 3.3.
158 * We must have 0 <= Kj < E*J = M.
159 * The limit condition on Kj does not seem very relevant
162 /* Quoting from BFN: "Our program currently sets each K_q
163 * equal to eq. This has the effect of setting all unrestricted
165 * Actually, it sets them to the arbitrary chosen value.
170 /* Now choose values of V in accordance with
171 * the conditions in section 3.3.
173 for(r=0; r<kj; r++) {
180 for(r=kj+1; r<m; r++) {
181 v[r] = arbitrary_element;
185 /* This block is never reached. */
187 int term = NIED2_SUB(0, ph[kj]);
189 for(r=kj+1; r<bigm; r++) {
190 v[r] = arbitrary_element;
192 /* Check the condition of section 3.3,
193 * remembering that the H's have the opposite sign. [????????]
195 term = NIED2_SUB(term, NIED2_MUL(ph[r], v[r]));
198 /* Now v[bigm] != term. */
199 v[bigm] = NIED2_ADD(nonzero_element, term);
201 for(r=bigm+1; r<m; r++) {
202 v[r] = arbitrary_element;
206 /* Calculate the remaining V's using the recursion of section 2.3,
207 * remembering that the B's have the opposite sign.
209 for(r=0; r<=maxv-m; r++) {
212 term = NIED2_SUB(term, NIED2_MUL(pb[k], v[r+k]));
219 static void calculate_cj(nied2_state_t * ns, unsigned int dimension)
221 int ci[NIED2_NBITS][NIED2_NBITS];
226 for(i_dim=0; i_dim<dimension; i_dim++) {
228 const int poly_index = i_dim + 1;
231 /* Niederreiter (page 56, after equation (7), defines two
232 * variables Q and U. We do not need Q explicitly, but we
237 /* For each dimension, we need to calculate powers of an
238 * appropriate irreducible polynomial, see Niederreiter
239 * page 65, just below equation (19).
240 * Copy the appropriate irreducible polynomial into PX,
241 * and its degree into E. Set polynomial B = PX ** 0 = 1.
242 * M is the degree of B. Subsequently B will hold higher
245 int pb[NIED2_MAX_DEGREE+1];
246 int px[NIED2_MAX_DEGREE+1];
247 int px_degree = poly_degree[poly_index];
250 for(k=0; k<=px_degree; k++) {
251 px[k] = primitive_poly[poly_index][k];
255 for (;k<NIED2_MAX_DEGREE+1;k++) {
262 for(j=0; j<NIED2_NBITS; j++) {
264 /* If U = 0, we need to set B to the next power of PX
267 if(u == 0) calculate_v(px, px_degree, pb, &pb_degree, v, MAXV);
269 /* Now C is obtained from V. Niederreiter
270 * obtains A from V (page 65, near the bottom), and then gets
271 * C from A (page 56, equation (7)). However this can be done
272 * in one step. Here CI(J,R) corresponds to
273 * Niederreiter's C(I,J,R).
275 for(r=0; r<NIED2_NBITS; r++) {
279 /* Advance Niederreiter's state variables. */
281 if(u == px_degree) u = 0;
284 /* The array CI now holds the values of C(I,J,R) for this value
285 * of I. We pack them into array CJ so that CJ(I,R) holds all
286 * the values of C(I,J,R) for J from 1 to NBITS.
288 for(r=0; r<NIED2_NBITS; r++) {
290 for(j=0; j<NIED2_NBITS; j++) {
291 term = 2*term + ci[r][j];
293 ns->cj[r][i_dim] = term;
300 static int nied2_init(void * state, unsigned int dimension)
302 nied2_state_t * n_state = (nied2_state_t *) state;
305 if(dimension < 1 || dimension > NIED2_MAX_DIMENSION) return GSL_EINVAL;
307 calculate_cj(n_state, dimension);
309 for(i_dim=0; i_dim<dimension; i_dim++) n_state->nextq[i_dim] = 0;
310 n_state->sequence_count = 0;
316 static int nied2_get(void * state, unsigned int dimension, double * v)
318 static const double recip = 1.0/(double)(1U << NIED2_NBITS); /* 2^(-nbits) */
319 nied2_state_t * n_state = (nied2_state_t *) state;
324 /* Load the result from the saved state. */
325 for(i_dim=0; i_dim<dimension; i_dim++) {
326 v[i_dim] = n_state->nextq[i_dim] * recip;
329 /* Find the position of the least-significant zero in sequence_count.
330 * This is the bit that changes in the Gray-code representation as
331 * the count is advanced.
334 c = n_state->sequence_count;
343 if(r >= NIED2_NBITS) return GSL_EFAILED; /* FIXME: better error code here */
345 /* Calculate the next state. */
346 for(i_dim=0; i_dim<dimension; i_dim++) {
347 n_state->nextq[i_dim] ^= n_state->cj[r][i_dim];
350 n_state->sequence_count++;