3 * Copyright (C) 2001, 2007 Brian Gough, Carlo Perassi
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * This generator is taken from
24 * The Art of Computer Programming
30 * The comments are taken from the book
31 * Our comments are signed
36 #include <gsl/gsl_rng.h>
38 #define BUFLEN 2009 /* [Brian]: length of the buffer aa[] */
39 #define KK 100 /* the long lag */
40 #define LL 37 /* the short lag */
41 #define MM (1L << 30) /* the modulus */
42 #define TT 70 /* guaranteed separation between streams */
44 #define evenize(x) ((x) & (MM - 2)) /* make x even */
45 #define is_odd(x) ((x) & 1) /* the units bit of x */
46 #define mod_diff(x, y) (((x) - (y)) & (MM - 1)) /* (x - y) mod MM */
48 static inline void ran_array (unsigned long int aa[], unsigned int n,
49 unsigned long int ran_x[]);
50 static inline unsigned long int ran_get (void *vstate);
51 static double ran_get_double (void *vstate);
52 static void ran_set (void *state, unsigned long int s);
57 unsigned long int aa[BUFLEN]; /* [Carlo]: I can't pass n to ran_array like
59 unsigned long int ran_x[KK]; /* the generator state */
64 ran_array (unsigned long int aa[], unsigned int n, unsigned long int ran_x[])
69 for (j = 0; j < KK; j++)
73 aa[j] = mod_diff (aa[j - KK], aa[j - LL]);
75 for (i = 0; i < LL; i++, j++)
76 ran_x[i] = mod_diff (aa[j - KK], aa[j - LL]);
78 for (; i < KK; i++, j++)
79 ran_x[i] = mod_diff (aa[j - KK], ran_x[i - LL]);
82 static inline unsigned long int
83 ran_get (void *vstate)
85 ran_state_t *state = (ran_state_t *) vstate;
87 unsigned int i = state->i;
91 /* fill buffer with new random numbers */
92 ran_array (state->aa, BUFLEN, state->ran_x);
95 state->i = (i + 1) % BUFLEN;
101 ran_get_double (void *vstate)
103 ran_state_t *state = (ran_state_t *) vstate;
105 return ran_get (state) / 1073741824.0; /* [Carlo]: RAND_MAX + 1 */
109 ran_set (void *vstate, unsigned long int s)
111 ran_state_t *state = (ran_state_t *) vstate;
113 long x[KK + KK - 1]; /* the preparation buffer */
117 register long ss = evenize (s + 2);
119 for (j = 0; j < KK; j++)
121 x[j] = ss; /* bootstrap the buffer */
123 if (ss >= MM) /* cyclic shift 29 bits */
126 for (; j < KK + KK - 1; j++)
128 x[1]++; /* make x[1] (and only x[1]) odd */
133 for (j = KK - 1; j > 0; j--) /* square */
135 for (j = KK + KK - 2; j > KK - LL; j -= 2)
136 x[KK + KK - 1 - j] = evenize (x[j]);
137 for (j = KK + KK - 2; j >= KK; j--)
140 x[j - (KK - LL)] = mod_diff (x[j - (KK - LL)], x[j]);
141 x[j - KK] = mod_diff (x[j - KK], x[j]);
144 { /* multiply by "z" */
145 for (j = KK; j > 0; j--)
147 x[0] = x[KK]; /* shift the buffer cyclically */
149 x[LL] = mod_diff (x[LL], x[KK]);
159 for (j = 0; j < LL; j++)
160 state->ran_x[j + KK - LL] = x[j];
162 state->ran_x[j - LL] = x[j];
167 static const gsl_rng_type ran_type = {
168 "knuthran", /* name */
169 0x3fffffffUL, /* RAND_MAX *//* [Carlo]: (2 ^ 30) - 1 */
171 sizeof (ran_state_t),
177 const gsl_rng_type *gsl_rng_knuthran = &ran_type;