This module provides a pseudo random number generator.
The module contains a number of algorithms.
The uniform distribution algorithms are based on the
For most algorithms, jump functions are provided for generating non-overlapping sequences for parallel computations. The jump functions perform calculations equivalent to perform a large number of repeated calls for calculating new states, but execute in a time roughly equivalent to one regular iteration per generator bit.
At the end of this module documentation there are also some
Xorshift116**, 58 bits precision and period of 2^116-1
Jump function: equivalent to 2^64 calls
This is the Xorshift116 generator combined with the StarStar scrambler
from the 2018 paper by David Blackman and Sebastiano Vigna:
The generator does not need 58-bit rotates so it is faster
than the Xoroshiro116 generator, and when combined with
the StarStar scrambler it does not have any weak low bits
like
Alas, this combination is about 10% slower than
Xoroshiro928**, 58 bits precision and a period of 2^928-1
Jump function: equivalent to 2^512 calls
This is a 58 bit version of Xoroshiro1024**,
from the 2018 paper by David Blackman and Sebastiano Vigna:
Many thanks to Sebastiano Vigna for his help with the 58 bit adaption.
Xoroshiro116+, 58 bits precision and period of 2^116-1
Jump function: equivalent to 2^64 calls
Xorshift1024*, 64 bits precision and a period of 2^1024-1
Jump function: equivalent to 2^512 calls
Xorshift116+, 58 bits precision and period of 2^116-1
Jump function: equivalent to 2^64 calls
This is a corrected version of the previous
Which algorithm that is the default may change between Erlang/OTP releases, and is selected to be one with high speed, small state and "good enough" statistical properties.
Undocumented (old) algorithms are deprecated but still implemented so old code relying on them will produce the same pseudo random sequences as before.
There were a number of problems in the implementation of the now undocumented algorithms, which is why they are deprecated. The new algorithms are a bit slower but do not have these problems:
Uniform integer ranges had a skew in the probability distribution that was not noticable for small ranges but for large ranges less than the generator's precision the probability to produce a low number could be twice the probability for a high.
Uniform integer ranges larger than or equal to the generator's precision used a floating point fallback that only calculated with 52 bits which is smaller than the requested range and therefore were not all numbers in the requested range even possible to produce.
Uniform floats had a non-uniform density so small values i.e less than 0.5 had got smaller intervals decreasing as the generated value approached 0.0 although still uniformly distributed for sufficiently large subranges. The new algorithms produces uniformly distributed floats on the form N * 2.0^(-53) hence equally spaced.
Every time a random number is requested, a state is used to calculate it and a new state is produced. The state can either be implicit or be an explicit argument and return value.
The functions with implicit state use the process dictionary
variable
If a process calls
The functions with explicit state never use the process dictionary.
Examples:
Simple use; creates and seeds the
R0 = rand:uniform(), R1 = rand:uniform(),
Use a specified algorithm:
_ = rand:seed(exs928ss), R2 = rand:uniform(),
Use a specified algorithm with a constant seed:
_ = rand:seed(exs928ss, {123, 123534, 345345}), R3 = rand:uniform(),
Use the functional API with a non-constant seed:
S0 = rand:seed_s(exsss), {R4, S1} = rand:uniform_s(S0),
Textbook basic form Box-Muller standard normal deviate
R5 = rand:uniform_real(), R6 = rand:uniform(), SND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)
Create a standard normal deviate:
{SND1, S2} = rand:normal_s(S1),
Create a normal deviate with mean -3 and variance 0.5:
{ND0, S3} = rand:normal_s(-3, 0.5, S2),
The builtin random number generator algorithms are not
cryptographically strong. If a cryptographically strong
random number generator is needed, use something like
For all these generators except
Beside passing BigCrush, this generator passes the PractRand test suite up to (and included) 16TB, with the exception of binary rank tests, which fail due to the lowest bit being an LFSR; all other bits pass all tests. We suggest to use a sign test to extract a random Boolean value.
If this is a problem; to generate a boolean with these algorithms use something like this:
(rand:uniform(256) > 128) % -> boolean()
((rand:uniform(256) - 1) bsr 7) % -> 0 | 1
For a general range, with
(((rand:uniform(Range bsl N) - 1) bsr N) + 1)
The floating point generating functions in this module waste the lowest bits when converting from an integer so they avoid this snag.
Algorithm-dependent state.
Algorithm-dependent state that can be printed or saved to file.
A seed value for the generator.
A list of integers sets the generator's internal state directly, after algorithm-dependent checks of the value and masking to the proper word size. The number of integers must be equal to the number of state words in the generator.
An integer is used as the initial state for a SplitMix64 generator. The output values of that is then used for setting the generator's internal state after masking to the proper word size and if needed avoiding zero values.
A traditional 3-tuple of integers seed is passed through algorithm-dependent hashing functions to create the generator's initial state.
Algorithm specific internal state
Algorithm specific internal state
Algorithm specific internal state
Algorithm specific internal state
Algorithm specific internal state
Algorithm specific internal state
Algorithm specific state
0 .. (2^58 - 1)
0 .. (2^64 - 1)
1 .. ((16#1ffb072 * 2^29 - 1) - 1)
Returns, for a specified integer
Returns, for a specified integer
Returns the random number state in an external format.
To be used with
Returns the random number generator state in an external format.
To be used with
Returns the state after performing jump calculation to the state in the process dictionary.
This function generates a
Returns the state after performing jump calculation to the given state.
This function generates a
Returns a standard normal deviate float (that is, the mean is 0 and the standard deviation is 1) and updates the state in the process dictionary.
Returns a normal N(Mean, Variance) deviate float and updates the state in the process dictionary.
Returns, for a specified state, a standard normal deviate float (that is, the mean is 0 and the standard deviation is 1) and a new state.
Returns, for a specified state, a normal N(Mean, Variance) deviate float and a new state.
Seeds random number generation with the specifed algorithm and
time-dependent data if
Otherwise recreates the exported seed in the process dictionary,
and returns the state. See also
Seeds random number generation with the specified algorithm and
integers in the process dictionary and returns the state.
Seeds random number generation with the specifed algorithm and
time-dependent data if
Otherwise recreates the exported seed and returns the state.
See also
Seeds random number generation with the specified algorithm and
integers and returns the state.
Returns a random float uniformly distributed in the value
range
The generated numbers are on the form N * 2.0^(-53), that is; equally spaced in the interval.
This function may return exactly
If neither endpoint is desired you can test and re-try like this:
my_uniform() -> case rand:uniform() of 0.0 -> my_uniform(); X -> X end end.
Returns a random float
uniformly distributed in the value range
Conceptually, a random real number
The generated numbers from this function has got better
granularity for small numbers than the regular
See
Returns, for a specified integer
Returns, for a specified state, random float
uniformly distributed in the value range
The generated numbers are on the form N * 2.0^(-53), that is; equally spaced in the interval.
This function may return exactly
If neither endpoint is desired you can test and re-try like this:
my_uniform(State) -> case rand:uniform(State) of {0.0, NewState} -> my_uniform(NewState); Result -> Result end end.
Returns, for a specified state, a random float
uniformly distributed in the value range
Conceptually, a random real number
The generated numbers from this function has got better
granularity for small numbers than the regular
The concept implicates that the probability to get
exactly zero is extremely low; so low that this function
is in fact guaranteed to never return zero. The smallest
number that it might return is
The value range stated at the top of this function
description is technically correct, but
For example; for all sub ranges
Having to generate extra random bits for
small numbers costs a little performance.
This function is about 20% slower than the regular
Returns, for a specified integer
This section contains special purpose algorithms
that does not use the
Since these algorithms lack the plug-in framework support, generating numbers in a range other than the generator's own generated range may become a problem.
There are at least 3 ways to do this, assuming that the range is less than the generator's range:
To generate a number
This method uses
Low bits from the generator propagate straight through to the generated value, so if the generator has got weaknesses in the low bits this method propagates them too.
If
Say the generator generates a byte, that is,
the generator range is 0..255,
and the desired range is 0..99 (
If
A byte generator when
To generate a number
If the multiplication
High bits from the generator propagate through to the generated value, so if the generator has got weaknesses in the high bits this method propagates them too.
If
To generate a number in the range 0..2^
Masking with
If the generator has got a range that is not a power of 2 and this method is used anyway, it introduces bias in the same way as for the Modulo method above.
In theory it is not certain that this method will ever complete, but in practice you ensure that the probability of rejection is low. Then the probability for yet another iteration decreases exponentially so the expected mean number of iterations will often be between 1 and 2. Also, since the base generator is a full length generator, a value that will break the loop must eventually be generated.
Chese methods can be combined, such as using the Modulo method and only if the generator value would create bias use Rejection. Or using Shift or mask to reduce the size of a generator value so that Truncated multiplication will not create a bignum.
The recommended way to generate a floating point number
(IEEE 745 double, that has got a 53-bit mantissa)
in the range 0..1, that is
0.0 =<
Returns a random 64-bit integer
This generator is used internally in the
Returns a random 58-bit integer
This is an API function into the internal implementation of the
To seed this generator use
This function offers no help in generating a number
on a selected range, nor in generating a floating point number.
It is easy to accidentally mess up the fairly good
statistical properties of this generator when doing either.
See the recepies at the start of this
Returns a new generator state equivalent of the state
after iterating over
See the description of jump functions at the top of this module description.
Returns a new generator state
This generator uses the multiplier 2^32 and the modulus
16#7fa6502 * 2^32 - 1,
which have been selected,
in collaboration with Sebastiano Vigna,
to avoid bignum operations
and still get good statistical quality.
It can be written as:
Because the generator uses a multiplier that is a power of 2 it gets statistical flaws for collision tests and birthday spacings tests in 2 and 3 dimensions, and even these caveats apply only to the MWC "digit", that is the low 32 bits (due to the multiplier) of the generator state.
The quality of the output value improves much by using
a scrambler instead of just taking the low bits.
Function
The low bits of the base generator are surprisingly good,
so the lowest 16 bits actually pass fairly strict PRNG tests,
despite the generator's weaknesses that lie in the high
bits of the 32-bit MWC "digit". It is recommended
to use
On a typical 64 bit Erlang VM this generator executes
in below 8% (1/13) of the time
for the default algorithm in the
This generator is a niche generator for high speed
applications. It has a much shorter period
than the default generator, which in itself
is a quality concern, although when used with the
value scramblers it passes strict PRNG tests.
The generator is much faster than
Returns a 32-bit value
When using this scrambler it is in general better to use
the high bits of the value than the low.
The lowest 8 bits are of good quality and pass right through
from the base generator. They are combined with the next 8
in the xorshift making the low 16 good quality,
but in the range 16..31 bits there are weaker bits
that you do not want to have as the high bits
of your generated values.
Therefore it is in general safer to shift out low bits.
See the recepies at the start of this
For a non power of 2 range less than about 16 bits
(to not get too much bias and to avoid bignums)
truncated multiplication can be used,
which is much faster than using
Returns a 59-bit value
Be careful to not accidentaly create a bignum
when handling the value
It is in general general better to use the high bits
from this scrambler than the low.
See the recepies at the start of this
For a non power of 2 range less than about 29 bits
(to not get too much bias and to avoid bignums)
truncated multiplication can be used,
which is much faster than using
Returns the generator value
Returns a generator state
Without