[m-rev.] for review: delete the old random number generator
Julien Fischer
jfischer at opturion.com
Mon Mar 14 17:26:08 AEDT 2022
For review by anyone.
The main thing requiring review here is the NEWS file.
(I am aware that there are further bits of the extras that need
updating, I will do that separately.)
-------------------------------------------
Delete the old random number generator.
It has been deprecated since Mercury 20.01.
library/random.m:
Delete the old generator.
library/array.m:
Delete the predicate random_permutation/4.
NEWS:
Announce the above.
tests/hard_coded/string_hash.m:
Update this test to use the new RNG framework.
tests/hard_coded/Mmakefile:
tests/hard_coded/random_permutation.{m,exp}:
tests/hard_coded/random_simple.{m,exp}:
Delete these tests, they were specific to the old RNG.
extras/curs/samples/nibbles.m:
extras/solver_types/library/any_array.m:
Replace use of the old RNG.
Julien.
diff --git a/NEWS b/NEWS
index d93a15c..f394df9 100644
--- a/NEWS
+++ b/NEWS
@@ -12,9 +12,18 @@ Changes that may break compatibility
as obsolete, while other predicates that had been marked as obsolete
before the release of Mercury 22.01 have been removed.
+* The old random number generator in the `random` module has been removed.
+
Changes to the Mercury standard library
---------------------------------------
+### Changes to the `array` module
+
+* The following predicate has been removed:
+
+ - pred `random_permutation/4`
+ (replacement: `random.suffle_array/4` or `random.shuffle_array/5`)
+
### Changes to the `benchmarking` module
* The following predicates have been added:
@@ -176,6 +185,20 @@ This new module has these predicates:
- pred `have_make_temp_directory/0`
- pred `get_temp_directory/3`
+### Changes to the `random` module
+
+The old random number generator has been removed. It has been replaced by the
+new type class random number generation framework defined in this module.
+As a result, the following predicates have been removed:
+
+ - pred `init/2`
+ - pred `random/3`
+ - pred `random/5`
+ - pred `randmax/3`
+ - pred `randcount/3`
+ - pred `permutation/4`
+ (replacement: `random.shuffle_list/4` or `random.shuffle_list/5`)
+
### Changes to the `term_io` module
* The following predicates have been removed:
diff --git a/extras/curs/samples/nibbles.m b/extras/curs/samples/nibbles.m
index 5d7fc98..21a0bbc 100644
--- a/extras/curs/samples/nibbles.m
+++ b/extras/curs/samples/nibbles.m
@@ -27,16 +27,16 @@
:- import_module char.
:- import_module int.
:- import_module list.
+:- import_module maybe.
:- import_module random.
+:- import_module random.sfc32.
+:- import_module random.system_rng.
:- import_module require.
:- import_module std_util.
:- import_module string.
-:- import_module time.
%-----------------------------------------------------------------------------%
-:- type rs == random.supply.
-
:- type world
---> world(
cols :: int,
@@ -66,34 +66,50 @@
:- type apple
---> no_apple
; apple(
- x :: int,
- y :: int,
- repr :: int
+ x :: int,
+ y :: int,
+ repr :: int
).
%-----------------------------------------------------------------------------%
main(!IO) :-
- time.time(Now, !IO),
- time.localtime(Now, LocalNow, !IO),
- random.init(LocalNow ^ tm_min * 60 + LocalNow ^ tm_sec, RS),
- curs.start(!IO),
- curs.nodelay(yes, !IO),
- curs.rows_cols(Rows, Cols, !IO),
- curs.flushinp(!IO),
- play_game(Cols, Rows, !IO, RS, _RS1),
- curs.stop(!IO).
+ open_system_rng(MaybeSystemRNG, !IO),
+ (
+ MaybeSystemRNG = ok(SystemRNG),
+ system_rng.generate_uint32(SystemRNG, SeedA, !IO),
+ system_rng.generate_uint32(SystemRNG, SeedB, !IO),
+ system_rng.generate_uint32(SystemRNG, SeedC, !IO),
+ close_system_rng(SystemRNG, !IO),
+
+ sfc32.seed(SeedA, SeedB, SeedC, RNG0, RS),
+ make_io_urandom(RNG0, RS, RNG, !IO),
+
+ curs.start(!IO),
+ curs.nodelay(yes, !IO),
+ curs.rows_cols(Rows, Cols, !IO),
+ curs.flushinp(!IO),
+ play_game(RNG, Cols, Rows, !IO),
+ curs.stop(!IO)
+ ;
+ MaybeSystemRNG = error(ErrMsg),
+ io.stderr_stream(Stderr, !IO),
+ io.format(Stderr, "Error %s.\n", [s(ErrMsg)], !IO),
+ io.set_exit_status(1, !IO)
+ ).
-:- pred play_game(int::in, int::in, io::di, io::uo, rs::mdi, rs::muo) is det.
+:- pred play_game(io_urandom(P, S)::in, int::in, int::in, io::di, io::uo) is det
+ <= urandom(P, S).
-play_game(Cols, Rows, !IO, !RS) :-
+play_game(RNG, Cols, Rows, !IO) :-
Snake = snake(right, {Cols / 2, Rows / 2}, [], 10),
World = world(Cols, Rows, Snake, 1, no_apple, 0),
- game_loop(World, !IO, !RS).
+ game_loop(RNG, World, !IO).
-:- pred game_loop(world::in, io::di, io::uo, rs::mdi, rs::muo) is det.
+:- pred game_loop(io_urandom(P, S)::in, world::in, io::di, io::uo) is det
+ <= urandom(P, S).
-game_loop(!.World, !IO, !RS) :-
+game_loop(RNG, !.World, !IO) :-
handle_input(!World, !IO, Quit),
(
Quit = no,
@@ -104,8 +120,8 @@ game_loop(!.World, !IO, !RS) :-
show_game_over(!IO)
else
sleep.usleep(50000, !IO),
- maybe_replenish_apple(!World, !RS),
- game_loop(!.World, !IO, !RS)
+ maybe_replenish_apple(RNG, !World, !IO),
+ game_loop(RNG, !.World, !IO)
)
;
Quit = yes
@@ -237,11 +253,12 @@ snake_is_dead(World) :-
%-----------------------------------------------------------------------------%
-:- pred maybe_replenish_apple(world::in, world::out, rs::mdi, rs::muo) is det.
+:- pred maybe_replenish_apple(io_urandom(P, S)::in, world::in, world::out,
+ io::di, io::uo) is det <= urandom(P, S).
-maybe_replenish_apple(World0, World, !RS) :-
+maybe_replenish_apple(RNG, World0, World, !IO) :-
( if World0 ^ apple = no_apple then
- new_apple(World0, !RS, NewApple),
+ new_apple(RNG, World0, NewApple, !IO),
NextAppleNum = inc_apple_num(World0 ^ next_apple_num),
World = ((World0
^ apple := NewApple)
@@ -250,13 +267,14 @@ maybe_replenish_apple(World0, World, !RS) :-
World = World0
).
-:- pred new_apple(world::in, rs::mdi, rs::muo, apple::out) is det.
+:- pred new_apple(io_urandom(P, S)::in, world::in, apple::out, io::di, io::uo)
+ is det <= urandom(P, S).
-new_apple(World, !RS, Apple) :-
- random.random(1, World ^ cols-2, X, !RS),
- random.random(1, World ^ rows-2, Y, !RS),
+new_apple(RNG, World, Apple, !IO) :-
+ uniform_int_in_range(RNG, 1, World ^ cols - 2, X, !IO),
+ uniform_int_in_range(RNG, 1, World ^ rows - 2, Y, !IO),
( if touches_snake(X, Y, World) then
- new_apple(World, !RS, Apple)
+ new_apple(RNG, World, Apple, !IO)
else
Apple = apple(X, Y, apple_char(World ^ next_apple_num))
).
diff --git a/extras/solver_types/library/any_array.m b/extras/solver_types/library/any_array.m
index ba0c11e..211bc56 100644
--- a/extras/solver_types/library/any_array.m
+++ b/extras/solver_types/library/any_array.m
@@ -283,14 +283,24 @@
:- mode any_array.foldr(func(ia, ia) = oa is det, any_array_ui, ia) = oa
is det.
- % any_array.random_permutation(A0, A, RS0, RS) permutes the elements in
- % A0 given random seed RS0 and returns the permuted any_array in A
- % and the next random seed in RS.
+ % any_array.random_permutation(A0, A, R0, R) permutes the elements in A0
+ % given random number generator R0 and returns the permuted any_array in A
+ % and the next random generator in R.
%
:- pred any_array.random_permutation(any_array(T), any_array(T),
- random.supply, random.supply).
+ R, R) <= random(R).
:- mode any_array.random_permutation(any_array_di, any_array_uo,
- mdi, muo) is det.
+ in, out) is det.
+
+ % any_array.random_permutation(RNG, A0, A, RS0, RS) permutes the elements
+ % in A0 given unique random number generator RNG and initial random state
+ % RS0. It returns the permuted any_array in A and the updated random
+ % number generator state in RS.
+ %
+:- pred any_array.random_permutation(P, any_array(T), any_array(T),
+ S, S) <= urandom(P, S).
+:- mode any_array.random_permutation(in, any_array_di, any_array_uo,
+ di, uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -797,25 +807,44 @@ Array ^ elem(Index) =
%------------------------------------------------------------------------------%
-any_array.random_permutation(A0, A, RS0, RS) :-
+random_permutation(A0, A, !R) :-
Lo = any_array.min(A0),
Hi = any_array.max(A0),
Sz = any_array.size(A0),
- permutation_2(Lo, Lo, Hi, Sz, A0, A, RS0, RS).
+ permutation_2(Lo, Lo, Hi, Sz, A0, A, !R).
+
+:- pred permutation_2(int::in, int::in, int::in, int::in,
+ any_array(T)::any_array_di, any_array(T)::any_array_uo, R::in, R::out) is det
+ <= random(R).
+
+permutation_2(I, Lo, Hi, Sz, !A, !R) :-
+ ( if I > Hi then
+ true
+ else
+ uniform_int_in_range(Lo, Sz, J, !R),
+ !:A = swap_elems(!.A, I, J),
+ permutation_2(I + 1, Lo, Hi, Sz, !A, !R)
+ ).
-:- pred permutation_2(int, int, int, int, any_array(T), any_array(T),
- random.supply, random.supply).
-:- mode permutation_2(in, in, in, in, any_array_di, any_array_uo, mdi, muo) is det.
+%------------------------------------------------------------------------------%
-permutation_2(I, Lo, Hi, Sz, A0, A, RS0, RS) :-
- ( I > Hi ->
- A = A0,
- RS = RS0
- ;
- random.random(R, RS0, RS1),
- J = Lo + (R `rem` Sz),
- A1 = swap_elems(A0, I, J),
- permutation_2(I + 1, Lo, Hi, Sz, A1, A, RS1, RS)
+any_array.random_permutation(P, A0, A, !S) :-
+ Lo = any_array.min(A0),
+ Hi = any_array.max(A0),
+ Sz = any_array.size(A0),
+ permutation_2(P, Lo, Lo, Hi, Sz, A0, A, !S).
+
+:- pred permutation_2(P::in, int::in, int::in, int::in, int::in,
+ any_array(T)::any_array_di, any_array(T)::any_array_uo, S::di, S::uo)
+ is det <= urandom(P, S).
+
+permutation_2(P, I, Lo, Hi, Sz, !A, !S) :-
+ ( if I > Hi then
+ true
+ else
+ uniform_int_in_range(P, Lo, Sz, J, !S),
+ !:A = swap_elems(!.A, I, J),
+ permutation_2(P, I + 1, Lo, Hi, Sz, !A, !S)
).
%------------------------------------------------------------------------------%
diff --git a/library/array.m b/library/array.m
index 8a200c0..6df93c0 100644
--- a/library/array.m
+++ b/library/array.m
@@ -45,7 +45,6 @@
:- import_module list.
:- import_module pretty_printer.
-:- import_module random.
:- type array(T).
@@ -826,13 +825,6 @@
%
:- func append(array(T)::in, array(T)::in) = (array(T)::array_uo) is det.
- % random_permutation(A0, A, RS0, RS) permutes the elements in
- % A0 given random seed RS0 and returns the permuted array in A
- % and the next random seed in RS.
- %
-:- pred random_permutation(array(T)::array_di, array(T)::array_uo,
- random.supply::mdi, random.supply::muo) is det.
-
% Convert an array to a pretty_printer.doc for formatting.
%
:- func array_to_doc(array(T)) = pretty_printer.doc.
@@ -2581,37 +2573,6 @@ append(A, B) = C :-
%---------------------------------------------------------------------------%
-random_permutation(A0, A, RS0, RS) :-
- Lo = array.min(A0),
- Hi = array.max(A0),
- Sz = array.size(A0),
- permutation_2(Lo, Lo, Hi, Sz, A0, A, RS0, RS).
-
-:- pred permutation_2(int::in, int::in, int::in, int::in,
- array(T)::array_di, array(T)::array_uo,
- random.supply::mdi, random.supply::muo) is det.
-
-permutation_2(I, Lo, Hi, Sz, !A, !RS) :-
- ( if I > Hi then
- true
- else
- random.random(R, !RS),
- J = Lo + (R `rem` Sz),
- swap_elems(I, J, !A),
- permutation_2(I + 1, Lo, Hi, Sz, !A, !RS)
- ).
-
-:- pred swap_elems(int::in, int::in, array(T)::array_di, array(T)::array_uo)
- is det.
-
-swap_elems(I, J, !A) :-
- array.lookup(!.A, I, XI),
- array.lookup(!.A, J, XJ),
- array.unsafe_set(I, XJ, !A),
- array.unsafe_set(J, XI, !A).
-
-%---------------------------------------------------------------------------%
-
foldl(Fn, A, X) =
do_foldl_func(Fn, A, X, array.min(A), array.max(A)).
diff --git a/library/random.m b/library/random.m
index a0bad45..59ae035 100644
--- a/library/random.m
+++ b/library/random.m
@@ -355,116 +355,6 @@
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
-%
-% Interface to the older random number generator. This is now deprecated.
-%
-% 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.
-%
-%---------------------------------------------------------------------------%
-
- % The type `supply' represents a supply of random numbers.
- %
-:- type supply.
-
- % init(Seed, RS).
- %
- % Creates a supply of random numbers RS using the specified Seed.
- %
- % This predicate has been declared obsolete because all of the
- % interface from here on is deprecated. All code using this part
- % of the interface will need to be updated.
- %
-:- pragma obsolete(pred(init/2)).
-:- pred init(int::in, supply::uo) is det.
-
- % random(Num, !RS).
- %
- % Extracts a number Num in the range 0 .. RandMax from the random number
- % supply !RS.
- %
-:- pred random(int, supply, supply).
-:- mode random(out, in, out) is det.
-:- mode random(out, mdi, muo) is det.
-
- % random(Low, Range, Num, !RS).
- %
- % Extracts a number Num in the range Low .. (Low + Range - 1) from the
- % random number supply !RS. For best results, the value of Range should be
- % no greater than about 100.
- %
-:- pred random(int, int, int, supply, supply).
-:- mode random(in, in, out, in, out) is det.
-:- mode random(in, in, out, mdi, muo) is det.
-
- % randmax(RandMax, !RS).
- %
- % Binds RandMax to the maximum random number that can be returned from the
- % random number supply !RS, the state of the supply is unchanged.
- %
-:- pred randmax(int, supply, supply).
-:- mode randmax(out, in, out) is det.
-:- mode randmax(out, mdi, muo) is det.
-
- % randcount(RandCount, !RS).
- %
- % Binds RandCount to the number of distinct random numbers that can be
- % returned from the random number supply !RS. The state of the supply is
- % unchanged. This will be one more than the number returned by randmax/3.
- %
-:- pred randcount(int, supply, supply).
-:- mode randcount(out, in, out) is det.
-:- mode randcount(out, mdi, muo) is det.
-
- % permutation(List0, List, !RS).
- %
- % Binds List to a random permutation of List0.
- %
-:- pred permutation(list(T), list(T), supply, supply).
-:- mode permutation(in, out, in, out) is det.
-:- mode permutation(in, out, mdi, muo) is det.
-
-%---------------------------------------------------------------------------%
-%---------------------------------------------------------------------------%
-
-:- implementation.
- % Everything after the first `:- implementation' does not appear
- % in the Mercury Library Reference Manual.
-:- interface.
-
-%---------------------------------------------------------------------------%
:- implementation.
@@ -854,108 +744,5 @@ make_io_urandom(P, S, Pio, !IO) :-
).
%---------------------------------------------------------------------------%
-%---------------------------------------------------------------------------%
-
-:- type supply
- ---> rs(int). % I(j)
-
-:- pred params(int::out, int::out, int::out) is det. % a, c, m
-
-params(9301, 49297, 233280).
-
-init(I0, rs(RS)) :-
- copy(I0, RS).
-
-random(I, rs(RS0), rs(RS)) :-
- RS0 = I0,
- random.params(A, C, M),
- I = ((I0 * A) + C) mod M,
- copy(I, RS).
-
- % We could make this more robust by checking whether the range is
- % less than a certain threshold, and using a more sophisticated
- % algorithm if the threshold is exceeded. But that would defeat
- % the purpose of having a "quick and dirty" random number generator,
- % so we don't do that.
-random(Low, Range, Num, !RandomSupply) :-
- random(R, !RandomSupply),
- randcount(M, !RandomSupply),
- % With our current set of parameters and a reasonable choice of Range,
- % the following should never overflow.
- Num = Low + (Range * R) // M.
-
-randmax(M1, RS, RS) :-
- params(_A, _C, M),
- M1 = M - 1.
-
-randcount(M, RS, RS) :-
- params(_A, _C, M).
-
-%---------------------------------------------------------------------------%
-
- % The random permutation is implemented via a "sampling without
- % replacement" method. In init_record, we build up an array in which
- % every integer in the range 0 .. Length - 1 is mapped to the
- % corresponding element in the list. The sampling stage
- % iterates from Length - 1 down to 0. The invariant being
- % maintained is that at iteration I, the elements in the image of
- % the part of the map indexed by 0 .. I-1 are the elements that have
- % not been selected yet. At each iteration, perform_sampling generates
- % a random number Index in the range 0 .. I-1, adds the element that
- % Index is mapped to, Next, to the permutation, and then ensures that
- % Next is not generated again by swapping it with the image of I-1.
-
-permutation(List0, List, !RS) :-
- Samples = array(List0),
- Len = array.size(Samples),
- perform_sampling(Len, Samples, [], List, !RS).
-
-:- pred perform_sampling(int, array(T), list(T), list(T),
- random.supply, random.supply).
-:- mode perform_sampling(in, array_di, in, out, in, out) is det.
-:- mode perform_sampling(in, array_di, in, out, mdi, muo) is det.
-
-perform_sampling(I, !.Record, !Order, !RS) :-
- ( if I =< 0 then
- true
- else
- I1 = I - 1,
- random.random(0, I, Index, !RS),
- array.lookup(!.Record, Index, Next),
- array.lookup(!.Record, I1, MaxImage),
- !:Order = [Next | !.Order],
- array.set(Index, MaxImage, !Record),
- array.set(I1, Next, !Record),
- perform_sampling(I1, !.Record, !Order, !RS)
- ).
-
-%---------------------------------------------------------------------------%
-
- % The following predicate was just for test purposes.
- % It should not be used by user programs.
- %
-:- pred test(int::in, int::in, list(int)::out, int::out) is det.
-:- pragma consider_used(pred(test/4)).
-:- pragma obsolete(pred(test/4)).
-
-test(Seed, N, Nums, Max) :-
- init(Seed, RS),
- randmax(Max, RS, RS1),
- test_2(N, Nums, RS1, _RS2).
-
-:- pred test_2(int, list(int), supply, supply).
-:- mode test_2(in, out, in, out) is det.
-
-test_2(N, Is, !RS) :-
- ( if N > 0 then
- N1 = N - 1,
- random(I, !RS),
- test_2(N1, Is0, !RS),
- Is = [I | Is0]
- else
- Is = []
- ).
-
-%---------------------------------------------------------------------------%
:- end_module random.
%---------------------------------------------------------------------------%
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index d197ec0..e2dfe6e 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -326,8 +326,6 @@ ORDINARY_PROGS = \
quantifier \
quantifier2 \
quoting_bug_test \
- random_permutation \
- random_simple \
rational_test \
read_binary_int16 \
read_binary_int32 \
diff --git a/tests/hard_coded/random_permutation.exp b/tests/hard_coded/random_permutation.exp
deleted file mode 100644
index f09768a..0000000
--- a/tests/hard_coded/random_permutation.exp
+++ /dev/null
@@ -1,9 +0,0 @@
-Test passed.
-Test passed.
-Test passed.
-Test passed.
-Test passed.
-Test passed.
-Test passed.
-Test passed.
-Test passed.
diff --git a/tests/hard_coded/random_permutation.m b/tests/hard_coded/random_permutation.m
deleted file mode 100644
index 804530e..0000000
--- a/tests/hard_coded/random_permutation.m
+++ /dev/null
@@ -1,47 +0,0 @@
-%---------------------------------------------------------------------------%
-% vim: ts=4 sw=4 et ft=mercury
-%---------------------------------------------------------------------------%
-
-:- module random_permutation.
-:- interface.
-:- import_module io.
-
-:- pred main(io::di, io::uo) is det.
-
-:- implementation.
-
-:- import_module int.
-:- import_module list.
-:- import_module random.
-
-main(!IO) :-
- List = gen_sorted_list(1, 100),
- random.init(1, RS),
- do_tests(List, 10, RS, !IO).
-
-:- pred do_tests(list(int)::in, int::in, random.supply::mdi,
- io::di, io::uo) is det.
-
-do_tests(List, Count, RS0, !IO) :-
- ( if Count > 1 then
- random.permutation(List, Perm, RS0, RS1),
- list.sort_and_remove_dups(Perm, SortedList),
- ( if SortedList = List then
- io.write_string("Test passed.\n", !IO)
- else
- io.write_string("Test failed!\n", !IO)
- ),
- do_tests(List, Count - 1, RS1, !IO)
- else
- true
- ).
-
-:- func gen_sorted_list(int, int) = list(int).
-
-gen_sorted_list(M, N) =
- ( if M > N then
- []
- else
- [M | gen_sorted_list(M + 1, N)]
- ).
-
diff --git a/tests/hard_coded/random_simple.exp b/tests/hard_coded/random_simple.exp
deleted file mode 100644
index 669a531..0000000
--- a/tests/hard_coded/random_simple.exp
+++ /dev/null
@@ -1,2 +0,0 @@
-Test passed.
-Test passed.
diff --git a/tests/hard_coded/random_simple.m b/tests/hard_coded/random_simple.m
deleted file mode 100644
index 04d5f8a..0000000
--- a/tests/hard_coded/random_simple.m
+++ /dev/null
@@ -1,36 +0,0 @@
-%---------------------------------------------------------------------------%
-% vim: ts=4 sw=4 et ft=mercury
-%---------------------------------------------------------------------------%
-
-:- module random_simple.
-:- interface.
-:- import_module io.
-
-:- pred main(io::di, io::uo) is det.
-
-:- implementation.
-:- import_module int.
-:- import_module random.
-
-main(!IO) :-
- Seed = 3,
- random.init(Seed, RS0),
- test(1, 20, RS0, RS1, !IO),
- test(-1, 20, RS1, _, !IO).
-
-:- pred test(int::in, int::in, random.supply::mdi, random.supply::muo,
- io::di, io::uo) is det.
-
-test(Range, Count, RS0, RS, !IO) :-
- ( if Count > 0 then
- random.random(0, Range, N, RS0, RS1),
- ( if N = 0 then
- test(Range, Count - 1, RS1, RS, !IO)
- else
- io.write_string("Test failed.\n", !IO),
- RS = RS1
- )
- else
- io.write_string("Test passed.\n", !IO),
- RS = RS0
- ).
diff --git a/tests/hard_coded/string_hash.m b/tests/hard_coded/string_hash.m
index 30200b9..82b628b 100644
--- a/tests/hard_coded/string_hash.m
+++ b/tests/hard_coded/string_hash.m
@@ -26,13 +26,14 @@
:- import_module int.
:- import_module list.
:- import_module random.
+:- import_module random.sfc32.
:- import_module require.
:- import_module string.
main(!IO) :-
MaxLength = 1024,
- random.init(1, RS0),
- test(MaxLength, yes, Succeeded, RS0, _, !IO),
+ sfc32.init(RNG, RS0),
+ test(RNG, MaxLength, yes, Succeeded, RS0, _, !IO),
(
Succeeded = yes,
io.write_string("all tests succeeded\n", !IO)
@@ -41,14 +42,14 @@ main(!IO) :-
io.write_string("some tests failed\n", !IO)
).
-:- pred test(int::in, bool::in, bool::out,
- random.supply::mdi, random.supply::muo, io::di, io::uo) is det.
+:- pred test(RNG::in, int::in, bool::in, bool::out,
+ State::di, State::uo, io::di, io::uo) is det <= urandom(RNG, State).
-test(Length, !Succeeded, !RS, !IO) :-
+test(RNG, Length, !Succeeded, !RS, !IO) :-
( if Length < 0 then
true
else
- make_char_list(Length, [], List, !RS),
+ make_char_list(RNG, Length, [], List, !RS),
string.from_char_list(List, String),
LibHash1 = string.hash(String),
@@ -75,30 +76,30 @@ test(Length, !Succeeded, !RS, !IO) :-
RuntimeHash6 = runtime_string_hash6(String),
test_hash("hash6", LibHash6, RuntimeHash6, String, !Succeeded, !IO),
- test(Length - 1, !Succeeded, !RS, !IO)
+ test(RNG, Length - 1, !Succeeded, !RS, !IO)
).
-:- pred make_char_list(int::in, list(char)::in, list(char)::out,
- random.supply::mdi, random.supply::muo) is det.
+:- pred make_char_list(RNG::in, int::in, list(char)::in, list(char)::out,
+ State::di, State::uo) is det <= urandom(RNG, State).
-make_char_list(Length, !List, !RS) :-
+make_char_list(RNG, Length, !List, !RS) :-
( if Length = 0 then
true
else
- rand_char(Char, !RS),
+ rand_char(RNG, Char, !RS),
!:List = [Char | !.List],
- make_char_list(Length - 1, !List, !RS)
+ make_char_list(RNG, Length - 1, !List, !RS)
).
-:- pred rand_char(char::out, random.supply::mdi, random.supply::muo) is det.
+:- pred rand_char(RNG::in, char::out, State::di, State::uo) is det
+ <= urandom(RNG, State).
-rand_char(Char, !RS) :-
- random.random(Rand, !RS),
+rand_char(RNG, Char, !RS) :-
% U+0001..U+10ffff (avoid null character).
- Int = 1 + (Rand `mod` char.max_char_value),
+ uniform_int_in_range(RNG, 1, char.max_char_value, Int, !RS),
char.det_from_int(Int, Char0),
( if is_surrogate(Char0) then
- rand_char(Char, !RS)
+ rand_char(RNG, Char, !RS)
else
Char = Char0
).
More information about the reviews
mailing list