From 3870c13bfc0d3756c55f52b1d94676ae5620a352 Mon Sep 17 00:00:00 2001 From: jb Date: Wed, 22 May 2013 08:36:12 +0000 Subject: [PATCH] Improve RANDOM_SEED example. 2013-05-22 Janne Blomqvist * intrinsic.texi (RANDOM_SEED): Improve example. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@199184 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/fortran/ChangeLog | 4 +++ gcc/fortran/intrinsic.texi | 70 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 2698389c810..97893b97950 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,7 @@ +2013-05-22 Janne Blomqvist + + * intrinsic.texi (RANDOM_SEED): Improve example. + 2013-05-07 Tobias Burnus Backport from mainline diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index ab91122a96b..d0a29cc25ea 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -10134,9 +10134,12 @@ end program Restarts or queries the state of the pseudorandom number generator used by @code{RANDOM_NUMBER}. -If @code{RANDOM_SEED} is called without arguments, it is initialized to -a default state. The example below shows how to initialize the random -seed based on the system's time. +If @code{RANDOM_SEED} is called without arguments, it is initialized +to a default state. The example below shows how to initialize the +random seed with a varying seed in order to ensure a different random +number sequence for each invocation of the program. Note that setting +any of the seed values to zero should be avoided as it can result in +poor quality random numbers being generated. @item @emph{Standard}: Fortran 95 and later @@ -10164,20 +10167,53 @@ the @var{SIZE} argument. @item @emph{Example}: @smallexample -SUBROUTINE init_random_seed() - INTEGER :: i, n, clock - INTEGER, DIMENSION(:), ALLOCATABLE :: seed - - CALL RANDOM_SEED(size = n) - ALLOCATE(seed(n)) - - CALL SYSTEM_CLOCK(COUNT=clock) - - seed = clock + 37 * (/ (i - 1, i = 1, n) /) - CALL RANDOM_SEED(PUT = seed) - - DEALLOCATE(seed) -END SUBROUTINE +subroutine init_random_seed() + implicit none + integer, allocatable :: seed(:) + integer :: i, n, un, istat, dt(8), pid, t(2), s + integer(8) :: count, tms + + call random_seed(size = n) + allocate(seed(n)) + ! First try if the OS provides a random number generator + open(newunit=un, file="/dev/urandom", access="stream", & + form="unformatted", action="read", status="old", iostat=istat) + if (istat == 0) then + read(un) seed + close(un) + else + ! Fallback to XOR:ing the current time and pid. The PID is + ! useful in case one launches multiple instances of the same + ! program in parallel. + call system_clock(count) + if (count /= 0) then + t = transfer(count, t) + else + call date_and_time(values=dt) + tms = (dt(1) - 1970) * 365_8 * 24 * 60 * 60 * 1000 & + + dt(2) * 31_8 * 24 * 60 * 60 * 1000 & + + dt(3) * 24 * 60 * 60 * 60 * 1000 & + + dt(5) * 60 * 60 * 1000 & + + dt(6) * 60 * 1000 + dt(7) * 1000 & + + dt(8) + t = transfer(tms, t) + end if + s = ieor(t(1), t(2)) + pid = getpid() + 1099279 ! Add a prime + s = ieor(s, pid) + if (n >= 3) then + seed(1) = t(1) + 36269 + seed(2) = t(2) + 72551 + seed(3) = pid + if (n > 3) then + seed(4:) = s + 37 * (/ (i, i = 0, n - 4) /) + end if + else + seed = s + 37 * (/ (i, i = 0, n - 1 ) /) + end if + end if + call random_seed(put=seed) +end subroutine init_random_seed @end smallexample @item @emph{See also}: -- 2.11.0