Add missing files from last commit

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6273 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2015-12-14 22:37:56 +00:00
parent 6be4f3d376
commit 00f78dd646
3 changed files with 151 additions and 0 deletions

76
lib/init_random_seed.c Normal file
View File

@ -0,0 +1,76 @@
#include "init_random_seed.h"
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
/* basic PRNG to use for improving the basic seed selection */
static unsigned lcg (uint64_t seed)
{
if (0 ==seed)
{
seed = UINT64_C(104729);
}
else
{
seed %= UINT64_C(4294967296);
}
seed = (seed * UINT64_C(279470273)) % UINT64_C(4294967291);
return seed % UINT64_MAX;
}
/* Generate a good PRNG seed value */
void init_random_seed(void)
{
unsigned seed = 0u;
int have_seed = 0;
// try /dev/urandom for an initial seed
int random_source;
if (0 == (random_source = open ("/dev/urandom", O_RDONLY)))
{
size_t random_data_length = 0;
have_seed = -1;
while (random_data_length < sizeof seed)
{
ssize_t result = read (random_source, &seed + random_data_length, (sizeof seed) - random_data_length);
if (result < 0)
{
// error, unable to read /dev/random
have_seed = 0;
}
random_data_length += result;
}
close (random_source);
}
if (!have_seed)
{
// fallback to XOR:ing the time and pid
seed = time (NULL) ^ getpid ();
seed = lcg (seed);
}
srand (seed);
}
#ifdef TEST
#include <stdio.h>
int main (int argc, char * argv[])
{
init_random_seed ();
int i, j;
int r[10][4];
for (i = 0; i < 10; ++i)
{
for (j = 0; j < 4; ++j)
{
printf ("%10d ", rand ());
}
printf ("\n");
}
return 0;
}
#endif

55
lib/init_random_seed.f90 Normal file
View File

@ -0,0 +1,55 @@
!
! Generate a seed for the RANDOM_NUMBER PRNG that is guaranteed to be
! unique even if many processes are started simultaneously
!
subroutine init_random_seed()
use iso_fortran_env, only: int64
implicit none
integer, allocatable :: seed(:)
integer :: i, n, un, istat, dt(8), pid
integer(int64) :: t
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(t)
if (t == 0) then
call date_and_time(values=dt)
t = (dt(1) - 1970) * 365_int64 * 24 * 60 * 60 * 1000 &
+ dt(2) * 31_int64 * 24 * 60 * 60 * 1000 &
+ dt(3) * 24_int64 * 60 * 60 * 1000 &
+ dt(5) * 60 * 60 * 1000 &
+ dt(6) * 60 * 1000 + dt(7) * 1000 &
+ dt(8)
end if
pid = getpid()
t = ieor(t, int(pid, kind(t)))
do i = 1, n
seed(i) = lcg(t)
end do
end if
call random_seed(put=seed)
contains
! This simple PRNG might not be good enough for real work, but is
! sufficient for seeding a better PRNG.
function lcg(s)
integer :: lcg
integer(int64) :: s
if (s == 0) then
s = 104729
else
s = mod(s, 4294967296_int64)
end if
s = mod(s * 279470273_int64, 4294967291_int64)
lcg = int(mod(s, int(huge(0), int64)), kind(0))
end function lcg
end subroutine init_random_seed

20
lib/init_random_seed.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef INIT_RANDOM_SEED_H__
#define INIT_RANDOM_SEED_H__
#ifdef __cplusplus
exten "C" {
#endif
/*
* Generate a seed for the RANDOM_NUMBER PRNG that is guaranteed to
* be unique even if many processes are started simultaneously
*
* Not suitable for multi-threaded requirements
*/
void init_random_seed (void);
#ifdef __cplusplus
}
#endif
#endif