RandExt.ob07 8.9 KB

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