P99

◆ p99_seed

typedef p00_seed160 p99_seed[2]

The internal state that the PRG for ::p99_rand and ::p99_drand uses.

Remarks
Usually you don't have to deal with this type other than the cases described for ::p99_seed_get.

This is currently a set of 12 values of type uint32_t, so 384 bits. Any reasonable initialization with true random bits of such a state variable should give you a different PRG of cycle length 2^160. (Reasonable here means that initializations with 160 consecutive 0 bits or more should be avoided.)

P99 initializes a different state for each thread that uses the corresponding functions. The setup of that state for each thread may incur a cost of about 16 to 20 times the call to ::p99_rand. The initialization only produces one state out of 2^160 possibilities, so the state space of 384 is not used optimally.

Please let me know if you have an idea of using other portable sources of randomness for the initialization, currently we use the wall clock time, monotonic time (if available), the stack address of the thread and a per thread malloced address. This guarantees that the states are different for all threads that run concurrently (they will not have the same stack or malloced address) or that are scheduled with a suitable time difference that exceeds the clock granularity (they will not use the same time stamp).

All of this is only a heuristic and can be spoofed; it might give the same initial state for threads that are schedule in short sequence if:

  • the first thread terminates before the second is started
  • the second obtains the same time stamp as the first
  • the second is scheduled with the same stack address as the first
  • the second receives exactly the same address from malloc.

Under non-hostile circumstance this should only occur on a combination of platform and code that quickly launches a lot of threads (thousands) and has no good address randomization and a low granularity clock.

Definition at line 117 of file p99_rand.h.