YAP 7.1.0
prandom.yap
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: regexp.yap *
12* Last rev: 5/15/2000 *
13* mods: *
14* comments: pseudo random numbers in YAP (from code by Van Gelder) *
15* *
16*************************************************************************/
17
18/**
19 * @file prandom.yap
20 * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
21 * @date Tue Nov 17 23:43:18 2015
22 *
23 * @brief Van Gelder Random Number Generator
24 *
25 *
26*/
27
28:- module(prandom, [
29 ranstart/0,
32 ranunif/2]).
33
34
35%%
36%% @groupdef prandom Van Gelder Random Number Generator
37%% @ingroup YAPLibrary
38%% @{
39%
40%
41% The following code produces the same random numbers as my previous
42% ranpkg.pl, but is more accurately documented and slightly more
43% efficient.
44%
45% ranpkg.pl random number package Allen Van Gelder, Stanford
46%
47% rannum produces a random non-negative integer whose low bits are not
48% all that random, so it should be scaled to a smaller range in general.
49% The integer is in the range 0 .. 2^(w-1) - 1,
50% where w is the word size available for integers, e.g., 18 for DEC-10,
51% and 16 or 32 for VAX and most IBM.
52%
53% ranunif produces a uniformly distributed non-negative random integer over
54% a caller-specified range. If range is R, the result is in 0 .. R-1.
55%
56% ranstart must be called before the first use of rannum or ranunif,
57% and may be called later to redefine the seed.
58% ranstart/0 causes a built-in seed to be used.
59% ranstart(N), N an integer, varies this, but the same N always
60% produces the same sequence of numbers.
61%
62% According to my reading of Knuth, Vol. 2, this generator has period
63% 2^(w-1) and potency w/2, i.e., 8, 9, or 16 in practice. Knuth says
64% potency should be at least 5, so this looks more than adequate.
65% Its drawback is the lack of randomness of low-order bits.
66
67
68/** @pred rannum(- _I_)
69
70
71Produces a random non-negative integer _I_ whose low bits are not
72all that random, so it should be scaled to a smaller range in general.
73The integer _I_ is in the range 0 .. 2^(w-1) - 1. You can use:
74
75```
76rannum(X) :- yap_flag(max_integer,MI), rannum(R), X is R/MI.
77```
78to obtain a floating point number uniformly distributed between 0 and 1.
79
80
81*/
82/** @pred ranstart
83
84
85Initialize the random number generator using a built-in seed. The
86ranstart/0 built-in is always called by the system when loading
87the package.
88
89
90*/
91/** @pred ranstart(+ _Seed_)
92
93Initialize the random number generator with user-defined _Seed_. The
94same _Seed_ always produces the same sequence of numbers.
95
96
97*/
98/** @pred ranunif(+ _Range_,- _I_)
99
100
101ranunif/2 produces a uniformly distributed non-negative random
102integer _I_ over a caller-specified range _R_. If range is _R_,
103the result is in 0 .. _R_-1.
104
105
106
107
108 */
109:- initialization(ranstart).
110
111:- dynamic ranState/5.
112
113%
114% vsc: dangerous code, to change.
115%
116%
117wsize(32) :-
118 yap_flag(max_tagged_integer,I), I >> 32 =:= 0, yap_flag.
119wsize(64).
120
121wsize :- ranstart(8'365). %
122
123ranstart(N) :-
124 wsize(Wsize), % bits available for int.
125 MaxInt is \(1 << (Wsize - 1)), % all bits but sign bit are 1.
126 Incr is (8'154 << (Wsize - 9)) + 1, % per Knuth, v.2 p.78
127 Mult is 8'3655, % OK for 16-18 Wsize
128 Prev is Mult * (8 * N + 5) + Incr,
129 assert(ranState(Mult, Prev, Wsize, MaxInt, Incr) ).
130
131rannum(Raw) :-
132 retract(ranState(Mult, Prev, Wsize, MaxInt, Incr)),
133 Curr is Mult * Prev + Incr,
134 assert(ranState(Mult, Curr, Wsize, MaxInt, Incr)),
135 ( Curr > 0,
136 Raw is Curr
137 ;
138 Curr < 0,
139 Raw is Curr /\ MaxInt % force positive sign bit
140 ).
141
142ranunif(Range, Unif) :-
143 Range > 0,
144 retract( ranState(Mult, Prev, Wsize, MaxInt, Incr) ),
145 Curr is Mult * Prev + Incr,
146 assert(ranState(Mult, Curr, Wsize, MaxInt, Incr)),
147 ( Curr > 0,
148 Raw is Curr
149 ;
150 Curr < 0,
151 Raw is Curr /\ MaxInt % force positive sign bit
152 ),
153 Unif is (Raw * Range) >> (Wsize-1).
154
155
156/** @} */
157
ranstart(+ Seed)
ranunif(+ Range,- I)
yap_flag( ?Param, ?Value)
assert(+ C)
retract(+ C)
initialization(+ G)
@groupdef prandom Van Gelder Random Number Generator% % The following code produces the same random n...