[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