Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!news.mathworks.com!news.kei.com!simtel!harbinger.cc.monash.edu.au!aggedor.rmit.EDU.AU!news.unimelb.EDU.AU!cs.mu.OZ.AU!mundil.cs.mu.OZ.AU!conway
From: conway@mundil.cs.mu.OZ.AU (Thomas Charles CONWAY)
Subject: Re: random numbers
Message-ID: <9521411.18644@mulga.cs.mu.OZ.AU>
Sender: news@cs.mu.OZ.AU (CS-Usenet)
Organization: Computer Science, University of Melbourne, Australia
References: <3uj8fs$ph@lyra.csx.cam.ac.uk>
Date: Wed, 2 Aug 1995 01:13:26 GMT
Lines: 110

etg10@cl.cam.ac.uk (Edmund Grimley-Evans) writes:

>I'm using a mixed C and Prolog library for generating random numbers.
>It works with Quintus, and with SICStus too with a bit of work, but
>I wonder if anyone knows where I can find a pure Prolog implementation
>as that would perhaps be more portable.

Appended to this post is the random.m file from the Mercury library.
Mercury is a pure language with Prolog compatible syntax, so if you
comment out the ':-' declaration lines, it should work under most
Prolog systems without any problems.

The generator itself is translated from Numerical Recipes in C
(Press et al), and is fairly straight forward, though as always
YMMV.

Thomas

%---------------------------------------------------------------------------%
% Copyright (C) 1995 University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% rand.m
%
% main author: conway
%
% Define a set of random number generator predicates. This implementation
% uses a threaded random-number supply. It could be made non-unique, but
% since each thread returns the same list of random numbers, in the interests
% of safety, it is declared with unique modes.
%
%---------------------------------------------------------------------------%

:- module random.

:- interface.

:- import_module int, list.

:- type random__supply.

:- pred random__init(int, random__supply).
:- mode random__init(in, uo) is det.

:- pred random__random(int, random__supply, random__supply).
:- mode random__random(out, di, uo) is det.

:- pred random__randmax(int, random__supply, random__supply).
:- mode random__randmax(out, di, uo) is det.

:- pred random__test(int, int, list(int), int).
:- mode random__test(in, in, out, out) is det.

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

:- implementation.
:- import_module require.

:- type random__supply		==	int.	% I(j)

:- pred random__params(int, int, int).	% a, c, m
:- mode random__params(out, out, out) is det.

random__params(2416, 374441, 1771875).

random__init(I0, RS) :-
	RS = I0.

random__random(I, RS0, RS) :-
	RS0 = I0,
	random__params(A, C, M),
	I1 is I0 * A,
	I2 is I1 + C,
	I is I2 mod M,
	RS = I.

random__randmax(M1, Rs0, Rs) :-
	Rs0 = I,
	random__params(_A, _C, M),
	M1 is M - 1,
	Rs = I.

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

random__test(Seed, N, Nums, Max) :-
	random__init(Seed, RS),
	random__randmax(Max, RS, RS1),
	random__test_2(N, Nums, RS1, _RS2).

:- pred random__test_2(int, list(int), random__supply, random__supply).
:- mode random__test_2(in, out, in, out) is det.

random__test_2(N, Is, RS0, RS) :-
	(
		N > 0
	->
		N1 is N - 1,
		random__random(I, RS0, RS1),
		random__test_2(N1, Is0, RS1, RS),
		Is = [I|Is0]
	;
		Is = [],
		RS = RS0
	).

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