Some (More) C++ PRNG Implementations

Nearly a year ago, I wrote a post suggesting some good alternatives to PCG. As part of that post, I included links to C++ implementations of those PRNGs, following C++-11 conventions (although omitting rarely-used features such as state I/O).

Since that post, I've written my own C++ implementations of a few more generation schemes. Links and brief descriptions below.

JSF: Bob Jenkins's Small/Fast Chaotic PRNG

The gist jsf.hpp contains an implementation of Bob Jenkins's “Small/Fast PRNG”, which is based on a random invertible mapping—what some call a “chaotic PRNG”. I discussed this generator in a previous post, but the short version is that it passes stringent statistical tests, seems to be quite annoying to predict, and works well. It's also very fast.

My C++ implementation provides the standard jsf64 and jsf32 variants, as well as a number of variations Jenkins suggests that use different constants that should also work well. It also includes some tiny versions, jsf16 and jsf8, which are mostly designed for experimental use (these smaller variants should not be expected to pass extensive statistical tests).

GJrand: David Blackman's Chaotic PRNG

The gist gjrand.hpp contains an implementation of David Blackman's gjrand PRNG, which is based on a random invertible mapping that includes a counter to guarantee no small cycles. I will discuss this generator in a future post, but the short version is that it passes stringent statistical tests, and works well. It's also fast, although not quite as fast as JSF, but on the other hand appears to have slightly stronger bit-mixing properties than JSF.

My C++ implementation provides the standard gjrand64 variant, and at my request Blackman also made a gjrand32 variant. It also includes some tiny versions, gjrand16 and gjrand8, which are mostly designed for experimental use (these smaller variants should not be expected to pass extensive statistical tests).

SFC: Chris Doty-Humphrey's Chaotic PRNG

The gist sfc.hpp contains an implementation of Chris Doty-Humphrey's sfc PRNG, which is based on a random invertible mapping that includes a counter to guarantee no small cycles. I will discuss this generator in a future post, but the short version is that it passes stringent statistical tests, and works well. It's also very fast, although it appears to have slightly weaker bit-mixing properties than JSF or gjrand.

My C++ implementation provides the standard sfc64 and sfc32 variants. It also includes some tiny versions, sfc16 and sfc8, which are mostly designed for experimental use (these smaller variants should not be expected to pass extensive statistical tests).

Lehmer: A 128-Bit Lehmer PRNG

The gist lehmer.hpp provides a C++ implementation of fast, 128-bit, Lehmer-style PRNGs (MCGs) as discussed in a previous post. On 64-bit x86 CPUs these are some of the fastest good-quality PRNGs I am aware of.

This code requires C++17 and a __uint128_t type (supported by Clang, GCC, and Intel's compiler). It provides mcg128 and mcg128_fast, the latter using a 64-bit multiplicative constant rather than the usual 128-bit constant for additional speed.

SplitMix: 32-Bit and 64-Bit Output from 128-Bit State

The gist splitmix.hpp provides a C++ implementation of SplitMix, as described by Guy L. Steele, Jr., Doug Lea and Christine H. Flood in the paper Fast Splittable Pseudorandom Number Generators and implemented in Java 8 as SplittableRandom (cannonical source code).

This C++ implementation avoids the bugs present in implementations directly derived from the (erroneous) code in the SplitMix paper. Without these bugs it has all properties, good and bad, that are inherent in SplitMix's design (discussed at length in previous posts). In particular, the 64-bit–output variant, splitmix64, may not be suitable for general-purpose use because it has the property that each number is only output once (similar to _once_insecure PCG variants), which can be detected as a deviation from random behavior by statistical tests. The 32-bit–output variant, splitmix32, does not have this issue.

Unlike the other implementations described in this post, this implementation includes both jump-ahead and distance operations (most implementations of SplitMix do not offer these features, although they are quite easy to provide). Also, in contrast to other implementations, the two variants are represented as separate classes (although it is possible to cast between them; splitmix32 is a subclass of splitmix64).

Arc4: A Classic

The gist arc4.hpp provides a C++ implementation of Arc4, based on the OpenBSD implementation (specifically the version found in Apple's Libc-594.9.4).

As a general-purpose PRNG, it is rather slow, and it is also slow by the standards of modern cryptographic PRNGs and is also considered too weak to use for cryptographic purposes. It is, however, of historical interest and can be useful in testing to see how sensitive a algorithms are to PRNG speed.

And more…

Other generators are linked to in my earlier post. I have also updated my C++ implementation of Xoroshiro to reflect the most recent changes made by Vigna & Blackman, and created a C++ implementation of their newest scheme, Xoshiro.