File: init_random_seed.c

package info (click to toggle)
wsjtx 2.7.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 70,440 kB
  • sloc: cpp: 75,379; f90: 46,460; python: 27,241; ansic: 13,367; fortran: 2,382; makefile: 197; sh: 133
file content (82 lines) | stat: -rwxr-xr-x 1,806 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "init_random_seed.h"

#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/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 ((random_source = open ("/dev/urandom", O_RDONLY)) >= 0)
    {
      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 combining the time and PID in a fairly random way
      pid_t pid = getpid ();
      struct timeval tv;
      gettimeofday (&tv, NULL);
      seed = (unsigned)(((unsigned)pid << 16)
        ^ (unsigned)pid
        ^ (unsigned)tv.tv_sec
        ^ (unsigned)tv.tv_usec);
      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