GhostScramble is the efficient PRNG (for advanced graphics rendering in video game engines) 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 (non-cryptographic state rewinding) and segmented parallel sequences.
GhostScramble was created by William Stafford Parsons as a product of Eightomic.
GhostScramble uses a proprietary 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 state 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 state 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 state 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).
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 independence properties that are provable in the following exhaustive black-box tests (scaled down to 8-bit integers for computational feasibility).
#include <stdint.h>
#include <stdio.h>
int circular_shift;
unsigned short odd_increase;
struct black_box_state {
uint8_t a;
uint8_t b;
};
void black_box(struct black_box_state *s) {
s->a = ((s->a << circular_shift) | (s->a >> (8 - circular_shift))) ^ s->b;
s->b += odd_increase;
}
int main(void) {
struct black_box_state s;
unsigned short i = 0;
unsigned short j;
while (i < 256) {
j = 0;
while (j < 256) {
circular_shift = 1;
while (circular_shift < 8) {
odd_increase = 1;
while (odd_increase < 256) {
s.a = i;
s.b = j;
black_box(&s);
while (s.b != j) {
black_box(&s);
}
if (s.a != i) {
printf("The state collides when a is %u and b is %u.\n", i, j);
}
odd_increase += 2;
}
circular_shift++;
}
j++;
}
i++;
}
return 0;
}Subtle stochastic cross-correlations among segmented parallel GhostScramble instances fall within practical tolerance parameters (for visual artifact reduction) in advanced graphics rendering scenarios (such as complex output transformations for rejection sampling).
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 yielded excellent results (not tampering with GhostScramble state variables after seeding each single-letter state variable with 0) from statistical test suites for randomness quality.
GhostScramble passed RNG_test stdin -tlmax 4TB -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 |
|---|---|
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 |
wanghash64 |
5983ms |
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.
