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.
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:
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:
#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
#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;
}