-
+ 51A08CE52E8DF06FC1CAC9D4DFD9EBFED15EACFBE86011D481326668D17007482E2998F516F29CAA2A4175154D3CE60C8A805F7A6214B609A2CD613E7649B5AE
udp/libmt/mt.adb
(0 . 0)(1 . 128)
10 -- Ada implementation of the Mersenne Twister Pseudo-Random number generator
11 -- S.MG, 2018
12
13
14 package body MT is
15
16 procedure Init_Genrand(Seed : in U32) is
17 begin
18 State(0) := Seed;
19 for I in State'First + 1 .. State'Last loop
20 State(I) := U32(1812433253) *
21 ( State(I - 1) xor
22 ( Shift_Right(State(I - 1), 30) )
23 ) + U32(I) ;
24 end loop;
25 Mti_Flag := N;
26 end Init_Genrand;
27
28 procedure Init_Genrand(Seed : in Init_Array_Type) is
29 Default_Seed: constant U32 := U32(19650218); -- magic value!
30 I, J, K : Integer;
31 begin
32 Init_Genrand(Default_Seed);
33 I := 1;
34 J := 0;
35 if N > Seed'Length then
36 K := N;
37 else
38 K := Seed'Length;
39 end if;
40
41 while K > 0 loop
42 State(I) := (State(I) xor
43 ( (State(I-1) xor
44 Shift_Right(State(I-1), 30)
45 ) * U32(1664525)
46 )) + Seed(J) + U32(J);
47 I := I + 1;
48 J := J + 1;
49 if I >= N then
50 State(0) := State(N-1);
51 I := 1;
52 end if;
53 if J >= Seed'Length then
54 J := 0;
55 end if;
56 K := K - 1;
57 end loop;
58
59 K := N -1;
60 while K > 0 loop
61 State(I) := (State(I) xor
62 ( (State(I-1) xor
63 Shift_Right(State(I-1), 30)
64 ) * U32(1566083941)
65 )) - U32(I);
66 I := I + 1;
67 if I >= N then
68 State(0) := State(N-1);
69 I := 1;
70 end if;
71 K := K - 1;
72 end loop;
73 State(0) := 16#8000_0000#; -- MSB is 1 to ensure non-zero initial state
74 end Init_Genrand;
75
76 function Gen_U32 return U32 is
77 Y : U32;
78 MASK1 : constant U32 := U32(1);
79 Mag01 : Array ( 0 .. 1 ) of U32;
80 begin
81 -- Mag01[x] is x * Matrix_A of the algorithm for x 0 or 1
82 Mag01(0) := U32(0);
83 Mag01(1) := MATRIX_MASK;
84
85 -- if no numbers available, generate another set of N words
86 if Mti_Flag >= N then
87
88 -- check it's not a non-initialised generator
89 if Mti_Flag = (N + 1) then
90 -- Generator was NOT initialised!
91 -- Original C code initialises with default seed 5489
92 -- This code will simply raise exception and abort
93 raise No_Init_Exception;
94 end if;
95
96 for K in 0 .. N - M - 1 loop
97 Y := ( State(K) and UPPER_MASK ) or
98 ( State(K+1) and LOWER_MASK );
99 State(K) := State(K+M) xor
100 Shift_Right(Y, 1) xor
101 Mag01(Integer(Y and MASK1));
102 end loop;
103 for K in N-M .. N - 2 loop
104 Y := ( State(K) and UPPER_MASK ) or
105 ( State(K+1) and LOWER_MASK);
106 State(K) := State(K + M - N) xor
107 Shift_Right(Y, 1) xor
108 Mag01(Integer(Y and MASK1));
109 end loop;
110 Y := (State(N-1) and UPPER_MASK ) or
111 (State(0) and LOWER_MASK );
112 State(N - 1) := State(M-1) xor
113 Shift_Right(Y, 1) xor
114 Mag01(Integer(Y and MASK1));
115 Mti_Flag := 0;
116 end if;
117
118 -- retrieve next available number
119 Y := State(Integer(Mti_Flag));
120 Mti_Flag := Mti_Flag + 1;
121
122 -- tempering
123 Y := Y xor Shift_Right(Y, 11);
124 Y := Y xor (Shift_Left(Y, 7) and 16#9d2c_5680#);
125 Y := Y xor (Shift_Left(Y, 15) and 16#efc6_0000#);
126 Y := Y xor Shift_Right(Y, 18);
127
128 -- return tempered number
129 return Y;
130 end Gen_U32;
131
132 function Get_State return State_Type is
133 begin
134 return State;
135 end Get_State;
136
137 end MT;