SFC64 Generator

class randomgen.sfc.SFC64(seed=None, w=1, k=1, *, mode='sequence')

Chris Doty-Humphrey’s Small Fast Chaotic PRNG with optional Weyl Sequence

Parameters
seed{None, int, array_like[ints], SeedSequence}, optional

A seed to initialize the BitGenerator. If None, then fresh, unpredictable entropy will be pulled from the OS. If an int or array_like[ints] is passed, then it will be passed to SeedSequence to derive the initial BitGenerator state. One may also pass in a SeedSequence instance.

w{uint64, None}, default 1

The starting value of the Weyl sequence. If None, then the initial value is generated from the SeedSequence.

k{uint64, None}, default 1

The increment to the Weyl sequence. Must be odd, and if even, 1 is added. If None, then k is generated from the `SeedSequence.

mode{“sequence”, “numpy”}

The default uses a seed sequence to initialize all unspecified values. When using “numpy” uses the seed sequence to initialize three values and checks that both w and k are 1.

Notes

SFC64 is a 256-bit implementation of Chris Doty-Humphrey’s Small Fast Chaotic PRNG ([1]). SFC64 has a few different cycles that one might be on, depending on the seed; the expected period will be about \(2^{255}\) ([2]). SFC64 incorporates a 64-bit counter which means that the absolute minimum cycle length is \(2^{64}\) and that distinct seeds will not run into each other for at least \(2^{64}\) iterations. SFC64 provides a capsule containing function pointers that produce doubles, and unsigned 32 and 64- bit integers. These are not directly consumable in Python and must be consumed by a Generator or similar object that supports low-level access.

State and Seeding

The SFC64 state vector consists of 4 unsigned 64-bit values. The last is a 64-bit counter that increments by 1 each iteration. The input seed is processed by SeedSequence to generate the first 3 values, then the SFC64 algorithm is iterated a small number of times to mix.

Compatibility Guarantee

SFC64 makes a guarantee that a fixed seed will always produce the same random integer stream.

References

1

“PractRand”. http://pracrand.sourceforge.net/RNG_engines.txt.

2

“Random Invertible Mapping Statistics”. https://www.pcg-random.org/posts/random-invertible-mapping-statistics.html.

Examples

SFC64 supports generating distinct streams using different Weyl increments. The recommend practice is to chose a set of distinct odd coefficients that have 32 or fewer bits set of 1 (i.e., <= 50%).

>>> import numpy as np
>>> from randomgen import SFC64, SeedSequence
>>> NUM_STREAMS = 8196
>>> seed_seq = SeedSequence(325874985469)
>>> bit_gen = SFC64(seed_seq)
>>> weyl_inc = bit_gen.weyl_increments(NUM_STREAMS)
>>> streams = [SFC64(seed_seq, k=k) for k in list(weyl_inc)]
>>> [stream.random_raw() for stream in streams[:3]]
[13020151409549081939, 8062752282355435850, 13933250373249421220]

Seeding and State

seed([seed])

Seed the generator

state

Get or set the PRNG state

Extending

cffi

CFFI interface

ctypes

ctypes interface

Testing

random_raw([size, output])

Return randoms as generated by the underlying BitGenerator

Parallelization

weyl_increments(n[, max_bits, min_bits])

Generate distinct Weyl increments to construct multiple streams