Permuted congruential generator explained

A permuted congruential generator (PCG) is a pseudorandom number generation algorithm developed in 2014 by Dr. M.E. O'Neill which applies an output permutation function to improve the statistical properties of a modulo-2n linear congruential generator. It achieves excellent statistical performance[1] [2] [3] [4] with small and fast code, and small state size.[5]

A PCG differs from a classical linear congruential generator (LCG) in three ways:

It is the variable rotation which eliminates the problem of a short period in the low-order bits that power-of-2 LCGs suffer from.

Variants

The PCG family includes a number of variants. The core LCG is defined for widths from 8 to 128 bits, although only 64 and 128 bits are recommended for practical use; smaller sizes are for statistical tests of the technique.

The additive constant in the LCG can be varied to produce different streams. The constant is an arbitrary odd integer,[6] so it does not need to be stored explicitly; the address of the state variable itself (with the low bit set) can be used.

There are several different output transformations defined. All perform well, but some have a larger margin than others. They are built from the following components:

These are combined into the following recommended output transformations, illustrated here in their most common sizes:

(64→32 bits) count = (int)(x >> 59); x ^= x >> 18; return rotr32((uint32_t)(x >> 27), count);.

(64→32 bits) count = (int)(x >> 61); x ^= x >> 22; return (uint32_t)(x >> (29 - count));.

(128→64 bits) count = (int)(x >> 122); x64 = (uint64_t)(x ^ (x >> 64)); return rotr64(x64, count);

(32→32 bits) count=(int)(x >> 28); x ^= x >> (4 + count); x *= 277803737u; return x ^ (x >> 22);

(64→64 bits) count=(int)(x >> 59); x ^= x >> (5 + count); x *= 12605985483714917081u; return x ^ (x >> 43);

(128→128 bits) count = (int)(x >> 122); low64 = rotr64((uint64_t)(x ^ (x >> 64)), count); high64 = rotr64((uint64_t)(x >> 64), low64 & 63); return (uint128_t)high64 << 64 | low64;

Each step of these output transformations is either invertible (and thus one-to-one) or a truncation, so their composition maps the same fixed number of input states to each output value. This preserves the equidistribution of the underlying LCG.

Finally, if a cycle length longer than 2128 is required, the generator can be extended with an array of sub-generators. One is chosen (in rotation) to be added to the main generator's output, and every time the main generator's state reaches zero, the sub-generators are cycled in a pattern which provides a period exponential in the total state size.

Example code

The generator recommended for most users is PCG-XSH-RR with 64-bit state and 32-bit output. It can be implemented as:

  1. include

static uint64_t state = 0x4d595df4d0f33173; // Or something seed-dependentstatic uint64_t const multiplier = 6364136223846793005u;static uint64_t const increment = 1442695040888963407u; // Or an arbitrary odd constant

static uint32_t rotr32(uint32_t x, unsigned r)

uint32_t pcg32(void)

void pcg32_init(uint64_t seed)

The generator applies the output transformation to the initial state rather than the final state in order to increase the available instruction-level parallelism to maximize performance on modern superscalar processors.

A slightly faster version eliminates the increment, reducing the LCG to a multiplicative (Lehmer-style) generator with a period of only 262, and uses the weaker XSH-RS output function:

static uint64_t mcg_state = 0xcafef00dd15ea5e5u; // Must be oddstatic uint64_t const multiplier = 6364136223846793005u;

uint32_t pcg32_fast(void)

void pcg32_fast_init(uint64_t seed)

The time saving is minimal, as the most expensive operation (the 64×64-bit multiply) remains, so the normal version is preferred except in extremis. Still, this faster version also passes statistical tests.

When executing on a 32-bit processor, the 64×64-bit multiply must be implemented using three 32×32→64-bit multiply operations. To reduce that to two, there are 32-bit multipliers which perform almost as well as the 64-bit one, such as 0xf13283ad, or 0xf2fc5985.

Comparison with other pseudorandom number generators

Melissa O'Neill proposes testing PRNGs by applying statistical tests to their reduced-size variants and determining the minimum number of internal state bits required to pass.[7] TestU01's BigCrush examines enough data to detect a period of 235, so even an ideal generator requires 36 bits of state to pass it. Some very poor generators can pass if given a large enough state;[8] passing despite a small state is a measure of an algorithm's quality, and shows how large a safety margin exists between that lower limit and the state size used in practical applications.

PCG-RXS-M-XS (with 32-bit output) passes BigCrush with 36 bits of state (the minimum possible), PCG-XSH-RR (pcg32 above) requires 39, and PCG-XSH-RS (pcg32_fast above) requires 49 bits of state. For comparison, xorshift*, one of the best of the alternatives, requires 40 bits of state, and Mersenne twister fails despite 19937 bits of state.[9]

Prediction and seed-recovery

It has been shown that it is practically possible (with a large computation) to recover the seed of the pseudo-random generator given 512 consecutive output bytes.[10] This implies that it is practically possible to predict the rest of the pseudo-random stream given 512 bytes.

See also

External links

Notes and References

  1. Web site: Testing non-cryptographic random number generators: my results . Daniel . Lemire . 22 August 2017 . 2017-10-03 .
  2. Web site: Testing the PCG random number generator . John D. . Cook . 7 July 2017 . 2017-10-03 .
  3. Web site: Testing RNGs with PractRand . John D. . Cook . 14 August 2017 . 2017-10-03 .
  4. Web site: PCG Passes PractRand . M.E. . O'Neill . 29 July 2017 . 2017-11-03 .
  5. PCG: A Family of Simple Fast Space-Efficient Statistically Good Algorithms for Random Number Generation . Melissa E. . O'Neill . . HMC-CS-2014-0905 . 5 September 2014 .
  6. Web site: Critiquing PCG's streams (and SplitMix's too) . M.E. . O'Neill . 10 August 2017 . 2017-11-03 .
  7. Web site: Visualizing the Heart of Some PRNGs . M.E. . O'Neill . 20 August 2017 . 2017-11-03 .
  8. Web site: Too Big to Fail . M.E. . O'Neill . 20 August 2017 . 2017-11-03 .
  9. Pierre . L'Ecuyer . Richard . Simard . TestU01: A C library for empirical testing of random number generators . . 33 . 4 . 22-1–22-40 . August 2007 . 10.1145/1268776.1268777 . 10.1.1.499.2830. 273446 .
  10. Bouillaguet . Charles . Martinez . Florette . Sauvage . Julia . Practical seed-recovery for the PCG Pseudo-Random Number Generator . IACR Transactions on Symmetric Cryptology . 28 September 2020 . 2020 . 3 . 175–196 . 10.13154/tosc.v2020.i3.175-196. 222137612 .