diff --git a/src/prolog/lib/clpb.pl b/src/prolog/lib/clpb.pl index d66257ee..f373f83a 100644 --- a/src/prolog/lib/clpb.pl +++ b/src/prolog/lib/clpb.pl @@ -31,6 +31,7 @@ :- use_module(library(atts)). :- use_module(library(lists)). :- use_module(library(iso_ext)). +:- use_module(library(random)). :- use_module(library(pairs)). :- use_module(library(dcgs)). :- use_module(library(error), []). diff --git a/src/prolog/lib/iso_ext.pl b/src/prolog/lib/iso_ext.pl index 68708250..e206fd0b 100644 --- a/src/prolog/lib/iso_ext.pl +++ b/src/prolog/lib/iso_ext.pl @@ -4,10 +4,10 @@ %% ?- use_module(library(iso_ext)). :- module(iso_ext, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2, - call_with_inference_limit/3, forall/2, maybe/0, - partial_string/1, partial_string/3, - partial_string_tail/2, set_random/1, - setup_call_cleanup/3, variant/2]). + call_with_inference_limit/3, forall/2, + partial_string/1, partial_string/3, + partial_string_tail/2, setup_call_cleanup/3, + variant/2]). forall(Generate, Test) :- \+ (Generate, \+ Test). @@ -22,9 +22,9 @@ bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)). bb_b_put(Key, NewValue) :- ( '$bb_get_with_offset'(Key, OldValue, OldOffset) -> call_cleanup((store_global_var_with_offset(Key, NewValue) ; false), - reset_global_var_at_offset(Key, OldValue, OldOffset)) + reset_global_var_at_offset(Key, OldValue, OldOffset)) ; call_cleanup((store_global_var_with_offset(Key, NewValue) ; false), - reset_global_var_at_key(Key)) + reset_global_var_at_key(Key)) ). store_global_var_with_offset(Key, Value) :- '$store_global_var_with_offset'(Key, Value). @@ -144,27 +144,12 @@ call_with_inference_limit(_, _, R, Bb, B) :- variant(X, Y) :- '$variant'(X, Y). -% succeeds with probability 0.5. -maybe :- '$maybe'. - -set_random(Seed) :- - ( nonvar(Seed) -> - ( Seed = seed(S) -> - ( var(S) -> throw(error(instantiation_error, set_random/1)) - ; integer(S) -> '$set_seed'(S) - ; throw(error(type_error(integer(S), set_random/1))) - ) - ) - ; throw(error(instantiation_error, set_random/1)) - ). - - partial_string(String, L, L0) :- ( String == [] -> L = L0 ; catch(atom_chars(Atom, String), - error(E, _), - throw(error(E, partial_string/3))), + error(E, _), + throw(error(E, partial_string/3))), '$create_partial_string'(Atom, L, L0) ). diff --git a/src/prolog/lib/random.pl b/src/prolog/lib/random.pl new file mode 100644 index 00000000..7e59fc23 --- /dev/null +++ b/src/prolog/lib/random.pl @@ -0,0 +1,51 @@ +:- module(random, [maybe/0, random/1, random_integer/3, set_random/1]). + +% succeeds with probability 0.5. +maybe :- '$maybe'. + +% The higher the precision, the slower it gets. +random_number_precision(64). + +random(R) :- + var(R), + random_number_precision(N), + rnd(N, R). + +random_integer(Lower, Upper, R) :- + var(R), + ( (var(Lower) ; var(Upper)) -> + throw(error(instantiation_error, random_integer/3)) + ; \+ integer(Lower) -> + throw(error(domain_error(integer, Lower), random_integer/3)) + ; \+ integer(Upper) -> + throw(error(domain_error(integer, Upper), random_integer/3)) + ; Upper > Lower, + random(R0), + R is floor((Upper - Lower) * R0 + Lower) + ). + +rnd(N, R) :- + rnd_(N, 0, R). + +rnd_(0, R, R) :- !. +rnd_(N, R0, R) :- + maybe, + !, + N1 is N - 1, + rnd_(N1, R0, R). +rnd_(N, R0, R) :- + N1 is N - 1, + R1 is R0 + 1.0 / 2.0 ^ N, + rnd_(N1, R1, R). + +set_random(Seed) :- + ( nonvar(Seed) -> + ( Seed = seed(S) -> + ( var(S) -> throw(error(instantiation_error, set_random/1)) + ; integer(S) -> '$set_seed'(S) + ; throw(error(type_error(integer(S), set_random/1))) + ) + ) + ; throw(error(instantiation_error, set_random/1)) + ). +