random.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. /* Implementation of the RANDOM intrinsics
  2. Copyright (C) 2002-2022 Free Software Foundation, Inc.
  3. Contributed by Lars Segerlund <seger@linuxmail.org>,
  4. Steve Kargl and Janne Blomqvist.
  5. This file is part of the GNU Fortran runtime library (libgfortran).
  6. Libgfortran is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public
  8. License as published by the Free Software Foundation; either
  9. version 3 of the License, or (at your option) any later version.
  10. Ligbfortran is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. Under Section 7 of GPL version 3, you are granted additional
  15. permissions described in the GCC Runtime Library Exception, version
  16. 3.1, as published by the Free Software Foundation.
  17. You should have received a copy of the GNU General Public License and
  18. a copy of the GCC Runtime Library Exception along with this program;
  19. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  20. <http://www.gnu.org/licenses/>. */
  21. /* For rand_s. */
  22. #define _CRT_RAND_S
  23. #include "libgfortran.h"
  24. #include <gthr.h>
  25. #include <string.h>
  26. #ifdef HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #include <sys/stat.h>
  30. #include <fcntl.h>
  31. #include "time_1.h"
  32. #ifdef HAVE_SYS_RANDOM_H
  33. #include <sys/random.h>
  34. #endif
  35. #ifdef __MINGW32__
  36. #define HAVE_GETPID 1
  37. #include <process.h>
  38. #include <_mingw.h> /* For __MINGW64_VERSION_MAJOR */
  39. #endif
  40. extern void random_r4 (GFC_REAL_4 *);
  41. iexport_proto(random_r4);
  42. extern void random_r8 (GFC_REAL_8 *);
  43. iexport_proto(random_r8);
  44. extern void arandom_r4 (gfc_array_r4 *);
  45. export_proto(arandom_r4);
  46. extern void arandom_r8 (gfc_array_r8 *);
  47. export_proto(arandom_r8);
  48. #ifdef HAVE_GFC_REAL_10
  49. extern void random_r10 (GFC_REAL_10 *);
  50. iexport_proto(random_r10);
  51. extern void arandom_r10 (gfc_array_r10 *);
  52. export_proto(arandom_r10);
  53. #endif
  54. #ifdef HAVE_GFC_REAL_16
  55. extern void random_r16 (GFC_REAL_16 *);
  56. iexport_proto(random_r16);
  57. extern void arandom_r16 (gfc_array_r16 *);
  58. export_proto(arandom_r16);
  59. #endif
  60. #ifdef HAVE_GFC_REAL_17
  61. extern void random_r17 (GFC_REAL_17 *);
  62. iexport_proto(random_r17);
  63. extern void arandom_r17 (gfc_array_r17 *);
  64. export_proto(arandom_r17);
  65. #endif
  66. #ifdef __GTHREAD_MUTEX_INIT
  67. static __gthread_mutex_t random_lock = __GTHREAD_MUTEX_INIT;
  68. #else
  69. static __gthread_mutex_t random_lock;
  70. #endif
  71. /* Helper routines to map a GFC_UINTEGER_* to the corresponding
  72. GFC_REAL_* types in the range of [0,1). If GFC_REAL_*_RADIX are 2
  73. or 16, respectively, we mask off the bits that don't fit into the
  74. correct GFC_REAL_*, convert to the real type, then multiply by the
  75. correct offset. */
  76. static void
  77. rnumber_4 (GFC_REAL_4 *f, GFC_UINTEGER_4 v)
  78. {
  79. GFC_UINTEGER_4 mask;
  80. #if GFC_REAL_4_RADIX == 2
  81. mask = ~ (GFC_UINTEGER_4) 0u << (32 - GFC_REAL_4_DIGITS);
  82. #elif GFC_REAL_4_RADIX == 16
  83. mask = ~ (GFC_UINTEGER_4) 0u << ((8 - GFC_REAL_4_DIGITS) * 4);
  84. #else
  85. #error "GFC_REAL_4_RADIX has unknown value"
  86. #endif
  87. v = v & mask;
  88. *f = (GFC_REAL_4) v * GFC_REAL_4_LITERAL(0x1.p-32);
  89. }
  90. static void
  91. rnumber_8 (GFC_REAL_8 *f, GFC_UINTEGER_8 v)
  92. {
  93. GFC_UINTEGER_8 mask;
  94. #if GFC_REAL_8_RADIX == 2
  95. mask = ~ (GFC_UINTEGER_8) 0u << (64 - GFC_REAL_8_DIGITS);
  96. #elif GFC_REAL_8_RADIX == 16
  97. mask = ~ (GFC_UINTEGER_8) 0u << (16 - GFC_REAL_8_DIGITS) * 4);
  98. #else
  99. #error "GFC_REAL_8_RADIX has unknown value"
  100. #endif
  101. v = v & mask;
  102. *f = (GFC_REAL_8) v * GFC_REAL_8_LITERAL(0x1.p-64);
  103. }
  104. #ifdef HAVE_GFC_REAL_10
  105. static void
  106. rnumber_10 (GFC_REAL_10 *f, GFC_UINTEGER_8 v)
  107. {
  108. GFC_UINTEGER_8 mask;
  109. #if GFC_REAL_10_RADIX == 2
  110. mask = ~ (GFC_UINTEGER_8) 0u << (64 - GFC_REAL_10_DIGITS);
  111. #elif GFC_REAL_10_RADIX == 16
  112. mask = ~ (GFC_UINTEGER_10) 0u << ((16 - GFC_REAL_10_DIGITS) * 4);
  113. #else
  114. #error "GFC_REAL_10_RADIX has unknown value"
  115. #endif
  116. v = v & mask;
  117. *f = (GFC_REAL_10) v * GFC_REAL_10_LITERAL(0x1.p-64);
  118. }
  119. #endif
  120. #ifdef HAVE_GFC_REAL_16
  121. /* For REAL(KIND=16), we only need to mask off the lower bits. */
  122. static void
  123. rnumber_16 (GFC_REAL_16 *f, GFC_UINTEGER_8 v1, GFC_UINTEGER_8 v2)
  124. {
  125. GFC_UINTEGER_8 mask;
  126. #if GFC_REAL_16_RADIX == 2
  127. mask = ~ (GFC_UINTEGER_8) 0u << (128 - GFC_REAL_16_DIGITS);
  128. #elif GFC_REAL_16_RADIX == 16
  129. mask = ~ (GFC_UINTEGER_8) 0u << ((32 - GFC_REAL_16_DIGITS) * 4);
  130. #else
  131. #error "GFC_REAL_16_RADIX has unknown value"
  132. #endif
  133. v2 = v2 & mask;
  134. *f = (GFC_REAL_16) v1 * GFC_REAL_16_LITERAL(0x1.p-64)
  135. + (GFC_REAL_16) v2 * GFC_REAL_16_LITERAL(0x1.p-128);
  136. }
  137. #endif
  138. #ifdef HAVE_GFC_REAL_17
  139. /* For REAL(KIND=16), we only need to mask off the lower bits. */
  140. static void
  141. rnumber_17 (GFC_REAL_17 *f, GFC_UINTEGER_8 v1, GFC_UINTEGER_8 v2)
  142. {
  143. GFC_UINTEGER_8 mask;
  144. #if GFC_REAL_17_RADIX == 2
  145. mask = ~ (GFC_UINTEGER_8) 0u << (128 - GFC_REAL_17_DIGITS);
  146. #elif GFC_REAL_17_RADIX == 16
  147. mask = ~ (GFC_UINTEGER_8) 0u << ((32 - GFC_REAL_17_DIGITS) * 4);
  148. #else
  149. #error "GFC_REAL_17_RADIX has unknown value"
  150. #endif
  151. v2 = v2 & mask;
  152. *f = (GFC_REAL_17) v1 * GFC_REAL_17_LITERAL(0x1.p-64)
  153. + (GFC_REAL_17) v2 * GFC_REAL_17_LITERAL(0x1.p-128);
  154. }
  155. #endif
  156. /*
  157. We use the xoshiro256** generator, a fast high-quality generator
  158. that:
  159. - passes TestU1 without any failures
  160. - provides a "jump" function making it easy to provide many
  161. independent parallel streams.
  162. - Long period of 2**256 - 1
  163. A description can be found at
  164. http://prng.di.unimi.it/
  165. or
  166. https://arxiv.org/abs/1805.01407
  167. The paper includes public domain source code which is the basis for
  168. the implementation below.
  169. */
  170. typedef struct
  171. {
  172. bool init;
  173. uint64_t s[4];
  174. }
  175. prng_state;
  176. /* master_state is the only variable protected by random_lock. */
  177. static prng_state master_state = { .init = false, .s = {
  178. 0xad63fa1ed3b55f36ULL, 0xd94473e78978b497ULL, 0xbc60592a98172477ULL,
  179. 0xa3de7c6e81265301ULL }
  180. };
  181. static __gthread_key_t rand_state_key;
  182. static prng_state*
  183. get_rand_state (void)
  184. {
  185. /* For single threaded apps. */
  186. static prng_state rand_state;
  187. if (__gthread_active_p ())
  188. {
  189. void* p = __gthread_getspecific (rand_state_key);
  190. if (!p)
  191. {
  192. p = xcalloc (1, sizeof (prng_state));
  193. __gthread_setspecific (rand_state_key, p);
  194. }
  195. return p;
  196. }
  197. else
  198. return &rand_state;
  199. }
  200. static inline uint64_t
  201. rotl (const uint64_t x, int k)
  202. {
  203. return (x << k) | (x >> (64 - k));
  204. }
  205. static uint64_t
  206. prng_next (prng_state* rs)
  207. {
  208. const uint64_t result = rotl(rs->s[1] * 5, 7) * 9;
  209. const uint64_t t = rs->s[1] << 17;
  210. rs->s[2] ^= rs->s[0];
  211. rs->s[3] ^= rs->s[1];
  212. rs->s[1] ^= rs->s[2];
  213. rs->s[0] ^= rs->s[3];
  214. rs->s[2] ^= t;
  215. rs->s[3] = rotl(rs->s[3], 45);
  216. return result;
  217. }
  218. /* This is the jump function for the generator. It is equivalent to
  219. 2^128 calls to prng_next(); it can be used to generate 2^128
  220. non-overlapping subsequences for parallel computations. */
  221. static void
  222. jump (prng_state* rs)
  223. {
  224. static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
  225. uint64_t s0 = 0;
  226. uint64_t s1 = 0;
  227. uint64_t s2 = 0;
  228. uint64_t s3 = 0;
  229. for(size_t i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
  230. for(int b = 0; b < 64; b++) {
  231. if (JUMP[i] & UINT64_C(1) << b) {
  232. s0 ^= rs->s[0];
  233. s1 ^= rs->s[1];
  234. s2 ^= rs->s[2];
  235. s3 ^= rs->s[3];
  236. }
  237. prng_next (rs);
  238. }
  239. rs->s[0] = s0;
  240. rs->s[1] = s1;
  241. rs->s[2] = s2;
  242. rs->s[3] = s3;
  243. }
  244. /* Splitmix64 recommended by xoshiro author for initializing. After
  245. getting one uint64_t value from the OS, this is used to fill in the
  246. rest of the xoshiro state. */
  247. static uint64_t
  248. splitmix64 (uint64_t x)
  249. {
  250. uint64_t z = (x += 0x9e3779b97f4a7c15);
  251. z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
  252. z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
  253. return z ^ (z >> 31);
  254. }
  255. /* Get some bytes from the operating system in order to seed
  256. the PRNG. */
  257. static int
  258. getosrandom (void *buf, size_t buflen)
  259. {
  260. /* rand_s is available in MinGW-w64 but not plain MinGW. */
  261. #if defined(__MINGW64_VERSION_MAJOR)
  262. unsigned int* b = buf;
  263. for (size_t i = 0; i < buflen / sizeof (unsigned int); i++)
  264. rand_s (&b[i]);
  265. return buflen;
  266. #else
  267. #ifdef HAVE_GETENTROPY
  268. if (getentropy (buf, buflen) == 0)
  269. return buflen;
  270. #endif
  271. int flags = O_RDONLY;
  272. #ifdef O_CLOEXEC
  273. flags |= O_CLOEXEC;
  274. #endif
  275. int fd = open("/dev/urandom", flags);
  276. if (fd != -1)
  277. {
  278. int res = read(fd, buf, buflen);
  279. close (fd);
  280. return res;
  281. }
  282. uint64_t seed = 0x047f7684e9fc949dULL;
  283. time_t secs;
  284. long usecs;
  285. if (gf_gettime (&secs, &usecs) == 0)
  286. {
  287. seed ^= secs;
  288. seed ^= usecs;
  289. }
  290. #ifdef HAVE_GETPID
  291. pid_t pid = getpid();
  292. seed ^= pid;
  293. #endif
  294. size_t size = buflen < sizeof (uint64_t) ? buflen : sizeof (uint64_t);
  295. memcpy (buf, &seed, size);
  296. return size;
  297. #endif /* __MINGW64_VERSION_MAJOR */
  298. }
  299. /* Initialize the random number generator for the current thread,
  300. using the master state and the number of times we must jump. */
  301. static void
  302. init_rand_state (prng_state* rs, const bool locked)
  303. {
  304. if (!locked)
  305. __gthread_mutex_lock (&random_lock);
  306. if (!master_state.init)
  307. {
  308. uint64_t os_seed;
  309. getosrandom (&os_seed, sizeof (os_seed));
  310. for (uint64_t i = 0; i < sizeof (master_state.s) / sizeof (uint64_t); i++)
  311. {
  312. os_seed = splitmix64 (os_seed);
  313. master_state.s[i] = os_seed;
  314. }
  315. master_state.init = true;
  316. }
  317. memcpy (&rs->s, master_state.s, sizeof (master_state.s));
  318. jump (&master_state);
  319. if (!locked)
  320. __gthread_mutex_unlock (&random_lock);
  321. rs->init = true;
  322. }
  323. /* This function produces a REAL(4) value from the uniform distribution
  324. with range [0,1). */
  325. void
  326. random_r4 (GFC_REAL_4 *x)
  327. {
  328. prng_state* rs = get_rand_state();
  329. if (unlikely (!rs->init))
  330. init_rand_state (rs, false);
  331. uint64_t r = prng_next (rs);
  332. /* Take the higher bits, ensuring that a stream of real(4), real(8),
  333. and real(10) will be identical (except for precision). */
  334. uint32_t high = (uint32_t) (r >> 32);
  335. rnumber_4 (x, high);
  336. }
  337. iexport(random_r4);
  338. /* This function produces a REAL(8) value from the uniform distribution
  339. with range [0,1). */
  340. void
  341. random_r8 (GFC_REAL_8 *x)
  342. {
  343. GFC_UINTEGER_8 r;
  344. prng_state* rs = get_rand_state();
  345. if (unlikely (!rs->init))
  346. init_rand_state (rs, false);
  347. r = prng_next (rs);
  348. rnumber_8 (x, r);
  349. }
  350. iexport(random_r8);
  351. #ifdef HAVE_GFC_REAL_10
  352. /* This function produces a REAL(10) value from the uniform distribution
  353. with range [0,1). */
  354. void
  355. random_r10 (GFC_REAL_10 *x)
  356. {
  357. GFC_UINTEGER_8 r;
  358. prng_state* rs = get_rand_state();
  359. if (unlikely (!rs->init))
  360. init_rand_state (rs, false);
  361. r = prng_next (rs);
  362. rnumber_10 (x, r);
  363. }
  364. iexport(random_r10);
  365. #endif
  366. /* This function produces a REAL(16) value from the uniform distribution
  367. with range [0,1). */
  368. #ifdef HAVE_GFC_REAL_16
  369. void
  370. random_r16 (GFC_REAL_16 *x)
  371. {
  372. GFC_UINTEGER_8 r1, r2;
  373. prng_state* rs = get_rand_state();
  374. if (unlikely (!rs->init))
  375. init_rand_state (rs, false);
  376. r1 = prng_next (rs);
  377. r2 = prng_next (rs);
  378. rnumber_16 (x, r1, r2);
  379. }
  380. iexport(random_r16);
  381. #endif
  382. /* This function produces a REAL(16) value from the uniform distribution
  383. with range [0,1). */
  384. #ifdef HAVE_GFC_REAL_17
  385. void
  386. random_r17 (GFC_REAL_17 *x)
  387. {
  388. GFC_UINTEGER_8 r1, r2;
  389. prng_state* rs = get_rand_state();
  390. if (unlikely (!rs->init))
  391. init_rand_state (rs, false);
  392. r1 = prng_next (rs);
  393. r2 = prng_next (rs);
  394. rnumber_17 (x, r1, r2);
  395. }
  396. iexport(random_r17);
  397. #endif
  398. /* This function fills a REAL(4) array with values from the uniform
  399. distribution with range [0,1). */
  400. void
  401. arandom_r4 (gfc_array_r4 *x)
  402. {
  403. index_type count[GFC_MAX_DIMENSIONS];
  404. index_type extent[GFC_MAX_DIMENSIONS];
  405. index_type stride[GFC_MAX_DIMENSIONS];
  406. index_type stride0;
  407. index_type dim;
  408. GFC_REAL_4 *dest;
  409. prng_state* rs = get_rand_state();
  410. dest = x->base_addr;
  411. dim = GFC_DESCRIPTOR_RANK (x);
  412. for (index_type n = 0; n < dim; n++)
  413. {
  414. count[n] = 0;
  415. stride[n] = GFC_DESCRIPTOR_STRIDE(x,n);
  416. extent[n] = GFC_DESCRIPTOR_EXTENT(x,n);
  417. if (extent[n] <= 0)
  418. return;
  419. }
  420. stride0 = stride[0];
  421. if (unlikely (!rs->init))
  422. init_rand_state (rs, false);
  423. while (dest)
  424. {
  425. /* random_r4 (dest); */
  426. uint64_t r = prng_next (rs);
  427. uint32_t high = (uint32_t) (r >> 32);
  428. rnumber_4 (dest, high);
  429. /* Advance to the next element. */
  430. dest += stride0;
  431. count[0]++;
  432. /* Advance to the next source element. */
  433. index_type n = 0;
  434. while (count[n] == extent[n])
  435. {
  436. /* When we get to the end of a dimension, reset it and increment
  437. the next dimension. */
  438. count[n] = 0;
  439. /* We could precalculate these products, but this is a less
  440. frequently used path so probably not worth it. */
  441. dest -= stride[n] * extent[n];
  442. n++;
  443. if (n == dim)
  444. {
  445. dest = NULL;
  446. break;
  447. }
  448. else
  449. {
  450. count[n]++;
  451. dest += stride[n];
  452. }
  453. }
  454. }
  455. }
  456. /* This function fills a REAL(8) array with values from the uniform
  457. distribution with range [0,1). */
  458. void
  459. arandom_r8 (gfc_array_r8 *x)
  460. {
  461. index_type count[GFC_MAX_DIMENSIONS];
  462. index_type extent[GFC_MAX_DIMENSIONS];
  463. index_type stride[GFC_MAX_DIMENSIONS];
  464. index_type stride0;
  465. index_type dim;
  466. GFC_REAL_8 *dest;
  467. prng_state* rs = get_rand_state();
  468. dest = x->base_addr;
  469. dim = GFC_DESCRIPTOR_RANK (x);
  470. for (index_type n = 0; n < dim; n++)
  471. {
  472. count[n] = 0;
  473. stride[n] = GFC_DESCRIPTOR_STRIDE(x,n);
  474. extent[n] = GFC_DESCRIPTOR_EXTENT(x,n);
  475. if (extent[n] <= 0)
  476. return;
  477. }
  478. stride0 = stride[0];
  479. if (unlikely (!rs->init))
  480. init_rand_state (rs, false);
  481. while (dest)
  482. {
  483. /* random_r8 (dest); */
  484. uint64_t r = prng_next (rs);
  485. rnumber_8 (dest, r);
  486. /* Advance to the next element. */
  487. dest += stride0;
  488. count[0]++;
  489. /* Advance to the next source element. */
  490. index_type n = 0;
  491. while (count[n] == extent[n])
  492. {
  493. /* When we get to the end of a dimension, reset it and increment
  494. the next dimension. */
  495. count[n] = 0;
  496. /* We could precalculate these products, but this is a less
  497. frequently used path so probably not worth it. */
  498. dest -= stride[n] * extent[n];
  499. n++;
  500. if (n == dim)
  501. {
  502. dest = NULL;
  503. break;
  504. }
  505. else
  506. {
  507. count[n]++;
  508. dest += stride[n];
  509. }
  510. }
  511. }
  512. }
  513. #ifdef HAVE_GFC_REAL_10
  514. /* This function fills a REAL(10) array with values from the uniform
  515. distribution with range [0,1). */
  516. void
  517. arandom_r10 (gfc_array_r10 *x)
  518. {
  519. index_type count[GFC_MAX_DIMENSIONS];
  520. index_type extent[GFC_MAX_DIMENSIONS];
  521. index_type stride[GFC_MAX_DIMENSIONS];
  522. index_type stride0;
  523. index_type dim;
  524. GFC_REAL_10 *dest;
  525. prng_state* rs = get_rand_state();
  526. dest = x->base_addr;
  527. dim = GFC_DESCRIPTOR_RANK (x);
  528. for (index_type n = 0; n < dim; n++)
  529. {
  530. count[n] = 0;
  531. stride[n] = GFC_DESCRIPTOR_STRIDE(x,n);
  532. extent[n] = GFC_DESCRIPTOR_EXTENT(x,n);
  533. if (extent[n] <= 0)
  534. return;
  535. }
  536. stride0 = stride[0];
  537. if (unlikely (!rs->init))
  538. init_rand_state (rs, false);
  539. while (dest)
  540. {
  541. /* random_r10 (dest); */
  542. uint64_t r = prng_next (rs);
  543. rnumber_10 (dest, r);
  544. /* Advance to the next element. */
  545. dest += stride0;
  546. count[0]++;
  547. /* Advance to the next source element. */
  548. index_type n = 0;
  549. while (count[n] == extent[n])
  550. {
  551. /* When we get to the end of a dimension, reset it and increment
  552. the next dimension. */
  553. count[n] = 0;
  554. /* We could precalculate these products, but this is a less
  555. frequently used path so probably not worth it. */
  556. dest -= stride[n] * extent[n];
  557. n++;
  558. if (n == dim)
  559. {
  560. dest = NULL;
  561. break;
  562. }
  563. else
  564. {
  565. count[n]++;
  566. dest += stride[n];
  567. }
  568. }
  569. }
  570. }
  571. #endif
  572. #ifdef HAVE_GFC_REAL_16
  573. /* This function fills a REAL(16) array with values from the uniform
  574. distribution with range [0,1). */
  575. void
  576. arandom_r16 (gfc_array_r16 *x)
  577. {
  578. index_type count[GFC_MAX_DIMENSIONS];
  579. index_type extent[GFC_MAX_DIMENSIONS];
  580. index_type stride[GFC_MAX_DIMENSIONS];
  581. index_type stride0;
  582. index_type dim;
  583. GFC_REAL_16 *dest;
  584. prng_state* rs = get_rand_state();
  585. dest = x->base_addr;
  586. dim = GFC_DESCRIPTOR_RANK (x);
  587. for (index_type n = 0; n < dim; n++)
  588. {
  589. count[n] = 0;
  590. stride[n] = GFC_DESCRIPTOR_STRIDE(x,n);
  591. extent[n] = GFC_DESCRIPTOR_EXTENT(x,n);
  592. if (extent[n] <= 0)
  593. return;
  594. }
  595. stride0 = stride[0];
  596. if (unlikely (!rs->init))
  597. init_rand_state (rs, false);
  598. while (dest)
  599. {
  600. /* random_r16 (dest); */
  601. uint64_t r1 = prng_next (rs);
  602. uint64_t r2 = prng_next (rs);
  603. rnumber_16 (dest, r1, r2);
  604. /* Advance to the next element. */
  605. dest += stride0;
  606. count[0]++;
  607. /* Advance to the next source element. */
  608. index_type n = 0;
  609. while (count[n] == extent[n])
  610. {
  611. /* When we get to the end of a dimension, reset it and increment
  612. the next dimension. */
  613. count[n] = 0;
  614. /* We could precalculate these products, but this is a less
  615. frequently used path so probably not worth it. */
  616. dest -= stride[n] * extent[n];
  617. n++;
  618. if (n == dim)
  619. {
  620. dest = NULL;
  621. break;
  622. }
  623. else
  624. {
  625. count[n]++;
  626. dest += stride[n];
  627. }
  628. }
  629. }
  630. }
  631. #endif
  632. #ifdef HAVE_GFC_REAL_17
  633. /* This function fills a REAL(16) array with values from the uniform
  634. distribution with range [0,1). */
  635. void
  636. arandom_r17 (gfc_array_r17 *x)
  637. {
  638. index_type count[GFC_MAX_DIMENSIONS];
  639. index_type extent[GFC_MAX_DIMENSIONS];
  640. index_type stride[GFC_MAX_DIMENSIONS];
  641. index_type stride0;
  642. index_type dim;
  643. GFC_REAL_17 *dest;
  644. prng_state* rs = get_rand_state();
  645. dest = x->base_addr;
  646. dim = GFC_DESCRIPTOR_RANK (x);
  647. for (index_type n = 0; n < dim; n++)
  648. {
  649. count[n] = 0;
  650. stride[n] = GFC_DESCRIPTOR_STRIDE(x,n);
  651. extent[n] = GFC_DESCRIPTOR_EXTENT(x,n);
  652. if (extent[n] <= 0)
  653. return;
  654. }
  655. stride0 = stride[0];
  656. if (unlikely (!rs->init))
  657. init_rand_state (rs, false);
  658. while (dest)
  659. {
  660. /* random_r17 (dest); */
  661. uint64_t r1 = prng_next (rs);
  662. uint64_t r2 = prng_next (rs);
  663. rnumber_17 (dest, r1, r2);
  664. /* Advance to the next element. */
  665. dest += stride0;
  666. count[0]++;
  667. /* Advance to the next source element. */
  668. index_type n = 0;
  669. while (count[n] == extent[n])
  670. {
  671. /* When we get to the end of a dimension, reset it and increment
  672. the next dimension. */
  673. count[n] = 0;
  674. /* We could precalculate these products, but this is a less
  675. frequently used path so probably not worth it. */
  676. dest -= stride[n] * extent[n];
  677. n++;
  678. if (n == dim)
  679. {
  680. dest = NULL;
  681. break;
  682. }
  683. else
  684. {
  685. count[n]++;
  686. dest += stride[n];
  687. }
  688. }
  689. }
  690. }
  691. #endif
  692. /* Number of elements in master_state array. */
  693. #define SZU64 (sizeof (master_state.s) / sizeof (uint64_t))
  694. /* Equivalent number of elements in an array of GFC_INTEGER_{4,8}. */
  695. #define SZ_IN_INT_4 (SZU64 * (sizeof (uint64_t) / sizeof (GFC_INTEGER_4)))
  696. #define SZ_IN_INT_8 (SZU64 * (sizeof (uint64_t) / sizeof (GFC_INTEGER_8)))
  697. /* Keys for scrambling the seed in order to avoid poor seeds. */
  698. static const uint64_t xor_keys[] = {
  699. 0xbd0c5b6e50c2df49ULL, 0xd46061cd46e1df38ULL, 0xbb4f4d4ed6103544ULL,
  700. 0x114a583d0756ad39ULL
  701. };
  702. /* Since a XOR cipher is symmetric, we need only one routine, and we
  703. can use it both for encryption and decryption. */
  704. static void
  705. scramble_seed (uint64_t *dest, const uint64_t *src)
  706. {
  707. for (size_t i = 0; i < SZU64; i++)
  708. dest[i] = src[i] ^ xor_keys[i];
  709. }
  710. /* random_seed is used to seed the PRNG with either a default
  711. set of seeds or user specified set of seeds. random_seed
  712. must be called with no argument or exactly one argument. */
  713. void
  714. random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get)
  715. {
  716. uint64_t seed[SZU64];
  717. /* Check that we only have one argument present. */
  718. if ((size ? 1 : 0) + (put ? 1 : 0) + (get ? 1 : 0) > 1)
  719. runtime_error ("RANDOM_SEED should have at most one argument present.");
  720. if (size != NULL)
  721. *size = SZ_IN_INT_4;
  722. prng_state* rs = get_rand_state();
  723. /* Return the seed to GET data. */
  724. if (get != NULL)
  725. {
  726. /* If the rank of the array is not 1, abort. */
  727. if (GFC_DESCRIPTOR_RANK (get) != 1)
  728. runtime_error ("Array rank of GET is not 1.");
  729. /* If the array is too small, abort. */
  730. if (GFC_DESCRIPTOR_EXTENT(get,0) < (index_type) SZ_IN_INT_4)
  731. runtime_error ("Array size of GET is too small.");
  732. if (!rs->init)
  733. init_rand_state (rs, false);
  734. /* Unscramble the seed. */
  735. scramble_seed (seed, rs->s);
  736. /* Then copy it back to the user variable. */
  737. for (size_t i = 0; i < SZ_IN_INT_4 ; i++)
  738. memcpy (&(get->base_addr[(SZ_IN_INT_4 - 1 - i) *
  739. GFC_DESCRIPTOR_STRIDE(get,0)]),
  740. (unsigned char*) seed + i * sizeof(GFC_UINTEGER_4),
  741. sizeof(GFC_UINTEGER_4));
  742. }
  743. else
  744. {
  745. __gthread_mutex_lock (&random_lock);
  746. /* From the standard: "If no argument is present, the processor assigns
  747. a processor-dependent value to the seed." */
  748. if (size == NULL && put == NULL && get == NULL)
  749. {
  750. master_state.init = false;
  751. init_rand_state (rs, true);
  752. }
  753. if (put != NULL)
  754. {
  755. /* If the rank of the array is not 1, abort. */
  756. if (GFC_DESCRIPTOR_RANK (put) != 1)
  757. runtime_error ("Array rank of PUT is not 1.");
  758. /* If the array is too small, abort. */
  759. if (GFC_DESCRIPTOR_EXTENT(put,0) < (index_type) SZ_IN_INT_4)
  760. runtime_error ("Array size of PUT is too small.");
  761. /* We copy the seed given by the user. */
  762. for (size_t i = 0; i < SZ_IN_INT_4; i++)
  763. memcpy ((unsigned char*) seed + i * sizeof(GFC_UINTEGER_4),
  764. &(put->base_addr[(SZ_IN_INT_4 - 1 - i) *
  765. GFC_DESCRIPTOR_STRIDE(put,0)]),
  766. sizeof(GFC_UINTEGER_4));
  767. /* We put it after scrambling the bytes, to paper around users who
  768. provide seeds with quality only in the lower or upper part. */
  769. scramble_seed (master_state.s, seed);
  770. master_state.init = true;
  771. init_rand_state (rs, true);
  772. }
  773. __gthread_mutex_unlock (&random_lock);
  774. }
  775. }
  776. iexport(random_seed_i4);
  777. void
  778. random_seed_i8 (GFC_INTEGER_8 *size, gfc_array_i8 *put, gfc_array_i8 *get)
  779. {
  780. uint64_t seed[SZU64];
  781. /* Check that we only have one argument present. */
  782. if ((size ? 1 : 0) + (put ? 1 : 0) + (get ? 1 : 0) > 1)
  783. runtime_error ("RANDOM_SEED should have at most one argument present.");
  784. if (size != NULL)
  785. *size = SZ_IN_INT_8;
  786. prng_state* rs = get_rand_state();
  787. /* Return the seed to GET data. */
  788. if (get != NULL)
  789. {
  790. /* If the rank of the array is not 1, abort. */
  791. if (GFC_DESCRIPTOR_RANK (get) != 1)
  792. runtime_error ("Array rank of GET is not 1.");
  793. /* If the array is too small, abort. */
  794. if (GFC_DESCRIPTOR_EXTENT(get,0) < (index_type) SZ_IN_INT_8)
  795. runtime_error ("Array size of GET is too small.");
  796. if (!rs->init)
  797. init_rand_state (rs, false);
  798. /* Unscramble the seed. */
  799. scramble_seed (seed, rs->s);
  800. /* This code now should do correct strides. */
  801. for (size_t i = 0; i < SZ_IN_INT_8; i++)
  802. memcpy (&(get->base_addr[i * GFC_DESCRIPTOR_STRIDE(get,0)]), &seed[i],
  803. sizeof (GFC_UINTEGER_8));
  804. }
  805. else
  806. {
  807. __gthread_mutex_lock (&random_lock);
  808. /* From the standard: "If no argument is present, the processor assigns
  809. a processor-dependent value to the seed." */
  810. if (size == NULL && put == NULL && get == NULL)
  811. {
  812. master_state.init = false;
  813. init_rand_state (rs, true);
  814. }
  815. if (put != NULL)
  816. {
  817. /* If the rank of the array is not 1, abort. */
  818. if (GFC_DESCRIPTOR_RANK (put) != 1)
  819. runtime_error ("Array rank of PUT is not 1.");
  820. /* If the array is too small, abort. */
  821. if (GFC_DESCRIPTOR_EXTENT(put,0) < (index_type) SZ_IN_INT_8)
  822. runtime_error ("Array size of PUT is too small.");
  823. /* This code now should do correct strides. */
  824. for (size_t i = 0; i < SZ_IN_INT_8; i++)
  825. memcpy (&seed[i], &(put->base_addr[i * GFC_DESCRIPTOR_STRIDE(put,0)]),
  826. sizeof (GFC_UINTEGER_8));
  827. scramble_seed (master_state.s, seed);
  828. master_state.init = true;
  829. init_rand_state (rs, true);
  830. }
  831. __gthread_mutex_unlock (&random_lock);
  832. }
  833. }
  834. iexport(random_seed_i8);
  835. #if !defined __GTHREAD_MUTEX_INIT || defined __GTHREADS
  836. static void __attribute__((constructor))
  837. constructor_random (void)
  838. {
  839. #ifndef __GTHREAD_MUTEX_INIT
  840. __GTHREAD_MUTEX_INIT_FUNCTION (&random_lock);
  841. #endif
  842. if (__gthread_active_p ())
  843. __gthread_key_create (&rand_state_key, &free);
  844. }
  845. #endif
  846. #ifdef __GTHREADS
  847. static void __attribute__((destructor))
  848. destructor_random (void)
  849. {
  850. if (__gthread_active_p ())
  851. __gthread_key_delete (rand_state_key);
  852. }
  853. #endif