randomgen.pcg32.PCG32.advance_step

static PCG32.advance_step(max_draws)

Step for splitting one stream into streams of up to max_draws draws

Added in version 2.5.0.

Parameters:
max_draws

The largest number of draws that any stream makes. Must be at least 1 and at most the integer part of 2**64 / phi, about 1.1 * 10**19, where phi is the golden ratio.

Returns:

step – The odd integer closest to 2**XX / phi, where XX is the smallest integer for which 2**XX / phi is larger than max_draws. The step is never smaller than max_draws.

Return type:

int

Raises:
  • ValueError – If max_draws is outside the range above.

  • TypeError – If max_draws is not an integer.

See also

advance

Advance the state as-if delta draws have occurred.

Notes

Advance stream i by i * step to split one stream into several. The step is odd, so the states of two streams differ as if at random, apart from their lowest few bits. The step is at least max_draws, so a stream that makes at most max_draws draws does not reach the start of the next stream. The Notes of advance explain this choice of step.

The starts i * step are taken modulo the period, 2**64, so streams 0 to n - 1 are only guaranteed not to overlap when n * step <= 2**64. advance_step does not check this, since it does not know n, and the period of PCG32 is short enough for the limit to matter. The largest n is 2**64 // step:

max_draws

Largest n

10**6

1.4 * 10**13

10**9

1.4 * 10**10

10**12

1.4 * 10**7

10**15

13,254

10**18

12

The step is less than 2 * max_draws, so n streams always fit when n * max_draws <= 2**63. When many streams or many draws per stream are needed, use PCG64, or the related PCG64DXSM or LCG128Mix. Their period of 2**128 allows about 2.5 * 10**26 streams of 10**12 draws.

The step is computed with integer arithmetic only, so it is exact for any max_draws.

Examples

>>> from randomgen import PCG32
>>> step = PCG32.advance_step(10**10)
>>> hex(step)
'0x278dde6e5'
>>> streams = [PCG32(1234).advance(i * step) for i in range(8)]