Skip to content

RNG

Good General Resources

Pierre L'Ecuyer's publications

xoshiro/xoroshiro - Sebastiano Vignas webpage

www.pcg-random.org PCG family blog by Melissa O'neill. The pcg paper.

Pseudo Random Number Generators - Agner fogs webpage.

prng google forum

RNG Testing Libraries

It's almost paradoxical that we can statistically test whether the output of an RNG is "random". I think Knuth covers some of the basic ideas of this theory pretty well in TAOCP vol. 2 ch. 2. There are two libraries I'm aware of are "good" and have used:

TestU01

PractRand (sourceforge): (most extensive) Note the sourceforge url is https://pracrand.sourceforge.net without the t.

DieHarder is commonly reference in older articles but it's not as extensive as the two test suites above. The practrand documentation on sourceforge has some nice links. Note that there are many bad libraries and much outdated advice out about RNGs and RNG quality readily available. I recommend reading one of the recent survey papers by L'Ecuyer for an overview. An introduction to the theory of RNGs can also be found in section 2.4 of my Master's thesis and the many works referenced therein.

Using TestU01 in C++

Note that TestU01 is a C-library and expects a function pointer to a prng function. In C++ we generally have RNG classes. The following example shows how you can pass a pointer of a class method (operator() in this case) as a C function pointer and use TestU01 from C++.

Here is a C++ implementaion of the KISS generator:

kiss.hpp
#include <cstdint>

using uint32 = std::uint32_t;

// Marsaglia's KISS generator
class KISS {
private:
    std::uint32_t x=123456789, y=362436000, z=521288629, c=7654321;
    const uint64_t a = 698769069; //ULL; is this required
    uint64_t t;
public:
    double random();
    uint32_t operator()() {
        x = 69069*x + 12345;
        y ^= (y<<13);
        y ^= (y>>17);
        y ^= (y<<5);
        t = a*z + c;
        c = (t>>32);
        return x+y+(z=t);
    }
};

The code below

kiss_test.cpp
#include "kiss.hpp"

extern "C" {
#include "TestU01.h"
}

KISS *kiss_generator;
KISS generator = KISS();

extern "C" {
unsigned int kiss_random() {
    return kiss_generator->operator()();
}
}

int main()
{
// Create TestU01 PRNG object for our generator
kiss_generator = &generator;
unsigned int (*C_generator) () = kiss_random;
unif01_Gen *gen = unif01_CreateExternGenBits("KISS", C_generator);

// Run the tests.
bbattery_SmallCrush(gen);

// Clean up.
unif01_DeleteExternGenBits(gen);

return 0;
}