From 437555fd6c495915773b0f9ade7aad3fd0a73a1b Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 21 Mar 2017 16:36:33 +0100 Subject: Implement Xoroshiro116+ and improve statisticals Implement Xoroshiro116+ as 'exrop' with fixes. Deprecate all old algorithms but reincarnate 'exs1024' as 'exs1024s' and 'exsplus' as 'exsp' with fixes. Fixes: * Avoid skew for uniform integers caused by using a simple 'rem' operation for range confinement. Correctness requires retry with new random value for an unfortunate first value. * Implement a correct algorithm that collects enough random bits for ranges larger than the generator's precision. * Fix uniform density for floats by acquiring 53 bits then multiplying with 2.0^(-53) which produces floats on the form N * 2.0^(-53). --- lib/stdlib/doc/src/rand.xml | 130 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 23 deletions(-) (limited to 'lib/stdlib/doc/src/rand.xml') diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml index 2ddf3021ac..470dc4da97 100644 --- a/lib/stdlib/doc/src/rand.xml +++ b/lib/stdlib/doc/src/rand.xml @@ -50,26 +50,73 @@

The following algorithms are provided:

- exsplus + exrop -

Xorshift116+, 58 bits precision and period of 2^116-1

+

Xoroshiro116+, 58 bits precision and period of 2^116-1

Jump function: equivalent to 2^64 calls

- exs64 - -

Xorshift64*, 64 bits precision and a period of 2^64-1

-

Jump function: not available

-
- exs1024 + exs1024s

Xorshift1024*, 64 bits precision and a period of 2^1024-1

Jump function: equivalent to 2^512 calls

+ exsp + +

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 default algorithm, + that now has been superseeded by Xoroshiro116+ (exrop). + Since there is no native 58 bit rotate instruction this + algorithm executes a little (say < 15%) faster than exrop. + See the + algorithms' homepage. +

+
-

The default algorithm is exsplus. If a specific algorithm is +

+ The default algorithm is exrop (Xoroshiro116+). + If a specific algorithm is required, ensure to always use - seed/1 to initialize the state.

+ seed/1 to initialize the state. +

+ +

+ 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 @@ -99,19 +146,19 @@ R1 = rand:uniform(),

Use a specified algorithm:

-_ = rand:seed(exs1024),
+_ = rand:seed(exs1024s),
 R2 = rand:uniform(),

Use a specified algorithm with a constant seed:

-_ = rand:seed(exs1024, {123, 123534, 345345}),
+_ = rand:seed(exs1024s, {123, 123534, 345345}),
 R3 = rand:uniform(),

Use the functional API with a non-constant seed:

-S0 = rand:seed_s(exsplus),
+S0 = rand:seed_s(exrop),
 {R4, S1} = rand:uniform_s(S0),

Create a standard normal deviate:

@@ -127,6 +174,39 @@ S0 = rand:seed_s(exsplus),

+

+ For all these generators the lowest bit(s) has got + a slightly less random behaviour than all other bits. + 1 bit for exrop (and exsp), + and 3 bits for exs1024s. + See for example the explanation in the + + Xoroshiro128+ + + generator source code: +

+
+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 + use something like this: +

+
(rand:uniform(16) > 8)
+

+ And for a general range, with N = 1 for exrop, + and N = 3 for exs1024s: +

+
(((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. +

+ + @@ -141,6 +221,18 @@ S0 = rand:seed_s(exsplus), + + +

Algorithm-dependent state.

+
+ + + +

+ Algorithm-dependent state that can be printed or saved to file. +

+
+

Algorithm specific internal state

@@ -154,16 +246,8 @@ S0 = rand:seed_s(exsplus),

Algorithm specific internal state

- -

Algorithm-dependent state.

-
- - - -

- Algorithm-dependent state that can be printed or saved to file. -

-
+ +

Algorithm specific internal state

-- cgit v1.2.3