[erlang-questions] Implementation of a 2006 version of Wichmann-Hill random number generator for Erlang/OTP
Richard O'Keefe
<>
Wed Dec 1 02:58:05 CET 2010
On 1/12/2010, at 11:50 AM, Robert Virding wrote:
> What would be nice is if we could just drop the new algorithm into the old module so we avoid having to have 2 random modules. As I see it the main problem is that the old random has 3 seeds while the new has 4, which makes the seed functions incompatible. Couldn't you just have one seed be two?
Backwards compatibility would be nice, but let's think about what that
involves. If someone currently has a simulation program that saves random
states in a file and reads them back, we really don't want to change what
those states mean. Suppose someone is currently doing
{F,{A1,B1,C1}} = random:uniform_s({A0,B0,C0})
If we turn 3-cycle states into 4-cycle states on the way in, what do we
do on the way out?
The simplest change seems to me to be this.
(1) Decree that the random number module supports at least two kinds of
generators, the 1986 Wichmann-Hill 3-cycle generator with states
{A,B,C}, the 2006 Wichmann-Hill 4-cycle generator with states
{A,B,C,D}, and possibly other generators.
(2) Revise the existing function interfaces as follows:
seed0()
answer the default state, which might be any kind
of supported state. In particular, it might be
a 3-cycle state in one release and a 4-cycle one in
the next.
seed() ->
seed(seed0()).
seed(State)
set the state and return the old state.
The State might be a 3-cycle state, a 4-cycle state,
or whatever other kind of state the system supports.
seed(A,B,C) -> % deprecated
seed({A,B,C}).
uniform()
Generate a random float using whatever the currently
selected generator/state is.
uniform(N)
Generate a random integer using whatever the currently
selected generator/state is.
uniform_s(State) ->
Old_State = seed(State),
Result = uniform(),
New_State = seed(Old_State),
{Result, New_State}.
uniform_s(N, State) ->
Old_State = seed(State),
Result = uniform(N),
New_State = seed(Old_State),
{Result, New_State}.
(3) Currently there's a sort of pun which makes random:seed(now())
useful. We don't want to lose that, and with the interface
above, it continues to work, but it continues to provide a 3-cycle
state. So I suggest adding one more function:
seed(Generator, Time)
where Generator can be wichmann_hill_1986 or
wichman_hill_2006 or whatever else the module supports,
and Time is an Erlang time value as returned by now().
The 4-cycle generator really wants 124 bits of random state,
and erlang:now() only provides at best 40, for practical
purposes. The megaseconds value changes only once every
twelve-and-a-bit days, so might as well be constant for
random number seeding purposes.
(4) Add one more function for information purposes,
supported() -> list(atom).
answer a list of the generators supported by the implementation,
with the default at the head.
I have a version of the 'random' module with this interface if anyone
is interested.
More information about the erlang-questions
mailing list