[mercury-users] random.m: little warning

Martin Stein ms40 at inf.tu-dresden.de
Fri Oct 16 06:05:10 AEST 1998


Hi,

the xxrandom generator is checked, it produces the same output as the one of
Random.hs (hugs-1.4) and accepts only those Seeds which are needed. So it should
work now properly.

I used the interface of random.m and only added two further predicates. The
xxrandom__init_with_limits should be renamed, somehow (good name?). It's very
useful to have a generator which produces numbers in a specific range.

Because I ran into problems using mdi and muo I plainly used in, out. That
should be changed (using copy an such things, too) when mostly_xxx works.

Martin Stein
-------------- next part --------------
%---------------------------------------------------------------------------%
% I took the algorithm from Random.hs distributed with hugs-1.4
%
% extract from Random.hs:
%
%   This module implements a (good) random number generator.
%
%   The June 1988 (v31 #6) issue of the Communications of the ACM has an
%   article by Pierre L'Ecuyer called, "Efficient and Portable Combined
%   Random Number Generators".  Here is the Portable Combined Generator of
%   L'Ecuyer for 32-bit computers.  It has a period of roughly 2.30584e18.
%
%   Transliterator: Lennart Augustsson
%  
%   Modified 10/11/97 by Alastair Reid:
%    Added random and randomIO based on GHC's implementation of the
%    standard Random library.
%---------------------------------------------------------------------------%
%
% translated to Mercury: Stein
% some modes should be changed from 'in' and 'out' to
% 'mdi' and 'muo', resp. (when these modes work)
%
%---------------------------------------------------------------------------%

:- module xxrandom.
:- interface.

:- import_module list.

	% The type `xxrandom__supply' represents a supply of random numbers.
:- type xxrandom__supply.

	% xxrandom__init(Seed, RS): creates a supply of random numbers
        % RS using the specified Seed.
:- pred xxrandom__init(int, xxrandom__supply).
:- mode xxrandom__init(in, out) is det.

	% xxrandom__init_with_limits(Seed, Lo, Up, RS): creates a supply of random numbers
        % RS using the specified Seed
	% the numbers are between Lo and Up,
	% Up - Lo should not be greater than around 2^30
:- pred xxrandom__init_with_limits(int, int, int, xxrandom__supply).
:- mode xxrandom__init_with_limits(in, in, in, out) is det.

	% xxrandom__random(Num, RS0, RS): extracts a number Num in the
	% range RandMin .. RandMax from the random number supply RS0, and
	% binds RS to the new state of the random number supply.
:- pred xxrandom__random(int, xxrandom__supply, xxrandom__supply).
:- mode xxrandom__random(out, in, out) is det.

	% xxrandom__randmax(RandMax, RS0, RS): binds RandMax to the maximum
	% random number that can be returned from the random number
	% supply RS0, and returns RS = RS0.
:- pred xxrandom__randmax(int, xxrandom__supply, xxrandom__supply).
:- mode xxrandom__randmax(out, in, out) is det.

	% xxrandom__randmax(RandMin, RS0, RS): binds RandMin to the minimum
	% random number that can be returned from the random number
	% supply RS0, and returns RS = RS0.
:- pred xxrandom__randmin(int, xxrandom__supply, xxrandom__supply).
:- mode xxrandom__randmin(out, in, out) is det.

	% xxrandom__randlist(N, List, RS0, RS): binds List to a list of N
	% random numbers  from the random number supply RS0, and
	% binds RS to the new state of the random number supply.
:- pred xxrandom__randomlist(int, list(int), xxrandom__supply, xxrandom__supply).
:- mode xxrandom__randomlist(in, out, in, out) is det.

%---------------------------------------------------------------------------%

:- implementation.
:- import_module int, require.

%---------------------------------------------------------------------------%

:- type xxrandom__supply
	--->	ran(int, int, int, int). % Seed1, Seed2, Lo, Len=Up-Lo+1

%---------------------------------------------------------------------------%

:- pred xxrandom__params(int, int).
:- mode xxrandom__params(uo, uo) is det.

xxrandom__params(2147483562, 2147483398).

%---------------------------------------------------------------------------%

xxrandom__init(Seed, Rs) :-
	xxrandom__params(Param1,_),
	xxrandom__init_with_limits(Seed,0,Param1-1,Rs).

%---------------------------------------------------------------------------%

xxrandom__init_with_limits(Seed, Lo, Up, ran(S1,S2,Lo,Len)) :-
	xxrandom__params(Param1,Param2),
	( Lo > Up -> error("Lo>Up not allowed\n") ; true),
	Len = Up - Lo + 1,
	( Len > Param1 -> error("Up - Lo too large, should be less than 2^30\n") ; true),

	( Seed < 0 -> SeedPos = -Seed ; SeedPos = Seed ),
	Q = SeedPos // Param1,
	S1 = 1 + (SeedPos rem Param1),
	S2 = 1 + (Q rem Param2),
	
    %------- only a little check --------%
	( 1 =< S1, S1=< Param1 ->
	    true
	;
	    error("xxrandom__init_with_limits: Seed 1 is bad")
	),
	( 1 =< S2, S2=< Param2 ->
	    true
	;
	    error("xxrandom__init_with_limits: Seed 2 is bad")
	).
	
%---------------------------------------------------------------------------%

xxrandom__random(X, ran(S1in,S2in,Lo,Len), ran(S1out,S2out,Lo,Len)) :-
	xxrandom__rands(X1, S1in,S2in, S1out,S2out),
	X = Lo + (X1 mod Len).

%---------------------------------------------------------------------------%

xxrandom__randmax(Up, Rs, Rs) :-
	Rs = ran(_,_,Lo,Len),
	Up = Lo + Len - 1.

%---------------------------------------------------------------------------%

xxrandom__randmin(Lo, Rs, Rs) :-
	Rs = ran(_,_,Lo,_).

%---------------------------------------------------------------------------%

xxrandom__randomlist(N, L, Rin, Rout) :-
	( N =< 0 ->
	    Rout = Rin,
	    L = []
	;
	    xxrandom__random(X,Rin,Rx),
	    xxrandom__randomlist(N-1,Lx,Rx,Rout),
	    L = [X|Lx]
	).

%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%

% rands is the heart of the random generator
% the range of Seed1 and Seed2 (be careful!):
% 1 <= Seed1 <= Param1
% 1 <= Seed2 <= Param2
:- pred xxrandom__rands(int, int, int, int, int).
:- mode xxrandom__rands(out, in, in, out, out) is det.

xxrandom__rands(Zout, S1in,S2in, S1out,S2out) :-
	xxrandom__params(Param1,Param2),
	Z = S1out - S2out,
	( Z < 1 ->
	    Zout = Z + Param1
	;
	    Zout = Z
	),

	K1  = S1in // 53668,
	S1 = 40014 * (S1in - K1 * 53668) - K1 * 12211,
	( S1 < 0 ->
	    S1out = S1 + Param1 + 1
	;
	    S1out = S1
	),

	K2 = div(S2in, 52774),
	S2 = 40692 * (S2in - K2 * 52774) - K2 * 3791,
	( S2 < 0 ->
	    S2out = S2 + Param2 + 1
	;
	    S2out = S2
	).

%---------------------------------------------------------------------------%


More information about the users mailing list