Revised wording in pdb2gmx.c, hopefully clearer now.
[gromacs/rigid-bodies.git] / src / gmxlib / gmx_random.c
blob4e5c4c4dc43851a270ce8eea9e4485b58c8520cc
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 4.5
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
32 * And Hey:
33 * Groningen Machine for Chemical Simulation
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <gmx_random.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46 #include <time.h>
47 #include <math.h>
48 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
49 #include <process.h>
50 #endif
52 #include "maths.h"
53 #include "gmx_random_gausstable.h"
55 #define RNG_N 624
56 #define RNG_M 397
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)
72 struct gmx_rng {
73 unsigned int mt[RNG_N];
74 int mti;
75 int has_saved;
76 double gauss_saved;
81 int
82 gmx_rng_n(void)
84 return RNG_N;
88 gmx_rng_t
89 gmx_rng_init(unsigned int seed)
91 struct gmx_rng *rng;
93 if((rng=(struct gmx_rng *)malloc(sizeof(struct gmx_rng)))==NULL)
94 return 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++) {
100 rng->mt[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 */
110 return rng;
113 gmx_rng_t
114 gmx_rng_init_array(unsigned int seed[], int seed_length)
116 int i, j, k;
117 gmx_rng_t rng;
119 if((rng=gmx_rng_init(19650218UL))==NULL)
120 return NULL;
122 i=1; j=0;
123 k = (RNG_N>seed_length ? RNG_N : seed_length);
124 for (; k; k--) {
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 */
129 i++; j++;
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)) *
136 1566083941UL))
137 - i; /* non linear */
138 rng->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
139 i++;
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 */
145 return rng;
149 void
150 gmx_rng_destroy(gmx_rng_t rng)
152 if(rng)
153 free(rng);
157 void
158 gmx_rng_get_state(gmx_rng_t rng, unsigned int *mt,int *mti)
160 int i;
162 for(i=0; i<RNG_N; i++) {
163 mt[i] = rng->mt[i];
165 *mti = rng->mti;
169 void
170 gmx_rng_set_state(gmx_rng_t rng, unsigned int *mt,int mti)
172 int i;
174 for(i=0; i<RNG_N; i++) {
175 rng->mt[i] = mt[i];
177 rng->mti = mti;
181 unsigned int
182 gmx_rng_make_seed(void)
184 FILE *fp;
185 unsigned int data;
186 int ret;
187 long my_pid;
189 #ifdef HAVE_UNISTD_H
190 fp=fopen("/dev/random","rb"); /* will return NULL if it is not present */
191 #else
192 fp=NULL;
193 #endif
194 if(fp!=NULL) {
195 ret=fread(&data,sizeof(unsigned int),1,fp);
196 fclose(fp);
197 } else {
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();
201 #else
202 my_pid = (long)getpid();
203 #endif
204 data=(unsigned int)(((long)time(NULL)+my_pid) % (long)1000000);
206 return data;
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.
214 static void
215 gmx_rng_update(gmx_rng_t rng)
217 unsigned int lastx,x1,x2,y,*mt;
218 int mti,k;
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 */
224 mti = rng->mti;
226 x1 = mt[0];
227 for (k = 0; k < RNG_N-RNG_M-3; k += 4)
229 x2 = mt[k+1];
230 y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
231 mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
232 x1 = mt[k+2];
233 y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
234 mt[k+1] = mt[k+RNG_M+1] ^ (y >> 1) ^ mag01[y & 0x1UL];
235 x2 = mt[k+3];
236 y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
237 mt[k+2] = mt[k+RNG_M+2] ^ (y >> 1) ^ mag01[y & 0x1UL];
238 x1 = mt[k+4];
239 y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
240 mt[k+3] = mt[k+RNG_M+3] ^ (y >> 1) ^ mag01[y & 0x1UL];
242 x2 = mt[k+1];
243 y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
244 mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
245 k++;
246 x1 = mt[k+1];
247 y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
248 mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
249 k++;
250 x2 = mt[k+1];
251 y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
252 mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
253 k++;
254 for (; k < RNG_N-1; k += 4)
256 x1 = mt[k+1];
257 y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
258 mt[k] = mt[k+(RNG_M-RNG_N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
259 x2 = mt[k+2];
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];
262 x1 = mt[k+3];
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];
265 x2 = mt[k+4];
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];
272 rng->mti = 0;
276 real
277 gmx_rng_gaussian_real(gmx_rng_t rng)
279 real x,y,r;
281 if(rng->has_saved) {
282 rng->has_saved=0;
283 return rng->gauss_saved;
284 } else {
285 do {
286 x=2.0*gmx_rng_uniform_real(rng)-1.0;
287 y=2.0*gmx_rng_uniform_real(rng)-1.0;
288 r=x*x+y*y;
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 */
293 rng->has_saved=1;
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().
306 unsigned int
307 gmx_rng_uniform_uint32(gmx_rng_t rng)
309 unsigned int y;
311 if(rng->mti==RNG_N)
312 gmx_rng_update(rng);
313 y=rng->mt[rng->mti++];
315 y ^= (y >> 11);
316 y ^= (y << 7) & 0x9d2c5680UL;
317 y ^= (y << 15) & 0xefc60000UL;
318 y ^= (y >> 18);
320 return y;
327 /* Return a uniform floating point number on the interval 0<=x<1 */
328 real
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);
333 else
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.
344 real
345 gmx_rng_gaussian_table(gmx_rng_t rng)
347 unsigned int i;
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.
360 void
361 print_gaussian_table(int bits)
363 int n,nh,i,j;
364 double invn,fac,x,invgauss,det,dx;
365 real *table;
367 n = 1 << bits;
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
374 * with:
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.
379 invn = 1.0/n;
380 fac = sqrt(2*M_PI);
381 x = 0.5*fac*invn;
382 nh = n/2;
383 for(i=0; i<nh; i++) {
384 if (i > 0) {
385 if (i < nh-1) {
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;
390 } else {
391 dx = 1/x;
393 x = x + dx;
395 table[nh-1-i] = -x;
396 table[nh+i] = x;
398 printf("static const real *\ngaussian_table[%d] = {\n",n);
399 for(i=0;i<n;i+=4) {
400 printf(" ");
401 for(j=0;j<4;j++) {
402 printf("%14.7e",table[i+j]);
403 if(i+j<(n-1))
404 printf(",");
406 printf("\n");
408 printf("};\n");
409 free(table);