From c50f179a15ad8c8bcbc7a71101a9ca23f19f6e8f Mon Sep 17 00:00:00 2001
From: Cristian Greco
Date: Wed, 6 Oct 2010 03:22:41 +0200
Subject: Fix a bug in the implementation of the pseudo-random number generator
This commit fixes an error in the mathematical formula of the Wichmann-Hill
pseudo-random number generator. In particular, the implementation used until
now produces sequences which differ from the expected ones by an extra starting
number, which is instead the very last value of the sequence.
This bug amplified the effect of extremely correlated initial numbers when
seeding different generators with very similar seed values.
---
lib/stdlib/src/random.erl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index 01227c29b4..d94722cb33 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -86,7 +86,7 @@ uniform() ->
B2 = (A2*172) rem 30307,
B3 = (A3*170) rem 30323,
put(random_seed, {B1,B2,B3}),
- R = A1/30269 + A2/30307 + A3/30323,
+ R = B1/30269 + B2/30307 + B3/30323,
R - trunc(R).
%% uniform(N) -> I
@@ -110,7 +110,7 @@ uniform_s({A1, A2, A3}) ->
B1 = (A1*171) rem 30269,
B2 = (A2*172) rem 30307,
B3 = (A3*170) rem 30323,
- R = A1/30269 + A2/30307 + A3/30323,
+ R = B1/30269 + B2/30307 + B3/30323,
{R - trunc(R), {B1,B2,B3}}.
%% uniform_s(N, State) -> {I, NewState}
--
cgit v1.2.3
From b52a2170d13fe7ff6e4e3b146b63d8f68c2aaadf Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Mon, 28 Mar 2011 16:38:57 +0200
Subject: Improve algorithm in module random.
Avoid seed values that are even divisors of the primes
and by that prevent getting seeds that are stuck on zero.
Example: random:seed(0,0,0) would produce a series of only zeros.
---
lib/stdlib/doc/src/random.xml | 7 ++++++-
lib/stdlib/src/random.erl | 44 ++++++++++++++++++++++++-------------------
2 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml
index dcc6d756e1..26f22db48e 100644
--- a/lib/stdlib/doc/src/random.xml
+++ b/lib/stdlib/doc/src/random.xml
@@ -4,7 +4,7 @@
- 19962009
+ 19962011
Ericsson AB. All Rights Reserved.
@@ -146,6 +146,11 @@
random_seed to remember the current seed.
If a process calls uniform/0 or uniform/1 without
setting a seed first, seed/0 is called automatically.
+ The implementation changed in R15. Upgrading to R15 will break
+ applications that expect a specific output for a given seed. The output
+ is still deterministic number series, but different compared to releases
+ older than R15. The seed {0,0,0} will for example no longer
+ produce a flawed series of only zeros.
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index d94722cb33..606edbb1fb 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -26,6 +26,10 @@
-export([seed/0, seed/1, seed/3, uniform/0, uniform/1,
uniform_s/1, uniform_s/2, seed0/0]).
+-define(PRIME1, 30269).
+-define(PRIME2, 30307).
+-define(PRIME3, 30323).
+
%%-----------------------------------------------------------------------
%% The type of the state
@@ -44,7 +48,11 @@ seed0() ->
-spec seed() -> ran().
seed() ->
- reseed(seed0()).
+ case seed_put(seed0()) of
+ undefined -> seed0();
+ {_,_,_} = Tuple -> Tuple
+ end.
+
%% seed({A1, A2, A3})
%% Seed random number generation
@@ -60,17 +68,15 @@ seed({A1, A2, A3}) ->
-spec seed(integer(), integer(), integer()) -> 'undefined' | ran().
seed(A1, A2, A3) ->
- put(random_seed,
- {abs(A1) rem 30269, abs(A2) rem 30307, abs(A3) rem 30323}).
+ seed_put({(abs(A1) rem (?PRIME1-1)) + 1, % Avoid seed numbers that are
+ (abs(A2) rem (?PRIME2-1)) + 1, % even divisors of the
+ (abs(A3) rem (?PRIME3-1)) + 1}). % corresponding primes.
--spec reseed(ran()) -> ran().
-
-reseed({A1, A2, A3}) ->
- case seed(A1, A2, A3) of
- undefined -> seed0();
- {_,_,_} = Tuple -> Tuple
- end.
+-spec seed_put(ran()) -> 'undefined' | ran().
+
+seed_put(Seed) ->
+ put(random_seed, Seed).
%% uniform()
%% Returns a random float between 0 and 1.
@@ -82,11 +88,11 @@ uniform() ->
undefined -> seed0();
Tuple -> Tuple
end,
- B1 = (A1*171) rem 30269,
- B2 = (A2*172) rem 30307,
- B3 = (A3*170) rem 30323,
+ B1 = (A1*171) rem ?PRIME1,
+ B2 = (A2*172) rem ?PRIME2,
+ B3 = (A3*170) rem ?PRIME3,
put(random_seed, {B1,B2,B3}),
- R = B1/30269 + B2/30307 + B3/30323,
+ R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
R - trunc(R).
%% uniform(N) -> I
@@ -107,10 +113,10 @@ uniform(N) when is_integer(N), N >= 1 ->
-spec uniform_s(ran()) -> {float(), ran()}.
uniform_s({A1, A2, A3}) ->
- B1 = (A1*171) rem 30269,
- B2 = (A2*172) rem 30307,
- B3 = (A3*170) rem 30323,
- R = B1/30269 + B2/30307 + B3/30323,
+ B1 = (A1*171) rem ?PRIME1,
+ B2 = (A2*172) rem ?PRIME2,
+ B3 = (A3*170) rem ?PRIME3,
+ R = B1/?PRIME1 + B2/?PRIME2 + B3/?PRIME3,
{R - trunc(R), {B1,B2,B3}}.
%% uniform_s(N, State) -> {I, NewState}
--
cgit v1.2.3