.. _guide_random:
===============
Random Module
===============
In MOCCA, the random numbers are generated in two steps. First, a :ref:`guide_random_engine` creates a sequence of 32 or 64 pseudorandom bits that are later transforms into random number that follows a specific probability distribution (such as Uniform and Exponential) within a specific interval by the :ref:`guide_random_generator`.
.. _guide_random_engine:
RandomEngine
------------
MOCCA implement three different pseudorandom generators:
+--------------+----------+-------------------+---------------------+-----------------+
| **Name** | **Base** | **Output (bits)** | **Period** | **Streams** |
+==============+==========+===================+=====================+=================+
| PCG32 | LCG | 32 | :math:`2^{64}` | :math:`2^{63}` |
+--------------+----------+-------------------+---------------------+-----------------+
| PCG64 | LCG | 64 | :math:`2^{128}` | :math:`2^{127}` |
+--------------+----------+-------------------+---------------------+-----------------+
| SplitMix32 | None | 32 | :math:`2^{64}` | 1 |
+--------------+----------+-------------------+---------------------+-----------------+
| SplitMix64 | None | 64 | :math:`2^{64}` | 1 |
+--------------+----------+-------------------+---------------------+-----------------+
| Xoroshiro128 | LSFR | 32 | :math:`2^{128} - 1` | 1 |
+--------------+----------+-------------------+---------------------+-----------------+
| Xoroshiro256 | LSFR | 64 | :math:`2^{256} - 1` | 1 |
+--------------+----------+-------------------+---------------------+-----------------+
PCG
^^^
The `Permuted Congruential Generator (PCG) `_ was designed by Melissa O'Neil. The main idea of the PCG is to pass the output of a fast, well-known pseudorandom generator, such as a Linear Congruential Generator (LCG), into a permutation function to enhance its statistical properties. PCG is the default generator from the popular `NumPy `_ library. There are two ``RandomEngine``\s from this scheme:
- ``PCG32`` (``XSH-RR`` variant) first applies a xor and a shift on the high bits, then performs a random rotation on the output of a 64-bit LCG.
- ``PCG64`` (`DXSM `_ variant) applies a xor followed by a shift and multiplication on the output of a 128-bit LCG. It is **recommend** to use a compiler and platform that supports 128-bit arithmetic. Otherwise, MOCCA must emulate all the operations, which may result in a significant performance loss.
See :ref:`api_pcg` in the API Reference for all available methods.
SplitMix
^^^^^^^^
The `SplitMix `_ is a fast *splittable* random number generator proposed by Guy L. Steele, Jr., Doug Lea, and Christine H. Flood. SplitMix is a counter-based generator that uses the MurmurHash3 finalizer as a mixing function. The main feature of the SplitMix is the ability to "split" a generator in two, i.e., generating two instances from one. MOCCA uses the "fixed" version of SplitMix (`Bugs in SplitMix(es) `_). See :ref:`api_splitmix` in the API Reference for all available methods.
Xoroshiro
^^^^^^^^^
The `Xoroshiro `_ family of random number generators was created by David Blackman and Sebastiano Vigna. Xoroshiro consists of a linear generator (i.e., a LFSR, or linear-feedback shift register) and a scrambler. A linear generator produces a bit sequence using a xor, rotate, shift and another xor. This sequence is then passed to a scrambler to improve its quality. MOCCA uses the ``++`` scrambler, i.e., applies a sum, a rotation and then another sum to the bit sequence. Xoroshiro is currently used in the JavaScript engines of Chrome, Safari and Firefox and it is part of `Java's random module `_.
The internal state of the ``Xoroshiro128`` and ``Xoroshiro256`` are initialized using the ``SplitMix`` generator. See :ref:`api_xoroshiro` in the API Reference for all available methods.
.. _guide_random_generator:
Generator
-----------
The :ref:`api_generator` then uses the random bit sequence from the :ref:`guide_random_engine` to generate samples from specific distributions, shuffle/permute containers, choose a random element from the container, etc. The ``DefaultGenerator`` uses ``PCG64`` as :ref:`guide_random_engine`.
.. code:: cpp
using namespace mocca::random;
DefaultGenerator rng; // Creates a new DefaultGenerator with the default seed and stream
int n = rng.uniform(-10, 10); // Generates a random integer from U(-10, 10)
double f = rng(); // Generates a random double from U(0, 1)
double e = rng.exp(2.0); // Generates a random double from EXP with 2.0 as the rate parameter
DefaultGenerator rng2(8723, 6781); // Creates a new DefaultGenerator with seed=8723 and stream=6781
Generator rng3(87771); // Creates a new Generator using the Xoroshiro128 as RandomEngine with seed = 87771
When using multiple ``Generator`` instances, it is recommended to use a hash function (such as the `hash64()` or `hash128()` methods) to create the seeds (and streams, if applicable) in order to spread them over a wider range of initialization states of the ``RandomEngine`` and reducing the chances of similarities between the instances.