Random number generation generally falls into a couple of categories: statistically-sound, cryptographically-secure generation, and 'I just want a random number' generation. The latter is the more common case, particularly with games, benchmarking and testing. It's not dreadfully important that someone can reverse-engineer the sequence, or that the sequence should have some layer of possible predictability; what's important is that it is, to the naive end user, unpredictable. As it turns out, PCG rand is a random number generator by Melissa O'Neill which has both the properties of being statistically sound in terms of it's distribution, and also blazingly fast - about 20% faster than the fastest xor-shift RNG, and about 700% faster than most implementations of C/C++'s rand().

It also avoids the trap which xor-shift RNG and most rand() implementations have, which is lower statistical variability in the lower bits. And since in most 'I just want a random number' scenarios, the range you're looking for a number within is typically small, the lower bits count. It still is not cryptographically secure (like Arc4Random), but neither is rand(). The speed is important - in microbenchmarking, having an RNG which is taking up 20% of the overall CPU time (as rand() was in some of mine) can disrupt and reduce the accuracy of measurements. And of course in games and other high-performance scenarios, you need a RNG which uses as little CPU time as possible.

My adaptation of Melissa O'Neill's algorithm greatly simplifies the interface so that it's more of a straight-forward replacement for scenarios where people would otherwise be using rand() or something similar, and adds noexcept specifiers. The original interface is more suited for those looking for in-depth random number generation with a lot more control and alternative approaches. I also enable support for C++98/03 code by substituting a 32-bit xor_shift128++ generator when those modes are detected - because PCG relies on specifiable cross-compilers types of at least 32 and 64-bit, which are difficult to guarantee in C++98/03.

There are two functions, plf::rand() and plf::srand(). Unlike rand() (which returns an int), plf::rand() returns an unsigned int, and like srand(), plf::srand() takes an unsigned int as it's argument. The function accesses and modifies internal state objects, which may cause data races with concurrent calls to rand or srand.

The original code for the Permuted Congruential generator is under an Apache license, which allows for derivative code to use alternative licenses. plf::rand is under a permissive zlib license. This means: Software is used on 'as-is' basis. It can be modified and used in commercial software. Authors are not liable for any damages arising from its use. The distribution of a modified version of the software is subject to the following restrictions:

- The authorship of the original software must not be misrepresented,
- Altered source versions must not be misrepresented as being the original software, and
- The license notice must not be removed from source distributions.

Download here (6kb zip file) or
view the repository

The rand function library is a simple .h header file, to be included with a #include
command.

The zip includes a short benchmark comparing generation speed with rand(). This requires plf::nanotimer to run.

- unsigned int plf::rand();

Return an unsigned 32-bit pseudo-random integer using pcg_rand in C++11 or higher compilers, xor_shift128++ in lower.

- void plf::srand(unsigned int seed);

Seed the random number generator with an unsigned 32-bit integer.

- 2024-04-10: v1.0.6 - Minor optimisation to srand() under C++11 and earlier. Change to vcpkg-compatible versioning.
- 2022-08-27: v1.05 - Corrections/reductions to compiler feature detection routines.
- 2021-05-26: v1.04 - Correction to compiler detection routines for clang/gcc running in MSVC environment.
- 2021-05-23: v1.03 - Replacement of unary minus on unsigned integer with two's complement, in the pcg_rand version of plf::rand, to avoid warnings from clang and MSVC. Since two's complement is how unary minus is implemented on most platforms this is unproblematic in terms of the algorithm and has no performance impact.
- 2021-01-13: v1.02 - Reduction of compiler feature macros for reasons of readability, code size and convenience of updating between the different headers. Hopefully PLF_ by itself will be enough to disambiguate these from similarly-named macros.
- 2021-01-03: v1.01 - Replaced C++03 gen with xor_shift128++ as it is difficult to guarantee 64-bit unsigned integers in C++03 and below - particularly if they're running as 32-bit compilers. Subsequently renamed to rand() instead of pcg_rand().
- 2020-12-24: v1.00 - First release

Contact:

plf:: library and this page Copyright (c) 2022, Matthew Bentley