%--------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et wm=0 tw=0 %--------------------------------------------------% % Copyright (C) 1994-1998,2001-2006, 2011 The 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. %--------------------------------------------------% % % File: random.m % Main author: conway % Stability: low % % Define a set of random number generator predicates. This implementation % uses a threaded random-number supply. The supply can be used in a % non-unique way, which means that each thread returns the same list of % random numbers. However, this may not be desired so in the interests % of safety it is also declared with (backtrackable) unique modes. % % The coefficients used in the implementation were taken from Numerical % Recipes in C (Press et al), and are originally due to Knuth. These % coefficients are described as producing a "Quick and Dirty" random number % generator, which generates the numbers very quickly but not necessarily % with a high degree of quality. As with all random number generators, % the user is advised to consider carefully whether this generator meets % their requirements in terms of "randomness". For applications which have % special needs (e.g. cryptographic key generation), a generator such as % this is unlikely to be suitable. % % Note that random number generators of this type have several known % pitfalls which the user may need to avoid: % % 1) The high bits tend to be more random than the low bits. If % you wish to generate a random integer within a given range, you % should something like 'div' to reduce the random numbers to the % required range rather than something like 'mod' (or just use % random.random/5). % % 2) Similarly, you should not try to break a random number up into % components. Instead, you should generate each number with a % separate call to this module. % % 3) There can be sequential correlation between successive calls, % so you shouldn't try to generate tuples of random numbers, for % example, by generating each component of the tuple in sequential % order. If you do, it is likely that the resulting sequence will % not cover the full range of possible tuples. % %--------------------------------------------------% %--------------------------------------------------% :- module random. :- interface. :- import_module list. %--------------------------------------------------% % The type `random.supply' represents a supply of random numbers. % :- type random.supply. % random.init(Seed, RS): creates a supply of random numbers RS % using the specified Seed. % :- pred random.init(int::in, random.supply::uo) is det. % random.random(Num, RS0, RS): extracts a number Num in the % range 0 .. RandMax from the random number supply RS0, and % binds RS to the new state of the random number supply. % :- pred random.random(int, random.supply, random.supply). :- mode random.random(out, mdi, muo) is det. :- mode random.random(out, in, out) is det. % random.random(Low, Range, Num, RS0, RS): extracts a number Num % in the range Low .. (Low + Range - 1) from the random number % supply RS0, and binds RS to the new state of the random number % supply. For best results, the value of Range should be no greater % than about 100. % :- pred random.random(int, int, int, random.supply, random.supply). :- mode random.random(in, in, out, mdi, muo) is det. :- mode random.random(in, in, out, in, out) is det. % random.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 random.randmax(int, random.supply, random.supply). :- mode random.randmax(out, mdi, muo) is det. :- mode random.randmax(out, in, out) is det. % random.randcount(RandCount, RS0, RS): binds RandCount to the % number of distinct random numbers that can be returned from the % random number supply RS0, and returns RS = RS0. This will be one % more than the number returned by randmax/3. % :- pred random.randcount(int, random.supply, random.supply). :- mode random.randcount(out, mdi, muo) is det. :- mode random.randcount(out, in, out) is det. % random.permutation(List0, List, RS0, RS): % binds List to a random permutation of List0, % and binds RS to the new state of the random number supply. % :- pred random.permutation(list(T), list(T), random.supply, random.supply). :- mode random.permutation(in, out, mdi, muo) is det. :- mode random.permutation(in, out, in, out) is det. %--------------------------------------------------% %--------------------------------------------------%