UPDATE LOG
- PCG Implementation (2025-11-28)
- PCG Definition (2025-11-28)
- PCG Motivation (2025-11-28)
1. Why Introduce PCG?
Most random number generators in widespread use today have one of the following problems: [1]
| RNG Family | Statistical Quality | Prediction Difficulty | Reproducible Results | Multiple Streams | Period | Useful Features | Time Performance | Space Usage | Code Size & Complexity | k-Dimensional Equidistribution |
|---|---|---|---|---|---|---|---|---|---|---|
| PCG Family | 🟢 Excellent | 🟢 Challenging | 🟢 Yes | 🟢 Yes (2^63) | 🟢 Arbitrary | 🟢 Jump ahead, Distance | 🟢 Very fast | 🟢 Very compact | 🟢 Very small | 🟢 Arbitrary* |
| Mersenne Twister | 🟡 Some Failures | 🔴 Easy | 🟢 Yes | 🔴 No | 🟢 Huge (2^19937) | 🟡 Jump ahead | 🟡 Acceptable | 🟡 Huge (2 KB) | 🟡 Complex | 🟢 623 |
| Arc4Random | 🟡 Some Issues | 🟢 Secure | 🟡 Not Always | 🔴 No | 🟢 Huge (2^1699) | 🔴 No | 🔴 Slow | 🟡 Large (0.5 KB) | 🟡 Complex | 🔴 No |
| ChaCha20† | 🟢 Good | 🟢 Secure | 🟢 Yes | 🟢 Yes (2^128) | 🟢 2^128 | 🟢 Jump ahead, Distance | 🔴 Fairly Slow | 🟡 Plump (0.1 KB) | 🟡 Complex | 🔴 No |
| Minstd (LCG) | 🔴 Many Issues | 🔴 Trivial | 🟢 Yes | 🔴 No | 🔴 Tiny < 2^32 | 🟢 Jump ahead, Distance | 🟡 Acceptable | 🟢 Very compact | 🟢 Very small | 🔴 No |
| LCG 64/32 | 🔴 Many Issues | 🟡 Published Algos | 🟢 Yes | 🟢 Yes 2^63 | 🟢 Okay 2^64 | 🟢 Jump ahead, Distance | 🟢 Very fast | 🟢 Very compact | 🟢 Very small | 🔴 No |
| XorShift 32 | 🔴 Many Issues | 🔴 Trivial | 🟢 Yes | 🔴 No | 🔴 Small 2^32 | 🟡 Jump ahead | 🟢 Fast | 🟢 Very compact | 🟢 Very small | 🔴 No |
| XorShift 64 | 🔴 Many Issues | 🔴 Trivial | 🟢 Yes | 🔴 No | 🟢 Okay 2^64 | 🟡 Jump ahead | 🟢 Fast | 🟢 Very compact | 🟢 Very small | 🔴 No |
| RanQ | 🟡 Some Issues | 🔴 Trivial | 🟢 Yes | 🔴 No | 🟢 Okay 2^64 | 🟡 Jump ahead | 🟢 Fast | 🟢 Very compact | 🟢 Very small | 🔴 No |
| XorShift* 64/32 | 🟢 Excellent | 🟡 Unknown? | 🟢 Yes | 🔴 No | 🟢 Okay 2^64 | 🟡 Jump ahead | 🟢 Fast | 🟢 Very compact | 🟢 Very small | 🔴 No |
2. What is PCG? Learn PCG from Scratch
2.1 The foundation: LCG [2]
The most basic PRNG [3] uses this recurrence:
This is only integer modular arithmetic. .
It is fast, but it has huge weaknesses:
| Problem | Why |
|---|---|
| Poor randomness | Bits are highly correlated |
| Easy to predict | Given a few outputs → recover the sequence |
| Low quality high-order entropy | Top bits & bottom bits are uneven |
PCG starts from this formula, but enhances it.
2.2 PCG = LCG + Permutation
Key idea:
Instead of returning the state directly, apply a randomizing permutation to it.
where scrambles bits to break patterns.
So PCG is:
PCG doesn’t rely on a stronger LCG— it relies on a brilliant output function.
Permutation in PCG
Key properties we want of this permutation:
| Property | Meaning |
|---|---|
| bijective | every 64-bit input maps to a unique 64-bit output |
| nonlinear | breaks the linear structure of LCG outputs |
| statistically strong | spreads entropy across bits |
| predictable only with effort | increases difficulty of state recovery |
The specific permutation used in PCG-XSH-RR (the standard version) is a combination of XOR-shift, high-bit extraction, and a data-dependent bit rotation:
Step 1 — XOR-Shift (XSH)
Mix the state with a shifted copy of itself:
This step reduces 64-bit state to a scrambled 32-bit value while blending high bits into low bits — eliminating weak low-bit structure of raw LCG.
Step 2 — Random Rotate (RR)
Compute a rotation amount using the high bits of the state:
Then rotate the previous output value right by that amount:
This rotation is state-dependent, meaning each output is shuffled differently.
3. PCG: From Theory to Implementation
3.1 Precise Definition
Using everything above, we can now define a PCG generator precisely. [4]
A PCG generator is fully determined by two components:
- State transition function (LCG core)
- Output permutation function (scrambler)
Formally:
Where:
| Symbol | Meaning |
|---|---|
| 64-bit internal state (never returned directly) | |
| multiplier constant, odd, fixed per RNG instance | |
| increment constant (stream selector), must be odd | |
| output permutation for statistical quality | |
| the returned random number |
This structure is modular: any LCG + any permutation = a PCG variant.
The most common and recommended version is PCG-XSH-RR 64/32 → 64-bit state, produces 32-bit outputs.
3.2 Official PCG-XSH-RR Output Function
Expanded step-by-step:
| Step | Operation |
|---|---|
| extract high bits | |
| mix entropy (XOR-shift) | |
| compress to 32 bits | |
| derive rotation amount | |
| final non-linear permutation |
Result:
This is the heart of PCG.
3.3 Official Reference Implementation (C++)
uint32_t pcg32_random_r(uint64_t& state, uint64_t inc) { uint64_t old = state; state = old * 6364136223846793005ULL + (inc | 1ULL);
uint32_t xorshifted = ((old >> 18u) ^ old) >> 27u; uint32_t rot = old >> 59u;
return (xorshifted >> rot) | (xorshifted << ((32 - rot) & 31));}Notes:
stateevolves using LCG stepxorshiftedimplements the XSH algorithmrotcomes from the 59 highest bits- final line is the RR rotation → the output
This is exactly the formula we defined above.
Reference
Some information may be outdated