3 * Copyright (C) 2007 Brian Gough
4 * Copyright (C) 2001, 2007 Brian Gough, Carlo Perassi
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * This generator is taken from
24 * Donald E. Knuth, The Art of Computer Programming, Volume 2, Section 3.6
25 * Third Edition, Addison-Wesley,
27 * The modifications introduced in the 9th printing (2002) are
28 * included here; there's no backwards compatibility with the
29 * original. [ see http://www-cs-faculty.stanford.edu/~knuth/taocp.html ]
35 #include <gsl/gsl_rng.h>
37 #define BUFLEN 1009 /* length of the buffer aa[] */
38 #define KK 100 /* the long lag */
39 #define LL 37 /* the short lag */
40 #define MM (1L << 30) /* the modulus */
41 #define TT 70 /* guaranteed separation between streams */
43 #define is_odd(x) ((x) & 1) /* the units bit of x */
44 #define mod_diff(x, y) (((x) - (y)) & (MM - 1)) /* (x - y) mod MM */
46 static inline void ran_array (long int aa[], unsigned int n,
48 static inline unsigned long int ran_get (void *vstate);
49 static double ran_get_double (void *vstate);
50 static void ran_set (void *state, unsigned long int s);
56 long int ran_x[KK]; /* the generator state */
61 ran_array (long int aa[], unsigned int n, long int ran_x[])
66 for (j = 0; j < KK; j++)
70 aa[j] = mod_diff (aa[j - KK], aa[j - LL]);
72 for (i = 0; i < LL; i++, j++)
73 ran_x[i] = mod_diff (aa[j - KK], aa[j - LL]);
75 for (; i < KK; i++, j++)
76 ran_x[i] = mod_diff (aa[j - KK], ran_x[i - LL]);
79 static inline unsigned long int
80 ran_get (void *vstate)
82 ran_state_t *state = (ran_state_t *) vstate;
84 unsigned int i = state->i;
89 /* fill buffer with new random numbers */
90 ran_array (state->aa, BUFLEN, state->ran_x);
95 state->i = (i + 1) % KK;
101 ran_get_double (void *vstate)
103 ran_state_t *state = (ran_state_t *) vstate;
105 return ran_get (state) / 1073741824.0; /* 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 */
120 s = 314159; /* default seed used by Knuth */
124 for (j = 0; j < KK; j++)
126 x[j] = ss; /* bootstrap the buffer */
128 if (ss >= MM) /* cyclic shift 29 bits */
131 x[1]++; /* make x[1] (and only x[1]) odd */
137 for (j = KK - 1; j > 0; j--) /* square */
143 for (j = KK + KK - 2; j >= KK; j--)
145 x[j - (KK - LL)] = mod_diff (x[j - (KK - LL)], x[j]);
146 x[j - KK] = mod_diff (x[j - KK], x[j]);
150 { /* multiply by "z" */
151 for (j = KK; j > 0; j--)
155 x[0] = x[KK]; /* shift the buffer cyclically */
156 x[LL] = mod_diff (x[LL], x[KK]);
165 for (j = 0; j < LL; j++)
166 state->ran_x[j + KK - LL] = x[j];
168 state->ran_x[j - LL] = x[j];
171 for (j = 0; j< 10; j++)
172 ran_array(x, KK+KK-1, state->ran_x); /* warm things up */
179 static const gsl_rng_type ran_type = {
180 "knuthran2002", /* name */
181 0x3fffffffUL, /* RAND_MAX = (2 ^ 30) - 1 */
183 sizeof (ran_state_t),
189 const gsl_rng_type *gsl_rng_knuthran2002 = &ran_type;