This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/Logtalk/library/random.lgt
pmoura e75e406f84 Logtalk 2.29.2 files.
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1773 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
2007-01-10 12:46:10 +00:00

148 lines
3.6 KiB
Plaintext

:- object(random,
implements(randomp)).
:- info([
version is 1.2,
author is 'Paulo Moura',
date is 2007/1/3,
comment is 'Random number generator predicates.']).
:- synchronized. % make all object predicates multi-threading aware
:- initialization(::reset_seed).
:- private(seed_/3).
:- dynamic(seed_/3).
:- mode(seed_(-integer, -integer, -integer), one).
:- info(seed_/3, [
comment is 'Stores the current random generator seed values.',
argnames is ['S0', 'S1', 'S2']]).
random(Random) :-
::retract(seed_(A0, A1, A2)),
random(A0, A1, A2, B0, B1, B2, Random),
::asserta(seed_(B0, B1, B2)).
random(A0, A1, A2, B0, B1, B2, Random) :-
B0 is (A0*171) mod 30269,
B1 is (A1*172) mod 30307,
B2 is (A2*170) mod 30323,
Float is A0/30269 + A1/30307 + A2/30323,
Random is Float - truncate(Float).
random(Lower, Upper, Random) :-
integer(Lower),
integer(Upper),
Upper >= Lower,
!,
random(Float),
Random is truncate((Float * (Upper-Lower)+Lower)).
random(Lower, Upper, Random) :-
float(Lower),
float(Upper),
Upper >= Lower,
random(Float),
Random is Float * (Upper-Lower)+Lower.
randseq(Length, Lower, Upper, Sequence) :-
integer(Length),
Length >= 0,
integer(Lower),
integer(Upper),
Upper >= Lower,
!,
::retract(seed_(A0, A1, A2)),
randseq(Length, Lower, Upper, (A0, A1, A2), (B0, B1, B2), [], List),
::asserta(seed_(B0, B1, B2)),
map_truncate(List, Sequence).
randseq(Length, Lower, Upper, Sequence) :-
integer(Length),
Length >= 0,
float(Lower),
float(Upper),
Upper >= Lower,
::retract(seed_(A0, A1, A2)),
randseq(Length, Lower, Upper, (A0, A1, A2), (B0, B1, B2), [], Sequence),
::asserta(seed_(B0, B1, B2)).
randseq(0, _, _, Seed, Seed, List, List) :-
!.
randseq(N, Lower, Upper, (A0, A1, A2), (C0, C1, C2), Acc, List) :-
N2 is N - 1,
random(A0, A1, A2, B0, B1, B2, R),
Random is R * (Upper-Lower)+Lower,
randseq(N2, Lower, Upper, (B0, B1, B2), (C0, C1, C2), [Random| Acc], List).
map_truncate([], []).
map_truncate([Float| Floats], [Integer| Integers]) :-
Integer is truncate(Float),
map_truncate(Floats, Integers).
randset(Length, Lower, Upper, Set) :-
integer(Length),
Length >= 0,
integer(Lower),
integer(Upper),
Upper >= Lower,
Length =< Upper - Lower,
!,
::retract(seed_(A0, A1, A2)),
randset(Length, Lower, Upper, (A0, A1, A2), (B0, B1, B2), [], Set),
::asserta(seed_(B0, B1, B2)).
randset(Length, Lower, Upper, Set) :-
integer(Length),
Length >= 0,
float(Lower),
float(Upper),
Upper >= Lower,
::retract(seed_(A0, A1, A2)),
randset(Length, Lower, Upper, (A0, A1, A2), (B0, B1, B2), [], Set),
::asserta(seed_(B0, B1, B2)).
randset(0, _, _, Seed, Seed, List, List) :-
!.
randset(N, Lower, Upper, (A0, A1, A2), (C0, C1, C2), Acc, List) :-
N2 is N - 1,
random(A0, A1, A2, B0, B1, B2, Float),
Float2 is Float * (Upper-Lower)+Lower,
(integer(Lower) ->
Random is truncate(Float2)
;
Random is Float2),
(not_member(Acc, Random) ->
add_ordered(Acc, Random, Acc2),
randset(N2, Lower, Upper, (B0, B1, B2), (C0, C1, C2), Acc2, List)
;
randset(N, Lower, Upper, (B0, B1, B2), (C0, C1, C2), Acc, List)).
not_member([], _).
not_member([H| T], R) :-
H =\= R,
not_member(T, R).
add_ordered([], R, [R]).
add_ordered([H| T], R, L) :-
( H > R ->
L = [R, H| T]
; L = [H| T2],
add_ordered(T, R, T2)
).
reset_seed :-
::retractall(seed_(_, _, _)),
::asserta(seed_(3172, 9814, 20125)).
set_seed(Seed) :-
integer(Seed),
Seed > 0,
::retractall(seed_(_, _, _)),
S0 is Seed mod 30269,
S1 is Seed mod 30307,
S2 is Seed mod 30323,
::asserta(seed_(S0, S1, S2)).
:- end_object.