From 91151a7334543817f1f790310a1bfc4589889cad Mon Sep 17 00:00:00 2001 From: Janne Blomqvist Date: Fri, 19 Aug 2016 17:12:32 +0300 Subject: [PATCH] Always initialize PRNG using random data from the OS. libgfortran: 2016-08-16 Janne Blomqvist * intrinsics/random.c (master_init): New variable. (init_rand_state): Move below getosrandom (), maybe initialize master_state. (random_seed_i4): If called with no arguments, set master_init to false, and reinitialize. If called with PUT=, set master_init to true. (random_seed_i8): Likewise. testsuite: 2016-08-16 Janne Blomqvist * gfortran.dg/random_4.f90: Initialize seed before using, handle the last special seed value. * gfortran.dg/random_7.f90: Use size for last array member instead of hardcoded value. From-SVN: r239611 --- gcc/testsuite/ChangeLog | 7 ++++ gcc/testsuite/gfortran.dg/random_4.f90 | 3 ++ gcc/testsuite/gfortran.dg/random_7.f90 | 5 ++- libgfortran/ChangeLog | 10 +++++ libgfortran/intrinsics/random.c | 57 +++++++++++++++----------- 5 files changed, 55 insertions(+), 27 deletions(-) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6590fab9c29..3807dd5e806 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2016-08-19 Janne Blomqvist + + * gfortran.dg/random_4.f90: Initialize seed before using, handle + the last special seed value. + * gfortran.dg/random_7.f90: Use size for last array member instead + of hardcoded value. + 2016-08-19 Prathamesh Kulkarni * gcc.dg/cpp/warn-undef.c: Append "evaluates to 0" to dg-error. diff --git a/gcc/testsuite/gfortran.dg/random_4.f90 b/gcc/testsuite/gfortran.dg/random_4.f90 index 416b17c0086..e60698f4906 100644 --- a/gcc/testsuite/gfortran.dg/random_4.f90 +++ b/gcc/testsuite/gfortran.dg/random_4.f90 @@ -6,8 +6,11 @@ program trs integer, allocatable, dimension(:) :: seed, check call test_random_seed(size) allocate(seed(size),check(size)) + seed = 42 call test_random_seed(put=seed) call test_random_seed(get=check) + ! With xorshift1024* the last seed value is special + seed(size) = check(size) if (any (seed /= check)) call abort contains subroutine test_random_seed(size, put, get) diff --git a/gcc/testsuite/gfortran.dg/random_7.f90 b/gcc/testsuite/gfortran.dg/random_7.f90 index aafe346de7b..8cd9c43bd66 100644 --- a/gcc/testsuite/gfortran.dg/random_7.f90 +++ b/gcc/testsuite/gfortran.dg/random_7.f90 @@ -10,8 +10,9 @@ program trs seed(:) = huge(seed) / 17 call test_random_seed(put=seed) call test_random_seed(get=check) - ! In the current implementation seed(17) is special - seed(17) = check(17) + ! In the current xorshift1024* implementation the last seed value is + ! special + seed(size) = check(size) if (any (seed /= check)) call abort contains subroutine test_random_seed(size, put, get) diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 0f9d629b460..6fd12228645 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,13 @@ +2016-08-16 Janne Blomqvist + + * intrinsics/random.c (master_init): New variable. + (init_rand_state): Move below getosrandom (), maybe initialize + master_state. + (random_seed_i4): If called with no arguments, set master_init to + false, and reinitialize. If called with PUT=, set master_init to + true. + (random_seed_i8): Likewise. + 2016-08-11 Rainer Orth * intrinsics/random.c: Include . diff --git a/libgfortran/intrinsics/random.c b/libgfortran/intrinsics/random.c index 3b913893817..35c76113b1a 100644 --- a/libgfortran/intrinsics/random.c +++ b/libgfortran/intrinsics/random.c @@ -193,9 +193,10 @@ typedef struct xorshift1024star_state; -/* How many times we have jumped. This and master_state are the only - variables protected by random_lock. */ -static unsigned njumps; +/* master_init, njumps, and master_state are the only variables + protected by random_lock. */ +static bool master_init; +static unsigned njumps; /* How many times we have jumped. */ static uint64_t master_state[] = { 0xad63fa1ed3b55f36ULL, 0xd94473e78978b497ULL, 0xbc60592a98172477ULL, 0xa3de7c6e81265301ULL, 0x586640c5e785af27ULL, 0x7a2a3f63b67ce5eaULL, @@ -272,24 +273,6 @@ jump (xorshift1024star_state* rs) } -/* Initialize the random number generator for the current thread, - using the master state and the number of times we must jump. */ - -static void -init_rand_state (xorshift1024star_state* rs, const bool locked) -{ - if (!locked) - __gthread_mutex_lock (&random_lock); - memcpy (&rs->s, master_state, sizeof (master_state)); - unsigned n = njumps++; - if (!locked) - __gthread_mutex_unlock (&random_lock); - for (unsigned i = 0; i < n; i++) - jump (rs); - rs->init = true; -} - - /* Super-simple LCG generator used in getosrandom () if /dev/urandom doesn't exist. */ @@ -359,6 +342,30 @@ getosrandom (void *buf, size_t buflen) } +/* Initialize the random number generator for the current thread, + using the master state and the number of times we must jump. */ + +static void +init_rand_state (xorshift1024star_state* rs, const bool locked) +{ + if (!locked) + __gthread_mutex_lock (&random_lock); + if (!master_init) + { + getosrandom (master_state, sizeof (master_state)); + njumps = 0; + master_init = true; + } + memcpy (&rs->s, master_state, sizeof (master_state)); + unsigned n = njumps++; + if (!locked) + __gthread_mutex_unlock (&random_lock); + for (unsigned i = 0; i < n; i++) + jump (rs); + rs->init = true; +} + + /* This function produces a REAL(4) value from the uniform distribution with range [0,1). */ @@ -791,8 +798,7 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get) a processor-dependent value to the seed." */ if (size == NULL && put == NULL && get == NULL) { - getosrandom (master_state, sizeof (master_state)); - njumps = 0; + master_init = false; init_rand_state (rs, true); } @@ -816,6 +822,7 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get) provide seeds with quality only in the lower or upper part. */ scramble_seed ((unsigned char *) master_state, seed, sizeof seed); njumps = 0; + master_init = true; init_rand_state (rs, true); rs->p = put->base_addr[SZ * GFC_DESCRIPTOR_STRIDE(put, 0)] & 15; @@ -873,8 +880,7 @@ random_seed_i8 (GFC_INTEGER_8 *size, gfc_array_i8 *put, gfc_array_i8 *get) a processor-dependent value to the seed." */ if (size == NULL && put == NULL && get == NULL) { - getosrandom (master_state, sizeof (master_state)); - njumps = 0; + master_init = false; init_rand_state (rs, true); } @@ -894,6 +900,7 @@ random_seed_i8 (GFC_INTEGER_8 *size, gfc_array_i8 *put, gfc_array_i8 *get) sizeof (GFC_UINTEGER_8)); njumps = 0; + master_init = true; init_rand_state (rs, true); rs->p = put->base_addr[SZ * GFC_DESCRIPTOR_STRIDE(put, 0)] & 15; } -- 2.30.2