# 32-Bit Pseudorandom Number Generator: A High-Performance, Low-Resource, Portable Approach With Provable Statistical Quality

Eightomic developed a 32-bit pseudorandom number generator algorithm with a library in C99 as a substantial improvement to JSF32, Lehmer, PCG32, Xoroshiro, Xorshift32 and any other PRNG with 32-bit output that doesn't require a full cycle larger than 16TB before re-seeding.

## Library

### Source

```
#include <stdint.h>
struct eightomic_s {
uint32_t a;
uint32_t b;
uint32_t c;
};
uint32_t eightomic_randomize(struct eightomic_s *s) {
s->a = ((s->a << 14) | (s->a >> 18)) ^ s->b;
s->c += 1111111111;
s->b = ((s->b << 21) | (s->b >> 11)) + s->c;
return s->a + 1111111111;
}
```

### Reference

eightomic_randomize() is the randomization function that accepts the following argument.

s is a struct eightomic_s pointer with 3 32-bit unsigned integers s->a, s->b and s->c initialized with any seed values.

The return value data type is uint32_t.

It returns the 32-bit unsigned integer pseudorandom number result.

### Requirements

C compiler with C99 (ISO/IEC 9899:1999) standard compatibility.

CPU with single-threaded, instruction-level parallelism support.

## Explanation

This 32-bit PRNG is designed to pass statistical tests with efficient resource usage, fast speed and a decent period.

It's portable for both 32-bit and 64-bit systems.

It doesn't use modulus, multiplication or division arithmetic operations.

32-bit entropy is generated with a 96-bit auxiliary state.

By default, the period guarantees a smallest full cycle of 2^32 numbers, an estimated average full cycle of 2^64 and a largest full cycle of 2^96 numbers.

32 bits of state are summed with 1111111111 after each random number generation result and mixed in with the bit shuffling sequence.

This eliminates the probability of broken infinite cycles and makes it trivial to add an occasional increment for estimated, randomized jumps.

Furthermore, when all state bits are 0, the next pseudorandom number escapes zeroland quickly, making it impossible to have a broken state with any combination of numbers.

The following code example generates randomized output for deterministic, verifiable testing with all state bits initialized to 0.

```
#include <stdint.h>
#include <stdio.h>
struct eightomic_s {
uint32_t a;
uint32_t b;
uint32_t c;
};
uint32_t eightomic_randomize(struct eightomic_s *s) {
s->a = ((s->a << 14) | (s->a >> 18)) ^ s->b;
s->c += 1111111111;
s->b = ((s->b << 21) | (s->b >> 11)) + s->c;
return s->a + 1111111111;
}
int main(void) {
struct eightomic_s s = {
.a = 0,
.b = 0,
.c = 0
};
uint32_t result = eightomic_randomize(&s);
while (1) {
fwrite(&result, sizeof(result), 1, stdout);
result = eightomic_randomize(&s);
}
return 0;
}
```

It passes all Diehard tests and extended Dieharder tests.

It passes all BigCrush battery tests.

It passes PractRand tests up to 16 TB using the same bits from the aforementioned DieHard tests.

The 32 TB test only fails 1 of about 100 statistical tests, suggesting the 0 seed values caused an anomalic positive that could easily occur in a source of true randomness.

Furthermore, the authors of Xoroshiro believe anything more than 5TB is irrelevant in practical applications. It's still undergoing tests to confirm this theory and, if possible, find optimal shift values with 0 anomalies.

Nevertheless, it should still be re-seeded with an entropy source after generating several TB of randomized data.

Compared to PCG32, the average speed is 8% faster on an AMD CPU and 10% faster on an Intel CPU when generating 1 billion random numbers repeatedly.

Compared to pcg32_fast, the average speed is similar, but when compiler optimization is enabled with -O3, the average speed is at least 18% faster and up to 3x as fast.

Furthermore, PCG32 has a smaller full cycle with a stricter 64-bit system requirement and multiplication operations.

Compared to Lehmer and JSF32, the average speed is 20% faster when generating 1 billion random numbers repeatedly.

Compared to all Xoroshiro and Xorshift algorithms, it's 20% to 40% faster.

Furthermore, most of these PRNGs are vulnerable to several confirmed broken cycles when seeded with specific values, including 0.