PageRenderTime 84ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/gromacs/random/random.c

https://github.com/mabraham/gromacs
C | 440 lines | 296 code | 63 blank | 81 comment | 25 complexity | 5434b946c3a13e76937e5ccdbfa2bfce MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. /*
  2. * This file is part of the GROMACS molecular simulation package.
  3. *
  4. * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  5. * Copyright (c) 2001-2008, The GROMACS development team.
  6. * Copyright (c) 2012,2014, by the GROMACS development team, led by
  7. * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  8. * and including many others, as listed in the AUTHORS file in the
  9. * top-level source directory and at http://www.gromacs.org.
  10. *
  11. * GROMACS is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public License
  13. * as published by the Free Software Foundation; either version 2.1
  14. * of the License, or (at your option) any later version.
  15. *
  16. * GROMACS is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with GROMACS; if not, see
  23. * http://www.gnu.org/licenses, or write to the Free Software Foundation,
  24. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  25. *
  26. * If you want to redistribute modifications to GROMACS, please
  27. * consider that scientific software is very special. Version
  28. * control is crucial - bugs must be traceable. We will be happy to
  29. * consider code for inclusion in the official distribution, but
  30. * derived work must not be called official GROMACS. Details are found
  31. * in the README & COPYING files - if they are missing, get the
  32. * official version at http://www.gromacs.org.
  33. *
  34. * To help us fund GROMACS development, we humbly ask that you cite
  35. * the research papers on the package. Check out http://www.gromacs.org.
  36. */
  37. #include "gmxpre.h"
  38. #include "random.h"
  39. #include "config.h"
  40. #include <math.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <time.h>
  44. #include "external/Random123-1.08/include/Random123/threefry.h"
  45. #include "gromacs/math/utilities.h"
  46. #include "gromacs/random/random_gausstable.h"
  47. #include "gromacs/utility/sysinfo.h"
  48. #define RNG_N 624
  49. #define RNG_M 397
  50. #define RNG_MATRIX_A 0x9908b0dfUL /* constant vector a */
  51. #define RNG_UPPER_MASK 0x80000000UL /* most significant w-r bits */
  52. #define RNG_LOWER_MASK 0x7fffffffUL /* least significant r bits */
  53. /* Note that if you change the size of the Gaussian table you will
  54. * also have to generate new initialization data for the table in
  55. * gmx_random_gausstable.h
  56. *
  57. * A routine print_gaussian_table() is in contrib/random.c
  58. * for convenience - use it if you need a different size of the table.
  59. */
  60. #define GAUSS_TABLE 14 /* the size of the gauss table is 2^GAUSS_TABLE */
  61. #define GAUSS_MASK ((1 << GAUSS_TABLE) - 1)
  62. struct gmx_rng {
  63. unsigned int mt[RNG_N];
  64. int mti;
  65. int has_saved;
  66. double gauss_saved;
  67. };
  68. int
  69. gmx_rng_n(void)
  70. {
  71. return RNG_N;
  72. }
  73. gmx_rng_t
  74. gmx_rng_init(unsigned int seed)
  75. {
  76. struct gmx_rng *rng;
  77. if ((rng = (struct gmx_rng *)malloc(sizeof(struct gmx_rng))) == NULL)
  78. {
  79. return NULL;
  80. }
  81. rng->has_saved = 0; /* no saved gaussian number yet */
  82. rng->mt[0] = seed & 0xffffffffUL;
  83. for (rng->mti = 1; rng->mti < RNG_N; rng->mti++)
  84. {
  85. rng->mt[rng->mti] =
  86. (1812433253UL * (rng->mt[rng->mti-1] ^
  87. (rng->mt[rng->mti-1] >> 30)) + rng->mti);
  88. /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
  89. /* In the previous versions, MSBs of the seed affect */
  90. /* only MSBs of the array mt[]. */
  91. /* 2002/01/09 modified by Makoto Matsumoto */
  92. rng->mt[rng->mti] &= 0xffffffffUL;
  93. /* for >32 bit machines */
  94. }
  95. return rng;
  96. }
  97. gmx_rng_t
  98. gmx_rng_init_array(unsigned int seed[], int seed_length)
  99. {
  100. int i, j, k;
  101. gmx_rng_t rng;
  102. if ((rng = gmx_rng_init(19650218UL)) == NULL)
  103. {
  104. return NULL;
  105. }
  106. i = 1; j = 0;
  107. k = (RNG_N > seed_length ? RNG_N : seed_length);
  108. for (; k; k--)
  109. {
  110. rng->mt[i] = (rng->mt[i] ^ ((rng->mt[i-1] ^
  111. (rng->mt[i-1] >> 30)) * 1664525UL))
  112. + seed[j] + j; /* non linear */
  113. rng->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
  114. i++; j++;
  115. if (i >= RNG_N)
  116. {
  117. rng->mt[0] = rng->mt[RNG_N-1]; i = 1;
  118. }
  119. if (j >= seed_length)
  120. {
  121. j = 0;
  122. }
  123. }
  124. for (k = RNG_N-1; k; k--)
  125. {
  126. rng->mt[i] = (rng->mt[i] ^ ((rng->mt[i-1] ^
  127. (rng->mt[i-1] >> 30)) *
  128. 1566083941UL))
  129. - i; /* non linear */
  130. rng->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
  131. i++;
  132. if (i >= RNG_N)
  133. {
  134. rng->mt[0] = rng->mt[RNG_N-1]; i = 1;
  135. }
  136. }
  137. rng->mt[0] = 0x80000000UL;
  138. /* MSB is 1; assuring non-zero initial array */
  139. return rng;
  140. }
  141. void
  142. gmx_rng_destroy(gmx_rng_t rng)
  143. {
  144. if (rng)
  145. {
  146. free(rng);
  147. }
  148. }
  149. void
  150. gmx_rng_get_state(gmx_rng_t rng, unsigned int *mt, int *mti)
  151. {
  152. int i;
  153. for (i = 0; i < RNG_N; i++)
  154. {
  155. mt[i] = rng->mt[i];
  156. }
  157. *mti = rng->mti;
  158. }
  159. void
  160. gmx_rng_set_state(gmx_rng_t rng, unsigned int *mt, int mti)
  161. {
  162. int i;
  163. for (i = 0; i < RNG_N; i++)
  164. {
  165. rng->mt[i] = mt[i];
  166. }
  167. rng->mti = mti;
  168. }
  169. unsigned int
  170. gmx_rng_make_seed(void)
  171. {
  172. FILE *fp;
  173. unsigned int data;
  174. int ret;
  175. long my_pid;
  176. #ifdef HAVE_UNISTD_H
  177. /* We never want Gromacs execution to halt 10-20 seconds while
  178. * waiting for enough entropy in the random number generator.
  179. * For this reason we should NOT use /dev/random, which will
  180. * block in cases like that. That will cause all sorts of
  181. * Gromacs programs to block ~20 seconds while waiting for a
  182. * super-random-number to generate cool quotes. Apart from the
  183. * minor irritation, it is really bad behavior of a program
  184. * to abuse the system random numbers like that - other programs
  185. * need them too.
  186. * For this reason, we ONLY try to get random numbers from
  187. * the pseudo-random stream /dev/urandom, and use other means
  188. * if it is not present (in this case fopen() returns NULL).
  189. */
  190. fp = fopen("/dev/urandom", "rb");
  191. #else
  192. fp = NULL;
  193. #endif
  194. if (fp != NULL)
  195. {
  196. ret = fread(&data, sizeof(unsigned int), 1, fp);
  197. fclose(fp);
  198. }
  199. else
  200. {
  201. /* No random device available, use time-of-day and process id */
  202. my_pid = gmx_getpid();
  203. data = (unsigned int)(((long)time(NULL)+my_pid) % (long)1000000);
  204. }
  205. return data;
  206. }
  207. /* The random number state contains RNG_N entries that are returned one by
  208. * one as random numbers. When we run out of them, this routine is called to
  209. * regenerate RNG_N new entries.
  210. */
  211. static void
  212. gmx_rng_update(gmx_rng_t rng)
  213. {
  214. unsigned int lastx, x1, x2, y, *mt;
  215. int mti, k;
  216. const unsigned int mag01[2] = {0x0UL, RNG_MATRIX_A};
  217. /* mag01[x] = x * MATRIX_A for x=0,1 */
  218. /* update random numbers */
  219. mt = rng->mt; /* pointer to array - avoid repeated dereferencing */
  220. mti = rng->mti;
  221. x1 = mt[0];
  222. for (k = 0; k < RNG_N-RNG_M-3; k += 4)
  223. {
  224. x2 = mt[k+1];
  225. y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
  226. mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
  227. x1 = mt[k+2];
  228. y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
  229. mt[k+1] = mt[k+RNG_M+1] ^ (y >> 1) ^ mag01[y & 0x1UL];
  230. x2 = mt[k+3];
  231. y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
  232. mt[k+2] = mt[k+RNG_M+2] ^ (y >> 1) ^ mag01[y & 0x1UL];
  233. x1 = mt[k+4];
  234. y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
  235. mt[k+3] = mt[k+RNG_M+3] ^ (y >> 1) ^ mag01[y & 0x1UL];
  236. }
  237. x2 = mt[k+1];
  238. y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
  239. mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
  240. k++;
  241. x1 = mt[k+1];
  242. y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
  243. mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
  244. k++;
  245. x2 = mt[k+1];
  246. y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
  247. mt[k] = mt[k+RNG_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
  248. k++;
  249. for (; k < RNG_N-1; k += 4)
  250. {
  251. x1 = mt[k+1];
  252. y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
  253. mt[k] = mt[k+(RNG_M-RNG_N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
  254. x2 = mt[k+2];
  255. y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
  256. mt[k+1] = mt[k+(RNG_M-RNG_N)+1] ^ (y >> 1) ^ mag01[y & 0x1UL];
  257. x1 = mt[k+3];
  258. y = (x2 & RNG_UPPER_MASK) | (x1 & RNG_LOWER_MASK);
  259. mt[k+2] = mt[k+(RNG_M-RNG_N)+2] ^ (y >> 1) ^ mag01[y & 0x1UL];
  260. x2 = mt[k+4];
  261. y = (x1 & RNG_UPPER_MASK) | (x2 & RNG_LOWER_MASK);
  262. mt[k+3] = mt[k+(RNG_M-RNG_N)+3] ^ (y >> 1) ^ mag01[y & 0x1UL];
  263. }
  264. y = (x2 & RNG_UPPER_MASK) | (mt[0] & RNG_LOWER_MASK);
  265. mt[RNG_N-1] = mt[RNG_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
  266. rng->mti = 0;
  267. }
  268. real
  269. gmx_rng_gaussian_real(gmx_rng_t rng)
  270. {
  271. real x, y, r;
  272. if (rng->has_saved)
  273. {
  274. rng->has_saved = 0;
  275. return rng->gauss_saved;
  276. }
  277. else
  278. {
  279. do
  280. {
  281. x = 2.0*gmx_rng_uniform_real(rng)-1.0;
  282. y = 2.0*gmx_rng_uniform_real(rng)-1.0;
  283. r = x*x+y*y;
  284. }
  285. while (r > 1.0 || r == 0.0);
  286. r = sqrt(-2.0*log(r)/r);
  287. rng->gauss_saved = y*r; /* save second random number */
  288. rng->has_saved = 1;
  289. return x*r; /* return first random number */
  290. }
  291. }
  292. /* Return a random unsigned integer, i.e. 0..4294967295
  293. * Provided in header file for performace reasons.
  294. * Unfortunately this function cannot be inlined, since
  295. * it needs to refer the internal-linkage gmx_rng_update().
  296. */
  297. unsigned int
  298. gmx_rng_uniform_uint32(gmx_rng_t rng)
  299. {
  300. unsigned int y;
  301. if (rng->mti == RNG_N)
  302. {
  303. gmx_rng_update(rng);
  304. }
  305. y = rng->mt[rng->mti++];
  306. y ^= (y >> 11);
  307. y ^= (y << 7) & 0x9d2c5680UL;
  308. y ^= (y << 15) & 0xefc60000UL;
  309. y ^= (y >> 18);
  310. return y;
  311. }
  312. /* Return a uniform floating point number on the interval 0<=x<1 */
  313. real
  314. gmx_rng_uniform_real(gmx_rng_t rng)
  315. {
  316. if (sizeof(real) == sizeof(double))
  317. {
  318. return ((double)gmx_rng_uniform_uint32(rng))*(1.0/4294967296.0);
  319. }
  320. else
  321. {
  322. return ((float)gmx_rng_uniform_uint32(rng))*(1.0/4294967423.0);
  323. }
  324. /* divided by the smallest number that will generate a
  325. * single precision real number on 0<=x<1.
  326. * This needs to be slightly larger than MAX_UNIT since
  327. * we are limited to an accuracy of 1e-7.
  328. */
  329. }
  330. real
  331. gmx_rng_gaussian_table(gmx_rng_t rng)
  332. {
  333. unsigned int i;
  334. i = gmx_rng_uniform_uint32(rng);
  335. /* The Gaussian table is a static constant in this file */
  336. return gaussian_table[i >> (32 - GAUSS_TABLE)];
  337. }
  338. void
  339. gmx_rng_cycle_2uniform(gmx_int64_t ctr1, gmx_int64_t ctr2,
  340. gmx_int64_t key1, gmx_int64_t key2,
  341. double* rnd)
  342. {
  343. const gmx_int64_t mask_53bits = 0x1FFFFFFFFFFFFF;
  344. const double two_power_min53 = 1.0/9007199254740992.0;
  345. threefry2x64_ctr_t ctr = {{ctr1, ctr2}};
  346. threefry2x64_key_t key = {{key1, key2}};
  347. threefry2x64_ctr_t rand = threefry2x64(ctr, key);
  348. rnd[0] = (rand.v[0] & mask_53bits)*two_power_min53;
  349. rnd[1] = (rand.v[1] & mask_53bits)*two_power_min53;
  350. }
  351. void
  352. gmx_rng_cycle_3gaussian_table(gmx_int64_t ctr1, gmx_int64_t ctr2,
  353. gmx_int64_t key1, gmx_int64_t key2,
  354. real* rnd)
  355. {
  356. threefry2x64_ctr_t ctr = {{ctr1, ctr2}};
  357. threefry2x64_key_t key = {{key1, key2}};
  358. threefry2x64_ctr_t rand = threefry2x64(ctr, key);
  359. rnd[0] = gaussian_table[(rand.v[0] >> 48) & GAUSS_MASK];
  360. rnd[1] = gaussian_table[(rand.v[0] >> 32) & GAUSS_MASK];
  361. rnd[2] = gaussian_table[(rand.v[0] >> 16) & GAUSS_MASK];
  362. }
  363. void
  364. gmx_rng_cycle_6gaussian_table(gmx_int64_t ctr1, gmx_int64_t ctr2,
  365. gmx_int64_t key1, gmx_int64_t key2,
  366. real* rnd)
  367. {
  368. threefry2x64_ctr_t ctr = {{ctr1, ctr2}};
  369. threefry2x64_key_t key = {{key1, key2}};
  370. threefry2x64_ctr_t rand = threefry2x64(ctr, key);
  371. rnd[0] = gaussian_table[(rand.v[0] >> 48) & GAUSS_MASK];
  372. rnd[1] = gaussian_table[(rand.v[0] >> 32) & GAUSS_MASK];
  373. rnd[2] = gaussian_table[(rand.v[0] >> 16) & GAUSS_MASK];
  374. rnd[3] = gaussian_table[(rand.v[1] >> 48) & GAUSS_MASK];
  375. rnd[4] = gaussian_table[(rand.v[1] >> 32) & GAUSS_MASK];
  376. rnd[5] = gaussian_table[(rand.v[1] >> 16) & GAUSS_MASK];
  377. }