1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2008, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Groningen Machine for Chemical Simulation
39 #include <gmx_random.h>
48 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
53 #include "gmx_random_gausstable.h"
57 #define RNG_MATRIX_A 0x9908b0dfUL /* constant vector a */
58 #define RNG_UPPER_MASK 0x80000000UL /* most significant w-r bits */
59 #define RNG_LOWER_MASK 0x7fffffffUL /* least significant r bits */
61 /* Note that if you change the size of the Gaussian table you will also
62 * have to generate new initialization data for the table in
63 * gmx_random_gausstable.h
65 * We have included the routine print_gaussian_table() in this file
66 * for convenience - use it if you need a different size of the table.
68 #define GAUSS_TABLE 14 /* the size of the gauss table is 2^GAUSS_TABLE */
69 #define GAUSS_SHIFT (32 - GAUSS_TABLE)
73 unsigned int mt
[RNG_N
];
89 gmx_rng_init(unsigned int seed
)
93 if((rng
=(struct gmx_rng
*)malloc(sizeof(struct gmx_rng
)))==NULL
)
96 rng
->has_saved
=0; /* no saved gaussian number yet */
98 rng
->mt
[0]= seed
& 0xffffffffUL
;
99 for (rng
->mti
=1; rng
->mti
<RNG_N
; rng
->mti
++) {
101 (1812433253UL * (rng
->mt
[rng
->mti
-1] ^
102 (rng
->mt
[rng
->mti
-1] >> 30)) + rng
->mti
);
103 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
104 /* In the previous versions, MSBs of the seed affect */
105 /* only MSBs of the array mt[]. */
106 /* 2002/01/09 modified by Makoto Matsumoto */
107 rng
->mt
[rng
->mti
] &= 0xffffffffUL
;
108 /* for >32 bit machines */
114 gmx_rng_init_array(unsigned int seed
[], int seed_length
)
119 if((rng
=gmx_rng_init(19650218UL))==NULL
)
123 k
= (RNG_N
>seed_length
? RNG_N
: seed_length
);
125 rng
->mt
[i
] = (rng
->mt
[i
] ^ ((rng
->mt
[i
-1] ^
126 (rng
->mt
[i
-1] >> 30)) * 1664525UL))
127 + seed
[j
] + j
; /* non linear */
128 rng
->mt
[i
] &= 0xffffffffUL
; /* for WORDSIZE > 32 machines */
130 if (i
>=RNG_N
) { rng
->mt
[0] = rng
->mt
[RNG_N
-1]; i
=1; }
131 if (j
>=seed_length
) j
=0;
133 for (k
=RNG_N
-1; k
; k
--) {
134 rng
->mt
[i
] = (rng
->mt
[i
] ^ ((rng
->mt
[i
-1] ^
135 (rng
->mt
[i
-1] >> 30)) *
137 - i
; /* non linear */
138 rng
->mt
[i
] &= 0xffffffffUL
; /* for WORDSIZE > 32 machines */
140 if (i
>=RNG_N
) { rng
->mt
[0] = rng
->mt
[RNG_N
-1]; i
=1; }
143 rng
->mt
[0] = 0x80000000UL
;
144 /* MSB is 1; assuring non-zero initial array */
150 gmx_rng_destroy(gmx_rng_t rng
)
158 gmx_rng_get_state(gmx_rng_t rng
, unsigned int *mt
,int *mti
)
162 for(i
=0; i
<RNG_N
; i
++) {
170 gmx_rng_set_state(gmx_rng_t rng
, unsigned int *mt
,int mti
)
174 for(i
=0; i
<RNG_N
; i
++) {
182 gmx_rng_make_seed(void)
190 fp
=fopen("/dev/random","rb"); /* will return NULL if it is not present */
195 ret
=fread(&data
,sizeof(unsigned int),1,fp
);
198 /* No random device available, use time-of-day and process id */
199 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
200 my_pid
= (long)_getpid();
202 my_pid
= (long)getpid();
204 data
=(unsigned int)(((long)time(NULL
)+my_pid
) % (long)1000000);
210 /* The random number state contains RNG_N entries that are returned one by
211 * one as random numbers. When we run out of them, this routine is called to
212 * regenerate RNG_N new entries.
215 gmx_rng_update(gmx_rng_t rng
)
217 unsigned int lastx
,x1
,x2
,y
,*mt
;
219 const unsigned int mag01
[2] = {0x0UL
, RNG_MATRIX_A
};
220 /* mag01[x] = x * MATRIX_A for x=0,1 */
222 /* update random numbers */
223 mt
= rng
->mt
; /* pointer to array - avoid repeated dereferencing */
227 for (k
= 0; k
< RNG_N
-RNG_M
-3; k
+= 4)
230 y
= (x1
& RNG_UPPER_MASK
) | (x2
& RNG_LOWER_MASK
);
231 mt
[k
] = mt
[k
+RNG_M
] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
233 y
= (x2
& RNG_UPPER_MASK
) | (x1
& RNG_LOWER_MASK
);
234 mt
[k
+1] = mt
[k
+RNG_M
+1] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
236 y
= (x1
& RNG_UPPER_MASK
) | (x2
& RNG_LOWER_MASK
);
237 mt
[k
+2] = mt
[k
+RNG_M
+2] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
239 y
= (x2
& RNG_UPPER_MASK
) | (x1
& RNG_LOWER_MASK
);
240 mt
[k
+3] = mt
[k
+RNG_M
+3] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
243 y
= (x1
& RNG_UPPER_MASK
) | (x2
& RNG_LOWER_MASK
);
244 mt
[k
] = mt
[k
+RNG_M
] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
247 y
= (x2
& RNG_UPPER_MASK
) | (x1
& RNG_LOWER_MASK
);
248 mt
[k
] = mt
[k
+RNG_M
] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
251 y
= (x1
& RNG_UPPER_MASK
) | (x2
& RNG_LOWER_MASK
);
252 mt
[k
] = mt
[k
+RNG_M
] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
254 for (; k
< RNG_N
-1; k
+= 4)
257 y
= (x2
& RNG_UPPER_MASK
) | (x1
& RNG_LOWER_MASK
);
258 mt
[k
] = mt
[k
+(RNG_M
-RNG_N
)] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
260 y
= (x1
& RNG_UPPER_MASK
) | (x2
& RNG_LOWER_MASK
);
261 mt
[k
+1] = mt
[k
+(RNG_M
-RNG_N
)+1] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
263 y
= (x2
& RNG_UPPER_MASK
) | (x1
& RNG_LOWER_MASK
);
264 mt
[k
+2] = mt
[k
+(RNG_M
-RNG_N
)+2] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
266 y
= (x1
& RNG_UPPER_MASK
) | (x2
& RNG_LOWER_MASK
);
267 mt
[k
+3] = mt
[k
+(RNG_M
-RNG_N
)+3] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
269 y
= (x2
& RNG_UPPER_MASK
) | (mt
[0] & RNG_LOWER_MASK
);
270 mt
[RNG_N
-1] = mt
[RNG_M
-1] ^ (y
>> 1) ^ mag01
[y
& 0x1UL
];
277 gmx_rng_gaussian_real(gmx_rng_t rng
)
283 return rng
->gauss_saved
;
286 x
=2.0*gmx_rng_uniform_real(rng
)-1.0;
287 y
=2.0*gmx_rng_uniform_real(rng
)-1.0;
289 } while(r
>1.0 || r
==0.0);
291 r
=sqrt(-2.0*log(r
)/r
);
292 rng
->gauss_saved
=y
*r
; /* save second random number */
294 return x
*r
; /* return first random number */
301 /* Return a random unsigned integer, i.e. 0..4294967295
302 * Provided in header file for performace reasons.
303 * Unfortunately this function cannot be inlined, since
304 * it needs to refer the internal-linkage gmx_rng_update().
307 gmx_rng_uniform_uint32(gmx_rng_t rng
)
313 y
=rng
->mt
[rng
->mti
++];
316 y
^= (y
<< 7) & 0x9d2c5680UL
;
317 y
^= (y
<< 15) & 0xefc60000UL
;
327 /* Return a uniform floating point number on the interval 0<=x<1 */
329 gmx_rng_uniform_real(gmx_rng_t rng
)
331 if(sizeof(real
)==sizeof(double))
332 return ((double)gmx_rng_uniform_uint32(rng
))*(1.0/4294967296.0);
334 return ((float)gmx_rng_uniform_uint32(rng
))*(1.0/4294967423.0);
335 /* divided by the smallest number that will generate a
336 * single precision real number on 0<=x<1.
337 * This needs to be slightly larger than MAX_UNIT since
338 * we are limited to an accuracy of 1e-7.
345 gmx_rng_gaussian_table(gmx_rng_t rng
)
349 i
= gmx_rng_uniform_uint32(rng
);
351 /* The Gaussian table is a static constant in this file */
352 return gaussian_table
[i
>> GAUSS_SHIFT
];
357 * Print a lookup table for Gaussian numbers with 4 entries on each
358 * line, formatted for inclusion in this file. Size is 2^bits.
361 print_gaussian_table(int bits
)
364 double invn
,fac
,x
,invgauss
,det
,dx
;
368 table
= (real
*)malloc(n
*sizeof(real
));
370 /* Fill a table of size n such that random draws from it
371 * produce a Gaussian distribution.
372 * We integrate the Gaussian distribution G approximating:
373 * integral(x->x+dx) G(y) dy
375 * G(x) dx + G'(x) dx^2/2 = G(x) dx - G(x) x dx^2/2
376 * Then we need to find dx such that the integral is 1/n.
377 * The last step uses dx = 1/x as the approximation is not accurate enough.
383 for(i
=0; i
<nh
; i
++) {
386 invgauss
= fac
*exp(0.5*x
*x
);
387 /* det is larger than 0 for all x, except for the last */
388 det
= 1 - 2*invn
*x
*invgauss
;
389 dx
= (1 - sqrt(det
))/x
;
398 printf("static const real *\ngaussian_table[%d] = {\n",n
);
402 printf("%14.7e",table
[i
+j
]);