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