Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8097 | maxcodehac | 1 | (* ************************************************************ |
2 | Дополнительные алгоритмы генераторов какбыслучайных чисел. |
||
3 | Вадим Исаев, 2020 |
||
4 | |||
5 | Additional generators of pseudorandom numbers. |
||
6 | Vadim Isaev, 2020 |
||
7 | ************************************************************ *) |
||
8 | |||
9 | MODULE RandExt; |
||
10 | |||
11 | IMPORT HOST, MathRound, MathBits; |
||
12 | |||
13 | CONST |
||
14 | (* Для алгоритма Мерсена-Твистера *) |
||
15 | N = 624; |
||
16 | M = 397; |
||
17 | MATRIX_A = 9908B0DFH; (* constant vector a *) |
||
18 | UPPER_MASK = 80000000H; (* most significant w-r bits *) |
||
19 | LOWER_MASK = 7FFFFFFFH; (* least significant r bits *) |
||
20 | INT_MAX = 4294967295; |
||
21 | |||
22 | |||
23 | TYPE |
||
24 | (* структура служебных данных, для алгоритма mrg32k3a *) |
||
25 | random_t = RECORD |
||
26 | mrg32k3a_seed : REAL; |
||
27 | mrg32k3a_x : ARRAY 3 OF REAL; |
||
28 | mrg32k3a_y : ARRAY 3 OF REAL |
||
29 | END; |
||
30 | |||
31 | (* Для алгоритма Мерсена-Твистера *) |
||
32 | MTKeyArray = ARRAY N OF INTEGER; |
||
33 | |||
34 | VAR |
||
35 | (* Для алгоритма mrg32k3a *) |
||
36 | prndl: random_t; |
||
37 | (* Для алгоритма Мерсена-Твистера *) |
||
38 | mt : MTKeyArray; (* the array for the state vector *) |
||
39 | mti : INTEGER; (* mti == N+1 means mt[N] is not initialized *) |
||
40 | |||
41 | (* --------------------------------------------------------------------------- |
||
42 | Генератор какбыслучайных чисел в диапазоне [a,b]. |
||
43 | Алгоритм 133б из книги "Агеев и др. - Бибилотека алгоритмов 101б-150б", |
||
44 | стр. 53. |
||
45 | Переделка из Algol на Oberon и доработка, Вадим Исаев, 2020 |
||
46 | |||
47 | Generator pseudorandom numbers, algorithm 133b from |
||
48 | Comm ACM 5,10 (Oct 1962) 553. |
||
49 | Convert from Algol to Oberon Vadim Isaev, 2020. |
||
50 | |||
51 | Входные параметры: |
||
52 | a - начальное вычисляемое значение, тип REAL; |
||
53 | b - конечное вычисляемое значение, тип REAL; |
||
54 | seed - начальное значение для генерации случайного числа. |
||
55 | Должно быть в диапазоне от 10 000 000 000 до 34 359 738 368 (2^35), |
||
56 | нечётное. |
||
57 | --------------------------------------------------------------------------- *) |
||
58 | PROCEDURE alg133b* (a, b: REAL; VAR seed: INTEGER): REAL; |
||
59 | CONST |
||
60 | m35 = 34359738368; |
||
61 | m36 = 68719476736; |
||
62 | m37 = 137438953472; |
||
63 | |||
64 | VAR |
||
65 | x: INTEGER; |
||
66 | BEGIN |
||
67 | IF seed # 0 THEN |
||
68 | IF (seed MOD 2 = 0) THEN |
||
69 | seed := seed + 1 |
||
70 | END; |
||
71 | x:=seed; |
||
72 | seed:=0; |
||
73 | END; |
||
74 | |||
75 | x:=5*x; |
||
76 | IF x>=m37 THEN |
||
77 | x:=x-m37 |
||
78 | END; |
||
79 | IF x>=m36 THEN |
||
80 | x:=x-m36 |
||
81 | END; |
||
82 | IF x>=m35 THEN |
||
83 | x:=x-m35 |
||
84 | END; |
||
85 | |||
86 | RETURN FLT(x) / FLT(m35) * (b - a) + a |
||
87 | END alg133b; |
||
88 | |||
89 | (* ---------------------------------------------------------- |
||
90 | Генератор почти равномерно распределённых |
||
91 | какбыслучайных чисел mrg32k3a |
||
92 | (Combined Multiple Recursive Generator) от 0 до 1. |
||
93 | Период повторения последовательности = 2^127 |
||
94 | |||
95 | Generator pseudorandom numbers, |
||
96 | algorithm mrg32k3a. |
||
97 | |||
98 | Переделка из FreePascal на Oberon, Вадим Исаев, 2020 |
||
99 | Convert from FreePascal to Oberon, Vadim Isaev, 2020 |
||
100 | ---------------------------------------------------------- *) |
||
101 | (* Инициализация генератора. |
||
102 | |||
103 | Входные параметры: |
||
104 | seed - значение для инициализации. Любое. Если передать |
||
105 | ноль, то вместо ноля будет подставлено кол-во |
||
106 | процессорных тиков. *) |
||
107 | PROCEDURE mrg32k3a_init* (seed: REAL); |
||
108 | BEGIN |
||
109 | prndl.mrg32k3a_x[0] := 1.0; |
||
110 | prndl.mrg32k3a_x[1] := 1.0; |
||
111 | prndl.mrg32k3a_y[0] := 1.0; |
||
112 | prndl.mrg32k3a_y[1] := 1.0; |
||
113 | prndl.mrg32k3a_y[2] := 1.0; |
||
114 | |||
115 | IF seed # 0.0 THEN |
||
116 | prndl.mrg32k3a_x[2] := seed; |
||
117 | ELSE |
||
118 | prndl.mrg32k3a_x[2] := FLT(HOST.GetTickCount()); |
||
119 | END; |
||
120 | |||
121 | END mrg32k3a_init; |
||
122 | |||
123 | (* Генератор какбыслучайных чисел от 0.0 до 1.0. *) |
||
124 | PROCEDURE mrg32k3a* (): REAL; |
||
125 | |||
126 | CONST |
||
127 | (* random MRG32K3A algorithm constants *) |
||
128 | MRG32K3A_NORM = 2.328306549295728E-10; |
||
129 | MRG32K3A_M1 = 4294967087.0; |
||
130 | MRG32K3A_M2 = 4294944443.0; |
||
131 | MRG32K3A_A12 = 1403580.0; |
||
132 | MRG32K3A_A13 = 810728.0; |
||
133 | MRG32K3A_A21 = 527612.0; |
||
134 | MRG32K3A_A23 = 1370589.0; |
||
135 | RAND_BUFSIZE = 512; |
||
136 | |||
137 | VAR |
||
138 | |||
139 | xn, yn, result: REAL; |
||
140 | |||
141 | BEGIN |
||
142 | (* Часть 1 *) |
||
143 | xn := MRG32K3A_A12 * prndl.mrg32k3a_x[1] - MRG32K3A_A13 * prndl.mrg32k3a_x[2]; |
||
144 | xn := xn - MathRound.trunc(xn / MRG32K3A_M1) * MRG32K3A_M1; |
||
145 | IF xn < 0.0 THEN |
||
146 | xn := xn + MRG32K3A_M1; |
||
147 | END; |
||
148 | |||
149 | prndl.mrg32k3a_x[2] := prndl.mrg32k3a_x[1]; |
||
150 | prndl.mrg32k3a_x[1] := prndl.mrg32k3a_x[0]; |
||
151 | prndl.mrg32k3a_x[0] := xn; |
||
152 | |||
153 | (* Часть 2 *) |
||
154 | yn := MRG32K3A_A21 * prndl.mrg32k3a_y[0] - MRG32K3A_A23 * prndl.mrg32k3a_y[2]; |
||
155 | yn := yn - MathRound.trunc(yn / MRG32K3A_M2) * MRG32K3A_M2; |
||
156 | IF yn < 0.0 THEN |
||
157 | yn := yn + MRG32K3A_M2; |
||
158 | END; |
||
159 | |||
160 | prndl.mrg32k3a_y[2] := prndl.mrg32k3a_y[1]; |
||
161 | prndl.mrg32k3a_y[1] := prndl.mrg32k3a_y[0]; |
||
162 | prndl.mrg32k3a_y[0] := yn; |
||
163 | |||
164 | (* Смешение частей *) |
||
165 | IF xn <= yn THEN |
||
166 | result := ((xn - yn + MRG32K3A_M1) * MRG32K3A_NORM) |
||
167 | ELSE |
||
168 | result := (xn - yn) * MRG32K3A_NORM; |
||
169 | END; |
||
170 | |||
171 | RETURN result |
||
172 | END mrg32k3a; |
||
173 | |||
174 | |||
175 | (* ------------------------------------------------------------------- |
||
176 | Генератор какбыслучайных чисел, алгоритм Мерсена-Твистера (MT19937). |
||
177 | Переделка из Delphi в Oberon Вадим Исаев, 2020. |
||
178 | |||
179 | Mersenne Twister Random Number Generator. |
||
180 | |||
181 | A C-program for MT19937, with initialization improved 2002/1/26. |
||
182 | Coded by Takuji Nishimura and Makoto Matsumoto. |
||
183 | |||
184 | Adapted for DMath by Jean Debord - Feb. 2007 |
||
185 | Adapted for Oberon-07 by Vadim Isaev - May 2020 |
||
186 | ------------------------------------------------------------ *) |
||
187 | (* Initializes MT generator with a seed *) |
||
188 | PROCEDURE InitMT(Seed : INTEGER); |
||
189 | VAR |
||
190 | i : INTEGER; |
||
191 | BEGIN |
||
192 | mt[0] := MathBits.iand(Seed, INT_MAX); |
||
193 | FOR i := 1 TO N-1 DO |
||
194 | mt[i] := (1812433253 * MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) + i); |
||
195 | (* See Knuth TAOCP Vol2. 3rd Ed. P.106 For multiplier. |
||
196 | In the previous versions, MSBs of the seed affect |
||
197 | only MSBs of the array mt[]. |
||
198 | 2002/01/09 modified by Makoto Matsumoto *) |
||
199 | mt[i] := MathBits.iand(mt[i], INT_MAX); |
||
200 | (* For >32 Bit machines *) |
||
201 | END; |
||
202 | mti := N; |
||
203 | END InitMT; |
||
204 | |||
205 | (* Initialize MT generator with an array InitKey[0..(KeyLength - 1)] *) |
||
206 | PROCEDURE InitMTbyArray(InitKey : MTKeyArray; KeyLength : INTEGER); |
||
207 | VAR |
||
208 | i, j, k, k1 : INTEGER; |
||
209 | BEGIN |
||
210 | InitMT(19650218); |
||
211 | |||
212 | i := 1; |
||
213 | j := 0; |
||
214 | |||
215 | IF N > KeyLength THEN |
||
216 | k1 := N |
||
217 | ELSE |
||
218 | k1 := KeyLength; |
||
219 | END; |
||
220 | |||
221 | FOR k := k1 TO 1 BY -1 DO |
||
222 | (* non linear *) |
||
223 | mt[i] := MathBits.ixor(mt[i], (MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) * 1664525)) + InitKey[j] + j; |
||
224 | mt[i] := MathBits.iand(mt[i], INT_MAX); (* for WORDSIZE > 32 machines *) |
||
225 | INC(i); |
||
226 | INC(j); |
||
227 | IF i >= N THEN |
||
228 | mt[0] := mt[N-1]; |
||
229 | i := 1; |
||
230 | END; |
||
231 | IF j >= KeyLength THEN |
||
232 | j := 0; |
||
233 | END; |
||
234 | END; |
||
235 | |||
236 | FOR k := N-1 TO 1 BY -1 DO |
||
237 | (* non linear *) |
||
238 | mt[i] := MathBits.ixor(mt[i], (MathBits.ixor(mt[i-1], LSR(mt[i-1], 30)) * 1566083941)) - i; |
||
239 | mt[i] := MathBits.iand(mt[i], INT_MAX); (* for WORDSIZE > 32 machines *) |
||
240 | INC(i); |
||
241 | IF i >= N THEN |
||
242 | mt[0] := mt[N-1]; |
||
243 | i := 1; |
||
244 | END; |
||
245 | END; |
||
246 | |||
247 | mt[0] := UPPER_MASK; (* MSB is 1; assuring non-zero initial array *) |
||
248 | |||
249 | END InitMTbyArray; |
||
250 | |||
251 | (* Generates a integer Random number on [-2^31 .. 2^31 - 1] interval *) |
||
252 | PROCEDURE IRanMT(): INTEGER; |
||
253 | VAR |
||
254 | mag01 : ARRAY 2 OF INTEGER; |
||
255 | y,k : INTEGER; |
||
256 | BEGIN |
||
257 | IF mti >= N THEN (* generate N words at one Time *) |
||
258 | (* If IRanMT() has not been called, a default initial seed is used *) |
||
259 | IF mti = N + 1 THEN |
||
260 | InitMT(5489); |
||
261 | END; |
||
262 | |||
263 | FOR k := 0 TO (N-M)-1 DO |
||
264 | y := MathBits.ior(MathBits.iand(mt[k], UPPER_MASK), MathBits.iand(mt[k+1], LOWER_MASK)); |
||
265 | mt[k] := MathBits.ixor(MathBits.ixor(mt[k+M], LSR(y, 1)), mag01[MathBits.iand(y, 1H)]); |
||
266 | END; |
||
267 | |||
268 | FOR k := (N-M) TO (N-2) DO |
||
269 | y := MathBits.ior(MathBits.iand(mt[k], UPPER_MASK), MathBits.iand(mt[k+1], LOWER_MASK)); |
||
270 | mt[k] := MathBits.ixor(mt[k - (N - M)], MathBits.ixor(LSR(y, 1), mag01[MathBits.iand(y, 1H)])); |
||
271 | END; |
||
272 | |||
273 | y := MathBits.ior(MathBits.iand(mt[N-1], UPPER_MASK), MathBits.iand(mt[0], LOWER_MASK)); |
||
274 | mt[N-1] := MathBits.ixor(mt[M-1], MathBits.ixor(LSR(y, 1), mag01[MathBits.iand(y, 1H)])); |
||
275 | |||
276 | mti := 0; |
||
277 | END; |
||
278 | |||
279 | y := mt[mti]; |
||
280 | INC(mti); |
||
281 | |||
282 | (* Tempering *) |
||
283 | y := MathBits.ixor(y, LSR(y, 11)); |
||
284 | y := MathBits.ixor(y, MathBits.iand(LSL(y, 7), 9D2C5680H)); |
||
285 | y := MathBits.ixor(y, MathBits.iand(LSL(y, 15), 4022730752)); |
||
286 | y := MathBits.ixor(y, LSR(y, 18)); |
||
287 | |||
288 | RETURN y |
||
289 | END IRanMT; |
||
290 | |||
291 | (* Generates a real Random number on [0..1] interval *) |
||
292 | PROCEDURE RRanMT(): REAL; |
||
293 | BEGIN |
||
294 | RETURN FLT(IRanMT())/FLT(INT_MAX) |
||
295 | END RRanMT; |
||
296 | |||
297 | |||
298 | END RandExt.=>>> |