SkillAgentSearch skills...

CppRandLib

Many best in class pseudo random generators grouped into one simple library - c++ versions.

Install / Use

/learn @schmouk/CppRandLib

README

<img src="lib-banner.jpg" alt="Library banner">

license Latest release code_coverage tests

Many best in class pseudo random generators grouped into one simple library - c++11 and c++20 versions.

This is a c++ counterpart of library PyRandLib (Python, see Github repository https://github.com/schmouk/PyRandLib/ ).

CppRandLib github web pages are here: https://schmouk.github.io/CppRandLib/


License

CppRandLib is distributed under the MIT license for its largest use.
If you decide to use this library, please mention it and add the copyright notice to your software as stated in the LICENSE file.

Copyright (c) 2022-2026 Philippe Schmouker, <ph.schmouker (at) gmail.com>

Permission is hereby granted,  free of charge,  to any person obtaining a copy
of this software and associated documentation files (the "Software"),  to deal
in the Software without restriction, including  without  limitation the rights
to use,  copy,  modify,  merge,  publish,  distribute, sublicense, and/or sell
copies of the Software,  and  to  permit  persons  to  whom  the  Software  is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS",  WITHOUT WARRANTY OF ANY  KIND,  EXPRESS  OR
IMPLIED,  INCLUDING  BUT  NOT  LIMITED  TO  THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT  SHALL  THE
AUTHORS  OR  COPYRIGHT  HOLDERS  BE  LIABLE  FOR  ANY CLAIM,  DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  TORT OR OTHERWISE, ARISING FROM,
OUT  OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Intro

This library implements some of the best-in-class pseudo-random generators as evaluated by Pierre L'Ecuyer and Richard Simard in their famous paper "TestU01: A C library for empirical testing of random number generators" (ACM Trans. Math. Softw. Vol. 33 N.4, August 2007 - see reference [1]. The reader might then want to take the benefit of reading L'Ecuyer & Simard's paper.

CppRandLib implements also more recent pseudo-random generators with best known randomness characteristics. Their exhaustive list is provided here below (since CppRandLib 2.0, 2025/06):

  • Collatz-Weyl Generator (2023)
    (CWG, 64 bits, 128 bits or 128/64 bits, 3 different values of periodicities, see reference [8]);
  • Linear Congruential Generator
    (LCG, or FastRand, 32 bits or 63 bits, 2 different values of periodicities, see reference [1]);
  • Lagged Fibonacci Generator (1985)
    (LFib, 64 bits, 4 different periodicities, see reference [4]);
  • Maximally Equidistributed Long-period Linear Generator (2018)
    (MELG, 64/32 bits, 3 different values of periodicities, see reference [11]);
  • Multiple Recursive Generator (2000, 2005)
    (MRG, 31 bits or 32 bits, 3 different values of periodicities, see references [2] and [3]);
  • Permutated Congruential Generator (2014)
    (PCG, 64, 128 bits or 64/32 bits, 3 different values of periodicities, see reference [7]);
  • Squares (2022)
    (Squares, 32 or 64 bits, 1 value of periodicity but 32- or 64-bits output values, see reference [9]);
  • Well-Equilibrated Long-period Linear generators (2006)
    (WELL, 32 bits, 4 different values of periodicities, see reference [6]);
  • Scrambled Linear Pseudorandom Number Generators (2018)
    (Xoroshiro, 64 bits, 4 different values of periodicities, see reference [10]).

Each of the Pseudo Random Numbers Generators (PRNGs) implemented in CppRandLib is self documented. Names of classes directly refer to the type of PRNG they implement augmented with some number characterizing their periodicity. All of their randomness characteristics are explained in every related module.

Latest version of CppyRandLib* is version 2.1.2, released by October 2025.

  • It provides also implementations dedicated to different standards of c++: c++11 and c++20.
  • Time performances of every PRNG have been evaluated and are provided in a table below - see section CPU Performances.
  • Furthermore, starting from release 2.1 CppRandLib is fully validated. gTest is now used to unit-test the code with a full 100% code coverage.

Why not Mersenne twister?

The Mersenne Twister PRNG (MT) proposed by Matsumoto and Nishimura - see [5] - is currently the most widely used PRNG algorithm. The c++ STL implements this PRNG as the standard default one. It is also implemented in Python and Java standard libraries for instance.

It offers a very good period (2^19937, i.e. about 4.3e+6,001). Unfortunately, this PRNG is a little bit long to compute (up to 3 times than LCGs, or 60% more than LFibs, see below at section 'Architecture overview'). It embeds an internal state of 624 32-bits integers, which is larger to far larger than some other PRNGs. Moreover, MT fails four of the hardest TestU01 tests. You can still use it as your preferred PRNG but CppRandLib implements many other PRNGs that are either far faster, or that are far better in terms of generated pseudo-randomness than the Mersenne twister PRNG while consuming less memory space.


Installation

Currently, the only way to install CppRandLib is to download the .zip or .tar.gz archive, then to directly put sub-directory c++11 or c++20 from archive into your project directory.
See CppRandLib repository for an easy access to download versions or click on link Releases on the home page of GitHub repository.


Randomness evaluation

In [1], every known PRNG at the time of the editing (2007) has been tested according to three different sets of tests:

  • small crush is a small set of simple tests that quickly tests some of the expected characteristics for a pretty good PRNG;
  • crush is a bigger set of tests that test more deeply expected random characteristics;
  • big crush is the ultimate set of difficult tests that any good PRNG should definitively pass.

We give you here below a copy of the resulting table for the PRNGs that have been implemented in CppRandLib, as provided in [1], plus the Mersenne twister one which is not implemented in CppRandLib. Times present in this table are the measured ones in [1] by the time of their evaluations (i.e. 2007).
We add in this table the evaluations provided by the authors of every new PRNGs that have been published after the publication of [1]. Some fields may be missing for them in the belowing table, then.
Notice: a comparison of the computation times for all implemented PRNGs in CppRandLib is provided in an another table - see next subsection.

<table style="text-align:center"> <thead> <tr> <th>CppRandLib class</th> <th>TU01 generator name (1)</th> <th>Memory Usage</th> <th>Period</th> <th>SmallCrush fails</th> <th>Crush fails</th> <th>BigCrush fails</th> <th>time-64 bits</th> <th>time-32bits</th> </tr> </thead> <tbody> <tr> <td>Cwg64</td> <td>*CWG64*</td> <td>8 x 4-bytes</td> <td>&gt;= 2^64</td> <td>0</td> <td>0</td> <td>0</td> <td>n.a.</td> <td>n.a.</td> </tr> <tr> <td>Cwg128_64</td> <td>*CWG128-64*</td> <td>10 x 4-bytes</td> <td>&gt;= 2^64</td> <td>0</td> <td>0</td> <td>0</td> <td>n.a.</td> <td>n.a.</td> </tr> <tr> <td>Cwg128</td> <td>*CWG128*</td> <td>16 x 4-bytes</td> <td>&gt;= 2^128</td> <td>0</td> <td>0</td> <td>0</td> <td>n.a.</td> <td>n.a.</td> </tr> <tr> <td>FastRand32</td> <td>LCG(2^32, 69069, 1)</td> <td>1 x 4-bytes</td> <td>2^32</td> <td>11</td> <td>106</td> <td>*too many*</td> <td>0.67</td> <td>3.20</td> </tr> <tr> <td>FastRand63</td> <td>LCG(2^63, 9219741426499971445, 1)</td> <td>2 x 4-bytes</td> <td>2^63</td> <td>0</td> <td>5</td> <td>7</td> <td>0.75</td> <td>4.20</td> </tr> <tr> <td>LFib78</td> <td>LFib(2^64, 17, 5, +)</td> <td>34 x 4-bytes</td> <td>2^78</td> <td>0</td> <td>0</td> <td>0</td> <td>1.1</td> <td>n.a.</td> </tr> <tr> <td>LFib116</td> <td>LFib(2^64, 55, 24, +)</td> <td>110 x 4-bytes</td> <td>2^116</td> <td>0</td> <td>0</td> <td>0</td> <td>1.0</td> <td>n.a.</td> </tr> <tr> <td>LFib668</td> <td>LFib(2^64, 607, 273, +)</td> <td>1,214 x 4-bytes</td> <td>2^668</td> <td>0</td> <td>0</td> <td>0</td> <td>0.9</td> <td>n.a.</td> </tr> <tr> <td>LFib1340</td> <td>LFib(2^64, 1279, 861, +)</td> <td>2,558 x 4-bytes</td> <td>2^1,340</td> <td>0</td> <td>0</td> <td>0</td> <td>0.9</td> <td>n.a.</td> </tr> <tr> <td>Melg607</td> <td>*Melg607-64*</td> <td>21 x 4-bytes</td> <td>2^607</td> <td>0</td> <td>0</td> <td>0</td> <td>n.a.</td> <td>n.a</td> </tr> <
View on GitHub
GitHub Stars5
CategoryDevelopment
Updated2mo ago
Forks0

Languages

C++

Security Score

90/100

Audited on Jan 26, 2026

No findings