[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