GhostScramble is the hyper-efficient non-cryptographic PRNG that has 64-bit integers (for modern 64-bit architecture), a minimum period of at least 2⁶⁴ (from a Weyl sequence), excellent randomness test results, hyper-fast speed, low-footprint implementation, reversibility (state rewinding with no backtracking resistance) and segmented parallel sequences.
GhostScramble was created by William Stafford Parsons.
GhostScramble is licensed with the BSD-3-Clause license.
Each mention of GhostScramble refers to each of the 3 following variants individually (ghostscramble64, ghostscramble128 and ghostscramble256) implemented in C (requiring the stdint.h header to define a 64-bit, unsigned integral type for uint64_t).
The ghostscramble64 function modifies the state in a struct ghostscramble64_state instance to generate a pseudorandom uint64_t integer as the return value.
Each variable (a, b and c) in a struct ghostscramble64_state instance must be seeded before generating a deterministic ghostscramble64 sequence (that must discard the first 3 ghostscramble64 results as a state warmup).
The ghostscramble128 function modifies the state in a struct ghostscramble128_state instance to generate 2 pseudorandom uint64_t integers in the output array.
Each single-letter variable (a, b and c) in a struct ghostscramble128_state instance must be seeded before generating a deterministic ghostscramble128 sequence (that must discard the first 3 ghostscramble128 results as a state warmup).
The ghostscramble256 function modifies the state in a struct ghostscramble256_state instance to generate 4 pseudorandom uint64_t integers in the output array.
Each single-letter variable (a, b, c and d) in a struct ghostscramble256_state instance must be seeded before generating a deterministic ghostscramble256 sequence (that must discard the first 3 ghostscramble256 results as a state warmup).
ghostscramble512 doesn't exist yet.
ghostscramble1024 doesn't exist yet.
Each instance within a set of parallel GhostScramble instances must adhere to the following single-letter variable seeding rules before generating a set of up to 2⁶⁴ parallel GhostScramble sequences (that each have non-probabilistic full state collision avoidance with each other for a period of at least 2⁶⁴) without fixed-key variables or fixed-length jump-ahead functions (each parallel GhostScramble sequence has a minimum distance of 2⁶⁴ output results between each other).
a(the chaotic accumulation mixing variable that XOR-rotates withb) must be seeded with an integer that's unique among the set of parallel GhostScramble instances.b(the Weyl sequence variable) must be seeded with an integer that's consistent among the set of parallel GhostScramble instances.- The remaining single-letter state variables must be seeded.
After seeding a set of parallel GhostScramble instances, reseeding (or tampering with) either a or b voids the aforementioned parallelism segmentation properties (that are provable in scaled-down black-box tests with 8-bit integers).
GhostScramble uses straightforward chaotic state accumulation procedures (drastically reducing the probability of encountering hidden statistical biases from specific seeded states) to generate sequences that each have a minimum period of at least 2⁶⁴ (from a Weyl sequence).
Therefore, GhostScramble yields excellent results (not tampering with GhostScramble state variables after seeding) from statistical test suites for randomness quality.
GhostScramble passed RNG_test stdin -tlmax 8TB -tlmin 1KB tests.
GhostScramble passed BigCrush tests (using each uint64_t output integer as 2 uint32_t integers).
GhostScramble passed dieharder -Y 1 -a -g 200 -k 2 extended tests (each ambiguous result resolved to a PASSED result).
GhostScramble passed assess 1000000 tests (using 100 bitstreams).
Each of the following results log the fastest process execution speed (in milliseconds) among several repetitions of a speed benchmark (using gcc -O3 from an AMD A4-9120C) that generates (and hashes) 1 billion pseudorandom uint64_t integers in a #pragma GCC unroll 0 loop.
| PRNG | Elapsed |
|---|---|
ghostscramble1024 |
???ms |
ghostscramble512 |
???ms |
ghostscramble256 |
561ms |
ghostscramble128 |
743ms |
***shishua_avx2 (-mavx2) |
866ms |
**aesdec2 (-maes -msse4) |
905ms |
**shishua_sse4 (-msse4) |
978ms |
ghostscramble64 |
1072ms |
**shishua_sse3 (-msse3) |
1147ms |
**shishua_sse2 (-msse2) |
1154ms |
biski64 |
1292ms |
sfc64 |
1320ms |
xoshiro256_plus |
1546ms |
xorshiftr128_plus |
1654ms |
jsf64_2rotate |
1718ms |
xoroshiro128_plus |
1733ms |
mrsf64 |
1833ms |
jsf64_3rotate |
1841ms |
mrc64 |
1862ms |
romu_trio |
1894ms |
wob2m |
1928ms |
mwc192 |
1997ms |
wyrand |
2033ms |
xorshift64 |
2135ms |
shishua |
2251ms |
xorshift128_plus |
2260ms |
*xorwow |
2882ms |
romu_mono |
2982ms |
*pcg32_minimal |
2983ms |
*pcg_oneseq_64_xsh_rr_32 |
2987ms |
mwc128 |
2998ms |
*lehmer_mcg32 |
3402ms |
*pcg_oneseq_64_xsh_rs_32 |
3404ms |
*lcg32 |
3409ms |
lehmer_mcg64 |
3413ms |
lcg64 |
3416ms |
**aes_ni_ctr_128 (-maes -msse4) |
3796ms |
pcg_oneseq_64_xsl_rr_rr_64 |
3928ms |
*isaac |
4099ms |
splitmix64 |
4385ms |
cwg64 |
4680ms |
cwg128 |
4757ms |
**sfmt (-msse2) |
5525ms |
lxm_xbg128 |
5863ms |
pcg_oneseq_128_xsh_rr_64 |
6833ms |
mt19937_64 |
7126ms |
*squares32 |
7552ms |
pcg64_dxsm |
7604ms |
pcg_oneseq_128_xsh_rs_64 |
7676ms |
philox4x64 |
9171ms |
*****google_randen (-maes -msse4) |
9206ms |
squares64 |
9596ms |
*chacha8 |
13230ms |
tinymt64 |
16081ms |
****mrg32k3a |
19356ms |
*chacha20 |
26402ms |
*rand (stdlib.h) |
46083ms |
* Each n-bit output integer was casted to a uint64_t integer.
** Each 128-bit output integer was extracted as 2 uint64_t integers.
*** Each 256-bit output integer was extracted as 4 uint64_t integers.
**** Each output integer was returned as a uint64_t integer (omitting the double integer conversion).
***** Each block of 4 uint8_t output integers were merged into a uint32_t integer that was casted to a uint64_t integer.
