1 /* Implementation of the RANDOM intrinsics
2 Copyright 2002, 2004 Free Software Foundation, Inc.
3 Contributed by Lars Segerlund <seger@linuxmail.org>
6 This file is part of the GNU Fortran 95 runtime library (libgfortran).
8 Libgfortran is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 Ligbfortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with libgfor; see the file COPYING.LIB. If not,
20 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #include "libgfortran.h"
25 extern void random_r4 (GFC_REAL_4 *);
26 iexport_proto(random_r4);
28 extern void random_r8 (GFC_REAL_8 *);
29 iexport_proto(random_r8);
31 extern void arandom_r4 (gfc_array_r4 *);
32 export_proto(arandom_r4);
34 extern void arandom_r8 (gfc_array_r8 *);
35 export_proto(arandom_r8);
39 /* The Mersenne Twister code is currently commented out due to
41 (1) Simple user specified seeds lead to really bad sequences for
42 nearly 100000 random numbers.
43 (2) open(), read(), and close() are not properly declared via header
45 (3) The global index i is abused and causes unexpected behavior with
49 The algorithm was taken from the paper :
51 Mersenne Twister: 623-dimensionally equidistributed
52 uniform pseudorandom generator.
57 Which appeared in the: ACM Transactions on Modelling and Computer
58 Simulations: Special Issue on Uniform Random Number
59 Generation. ( Early in 1998 ). */
64 #include <sys/types.h>
72 /*Use the 'big' generator by default ( period -> 2**19937 ). */
76 /* Define the necessary constants for the algorithm. */
81 N = 624, M = 397, R = 19, TU = 11, TS = 7, TT = 15, TL = 17
83 #define M_A 0x9908B0DF
84 #define T_B 0x9D2C5680
85 #define T_C 0xEFC60000
89 N = 351, M = 175, R = 19, TU = 11, TS = 7, TT = 15, TL = 17
91 #define M_A 0xE4BD75F5
92 #define T_B 0x655E5280
93 #define T_C 0xFFD58000
97 static unsigned int seed[N];
99 /* This is the routine which handles the seeding of the generator,
100 and also reading and writing of the seed. */
103 random_seed (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get)
105 /* Initialize the seed in system dependent manner. */
106 if (get == NULL && put == NULL && size == NULL)
109 fd = open ("/dev/urandom", O_RDONLY);
112 /* We dont have urandom. */
113 GFC_UINTEGER_4 s = (GFC_UINTEGER_4) seed;
114 for (i = 0; i < N; i++)
116 s = s * 29943829 - 1;
122 /* Using urandom, might have a length issue. */
123 read (fd, &seed[0], sizeof (GFC_UINTEGER_4) * N);
129 /* Return the size of the seed */
136 /* if we have gotten to this pount we have a get or put
137 * now we check it the array fulfills the demands in the standard .
140 /* Set the seed to PUT data */
143 /* if the rank of the array is not 1 abort */
144 if (GFC_DESCRIPTOR_RANK (put) != 1)
147 /* if the array is too small abort */
148 if (((put->dim[0].ubound + 1 - put->dim[0].lbound)) < N)
151 /* If this is the case the array is a temporary */
152 if (put->dim[0].stride == 0)
155 /* This code now should do correct strides. */
156 for (i = 0; i < N; i++)
157 seed[i] = put->data[i * put->dim[0].stride];
160 /* Return the seed to GET data */
163 /* if the rank of the array is not 1 abort */
164 if (GFC_DESCRIPTOR_RANK (get) != 1)
167 /* if the array is too small abort */
168 if (((get->dim[0].ubound + 1 - get->dim[0].lbound)) < N)
171 /* If this is the case the array is a temporary */
172 if (get->dim[0].stride == 0)
175 /* This code now should do correct strides. */
176 for (i = 0; i < N; i++)
177 get->data[i * get->dim[0].stride] = seed[i];
180 iexport(random_seed);
182 /* Here is the internal routine which generates the random numbers
183 in 'batches' based upon the need for a new batch.
184 It's an integer based routine known as 'Mersenne Twister'.
185 This implementation still lacks 'tempering' and a good verification,
186 but gives very good metrics. */
189 random_generate (void)
194 /* Generate batch of N. */
196 for (k = 0, m = M; k < N - 1; k++)
198 y = (seed[k] & (-1 << R)) | (seed[k + 1] & ((1u << R) - 1));
199 seed[k] = seed[m] ^ (y >> 1) ^ (-(GFC_INTEGER_4) (y & 1) & M_A);
204 y = (seed[N - 1] & (-1 << R)) | (seed[0] & ((1u << R) - 1));
205 seed[N - 1] = seed[M - 1] ^ (y >> 1) ^ (-(GFC_INTEGER_4) (y & 1) & M_A);
209 /* A routine to return a REAL(KIND=4). */
212 random_r4 (GFC_REAL_4 * harv)
214 /* Regenerate if we need to. */
218 /* Convert uint32 to REAL(KIND=4). */
219 *harv = (GFC_REAL_4) ((GFC_REAL_4) (GFC_UINTEGER_4) seed[i++] /
220 (GFC_REAL_4) (~(GFC_UINTEGER_4) 0));
224 /* A routine to return a REAL(KIND=8). */
227 random_r8 (GFC_REAL_8 * harv)
229 /* Regenerate if we need to, may waste one 32-bit value. */
233 /* Convert two uint32 to a REAL(KIND=8). */
234 *harv = ((GFC_REAL_8) ((((GFC_UINTEGER_8) seed[i+1]) << 32) + seed[i])) /
235 (GFC_REAL_8) (~(GFC_UINTEGER_8) 0);
240 /* Code to handle arrays will follow here. */
242 /* REAL(KIND=4) REAL array. */
245 arandom_r4 (gfc_array_r4 * harv)
247 index_type count[GFC_MAX_DIMENSIONS - 1];
248 index_type extent[GFC_MAX_DIMENSIONS - 1];
249 index_type stride[GFC_MAX_DIMENSIONS - 1];
257 if (harv->dim[0].stride == 0)
258 harv->dim[0].stride = 1;
260 dim = GFC_DESCRIPTOR_RANK (harv);
262 for (n = 0; n < dim; n++)
265 stride[n] = harv->dim[n].stride;
266 extent[n] = harv->dim[n].ubound + 1 - harv->dim[n].lbound;
275 /* Set the elements. */
277 /* regenerate if we need to */
281 /* Convert uint32 to float in a hopefully g95 compiant manner */
282 *dest = (GFC_REAL_4) ((GFC_REAL_4) (GFC_UINTEGER_4) seed[i++] /
283 (GFC_REAL_4) (~(GFC_UINTEGER_4) 0));
285 /* Advance to the next element. */
288 /* Advance to the next source element. */
290 while (count[n] == extent[n])
292 /* When we get to the end of a dimension,
293 reset it and increment
294 the next dimension. */
296 /* We could precalculate these products,
298 frequently used path so proabably not worth it. */
299 dest -= stride[n] * extent[n];
315 /* REAL(KIND=8) array. */
318 arandom_r8 (gfc_array_r8 * harv)
320 index_type count[GFC_MAX_DIMENSIONS - 1];
321 index_type extent[GFC_MAX_DIMENSIONS - 1];
322 index_type stride[GFC_MAX_DIMENSIONS - 1];
330 if (harv->dim[0].stride == 0)
331 harv->dim[0].stride = 1;
333 dim = GFC_DESCRIPTOR_RANK (harv);
335 for (n = 0; n < dim; n++)
338 stride[n] = harv->dim[n].stride;
339 extent[n] = harv->dim[n].ubound + 1 - harv->dim[n].lbound;
348 /* Set the elements. */
350 /* regenerate if we need to, may waste one 32-bit value */
354 /* Convert two uint32 to a REAL(KIND=8). */
355 *dest = ((GFC_REAL_8) ((((GFC_UINTEGER_8) seed[i+1]) << 32) + seed[i])) /
356 (GFC_REAL_8) (~(GFC_UINTEGER_8) 0);
359 /* Advance to the next element. */
362 /* Advance to the next source element. */
364 while (count[n] == extent[n])
366 /* When we get to the end of a dimension,
367 reset it and increment
368 the next dimension. */
370 /* We could precalculate these products,
372 frequently used path so proabably not worth it. */
373 dest -= stride[n] * extent[n];
391 /* George Marsaglia's KISS (Keep It Simple Stupid) random number generator.
395 (1) The congruential generator x(n)=69069*x(n-1)+1327217885 with a period
397 (2) A 3-shift shift-register generator with a period of 2^32-1,
398 (3) Two 16-bit multiply-with-carry generators with a period of
399 597273182964842497 > 2^59.
401 The overall period exceeds 2^123.
403 http://www.ciphersbyritter.com/NEWS4/RANDC.HTM#369F6FCA.74C7C041@stat.fsu.edu
405 The above web site has an archive of a newsgroup posting from George
406 Marsaglia with the statement:
408 Subject: Random numbers for C: Improvements.
409 Date: Fri, 15 Jan 1999 11:41:47 -0500
410 From: George Marsaglia <geo@stat.fsu.edu>
411 Message-ID: <369F6FCA.74C7C041@stat.fsu.edu>
412 References: <369B5E30.65A55FD1@stat.fsu.edu>
413 Newsgroups: sci.stat.math,sci.math,sci.math.numer-analysis
416 As I hoped, several suggestions have led to
417 improvements in the code for RNG's I proposed for
418 use in C. (See the thread "Random numbers for C: Some
419 suggestions" in previous postings.) The improved code
422 A question of copyright has also been raised. Unlike
423 DIEHARD, there is no copyright on the code below. You
424 are free to use it in any way you want, but you may
425 wish to acknowledge the source, as a courtesy.
427 "There is no copyright on the code below." included the original
430 #define GFC_SL(k, n) ((k)^((k)<<(n)))
431 #define GFC_SR(k, n) ((k)^((k)>>(n)))
433 static const GFC_INTEGER_4 kiss_size = 4;
434 #define KISS_DEFAULT_SEED {123456789, 362436069, 521288629, 916191069};
435 static const GFC_UINTEGER_4 kiss_default_seed[4] = KISS_DEFAULT_SEED;
436 static GFC_UINTEGER_4 kiss_seed[4] = KISS_DEFAULT_SEED;
438 /* kiss_random_kernel() returns an integer value in the range of
439 (0, GFC_UINTEGER_4_HUGE]. The distribution of pseudorandom numbers
440 should be uniform. */
442 static GFC_UINTEGER_4
443 kiss_random_kernel(void)
447 kiss_seed[0] = 69069 * kiss_seed[0] + 1327217885;
448 kiss_seed[1] = GFC_SL(GFC_SR(GFC_SL(kiss_seed[1],13),17),5);
449 kiss_seed[2] = 18000 * (kiss_seed[2] & 65535) + (kiss_seed[2] >> 16);
450 kiss_seed[3] = 30903 * (kiss_seed[3] & 65535) + (kiss_seed[3] >> 16);
451 kiss = kiss_seed[0] + kiss_seed[1] + (kiss_seed[2] << 16) + kiss_seed[3];
456 /* This function produces a REAL(4) value from the uniform distribution
460 random_r4 (GFC_REAL_4 *x)
464 kiss = kiss_random_kernel ();
465 /* Burn a random number, so the REAL*4 and REAL*8 functions
466 produce similar sequences of random numbers. */
467 kiss_random_kernel ();
468 *x = normalize_r4_i4 (kiss, ~(GFC_UINTEGER_4) 0);
472 /* This function produces a REAL(8) value from the uniform distribution
476 random_r8 (GFC_REAL_8 *x)
480 kiss = ((GFC_UINTEGER_8)kiss_random_kernel ()) << 32;
481 kiss += kiss_random_kernel ();
482 *x = normalize_r8_i8 (kiss, ~(GFC_UINTEGER_8) 0);
486 /* This function fills a REAL(4) array with values from the uniform
487 distribution with range [0,1). */
490 arandom_r4 (gfc_array_r4 *x)
492 index_type count[GFC_MAX_DIMENSIONS - 1];
493 index_type extent[GFC_MAX_DIMENSIONS - 1];
494 index_type stride[GFC_MAX_DIMENSIONS - 1];
502 if (x->dim[0].stride == 0)
503 x->dim[0].stride = 1;
505 dim = GFC_DESCRIPTOR_RANK (x);
507 for (n = 0; n < dim; n++)
510 stride[n] = x->dim[n].stride;
511 extent[n] = x->dim[n].ubound + 1 - x->dim[n].lbound;
522 /* Advance to the next element. */
525 /* Advance to the next source element. */
527 while (count[n] == extent[n])
529 /* When we get to the end of a dimension, reset it and increment
530 the next dimension. */
532 /* We could precalculate these products, but this is a less
533 frequently used path so probably not worth it. */
534 dest -= stride[n] * extent[n];
550 /* This function fills a REAL(8) array with values from the uniform
551 distribution with range [0,1). */
554 arandom_r8 (gfc_array_r8 *x)
556 index_type count[GFC_MAX_DIMENSIONS - 1];
557 index_type extent[GFC_MAX_DIMENSIONS - 1];
558 index_type stride[GFC_MAX_DIMENSIONS - 1];
566 if (x->dim[0].stride == 0)
567 x->dim[0].stride = 1;
569 dim = GFC_DESCRIPTOR_RANK (x);
571 for (n = 0; n < dim; n++)
574 stride[n] = x->dim[n].stride;
575 extent[n] = x->dim[n].ubound + 1 - x->dim[n].lbound;
586 /* Advance to the next element. */
589 /* Advance to the next source element. */
591 while (count[n] == extent[n])
593 /* When we get to the end of a dimension, reset it and increment
594 the next dimension. */
596 /* We could precalculate these products, but this is a less
597 frequently used path so probably not worth it. */
598 dest -= stride[n] * extent[n];
614 /* random_seed is used to seed the PRNG with either a default
615 set of seeds or user specified set of seeds. random_seed
616 must be called with no argument or exactly one argument. */
619 random_seed (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get)
623 if (size == NULL && put == NULL && get == NULL)
625 /* From the standard: "If no argument is present, the processor assigns
626 a processor-dependent value to the seed." */
627 kiss_seed[0] = kiss_default_seed[0];
628 kiss_seed[1] = kiss_default_seed[1];
629 kiss_seed[2] = kiss_default_seed[2];
630 kiss_seed[3] = kiss_default_seed[3];
638 /* If the rank of the array is not 1, abort. */
639 if (GFC_DESCRIPTOR_RANK (put) != 1)
640 runtime_error ("Array rank of PUT is not 1.");
642 /* If the array is too small, abort. */
643 if (((put->dim[0].ubound + 1 - put->dim[0].lbound)) < kiss_size)
644 runtime_error ("Array size of PUT is too small.");
646 if (put->dim[0].stride == 0)
647 put->dim[0].stride = 1;
649 /* This code now should do correct strides. */
650 for (i = 0; i < kiss_size; i++)
651 kiss_seed[i] =(GFC_UINTEGER_4) put->data[i * put->dim[0].stride];
654 /* Return the seed to GET data. */
657 /* If the rank of the array is not 1, abort. */
658 if (GFC_DESCRIPTOR_RANK (get) != 1)
659 runtime_error ("Array rank of GET is not 1.");
661 /* If the array is too small, abort. */
662 if (((get->dim[0].ubound + 1 - get->dim[0].lbound)) < kiss_size)
663 runtime_error ("Array size of GET is too small.");
665 if (get->dim[0].stride == 0)
666 get->dim[0].stride = 1;
668 /* This code now should do correct strides. */
669 for (i = 0; i < kiss_size; i++)
670 get->data[i * get->dim[0].stride] = (GFC_INTEGER_4) kiss_seed[i];
673 iexport(random_seed);
675 #endif /* mersenne twister */