-- Ada implementation of the Mersenne Twister Pseudo-Random number generator -- S.MG, 2018 package body MT is procedure Init_Genrand(Seed : in U32) is begin State(0) := Seed; for I in State'First + 1 .. State'Last loop State(I) := U32(1812433253) * ( State(I - 1) xor ( Shift_Right(State(I - 1), 30) ) ) + U32(I) ; end loop; Mti_Flag := N; end Init_Genrand; procedure Init_Genrand(Seed : in Init_Array_Type) is Default_Seed: constant U32 := U32(19650218); -- magic value! I, J, K : Integer; begin Init_Genrand(Default_Seed); I := 1; J := 0; if N > Seed'Length then K := N; else K := Seed'Length; end if; while K > 0 loop State(I) := (State(I) xor ( (State(I-1) xor Shift_Right(State(I-1), 30) ) * U32(1664525) )) + Seed(J) + U32(J); I := I + 1; J := J + 1; if I >= N then State(0) := State(N-1); I := 1; end if; if J >= Seed'Length then J := 0; end if; K := K - 1; end loop; K := N -1; while K > 0 loop State(I) := (State(I) xor ( (State(I-1) xor Shift_Right(State(I-1), 30) ) * U32(1566083941) )) - U32(I); I := I + 1; if I >= N then State(0) := State(N-1); I := 1; end if; K := K - 1; end loop; State(0) := 16#8000_0000#; -- MSB is 1 to ensure non-zero initial state end Init_Genrand; function Gen_U32 return U32 is Y : U32; MASK1 : constant U32 := U32(1); Mag01 : Array ( 0 .. 1 ) of U32; begin -- Mag01[x] is x * Matrix_A of the algorithm for x 0 or 1 Mag01(0) := U32(0); Mag01(1) := MATRIX_MASK; -- if no numbers available, generate another set of N words if Mti_Flag >= N then -- check it's not a non-initialised generator if Mti_Flag = (N + 1) then -- Generator was NOT initialised! -- Original C code initialises with default seed 5489 -- This code will simply raise exception and abort raise No_Init_Exception; end if; for K in 0 .. N - M - 1 loop Y := ( State(K) and UPPER_MASK ) or ( State(K+1) and LOWER_MASK ); State(K) := State(K+M) xor Shift_Right(Y, 1) xor Mag01(Integer(Y and MASK1)); end loop; for K in N-M .. N - 2 loop Y := ( State(K) and UPPER_MASK ) or ( State(K+1) and LOWER_MASK); State(K) := State(K + M - N) xor Shift_Right(Y, 1) xor Mag01(Integer(Y and MASK1)); end loop; Y := (State(N-1) and UPPER_MASK ) or (State(0) and LOWER_MASK ); State(N - 1) := State(M-1) xor Shift_Right(Y, 1) xor Mag01(Integer(Y and MASK1)); Mti_Flag := 0; end if; -- retrieve next available number Y := State(Integer(Mti_Flag)); Mti_Flag := Mti_Flag + 1; -- tempering Y := Y xor Shift_Right(Y, 11); Y := Y xor (Shift_Left(Y, 7) and 16#9d2c_5680#); Y := Y xor (Shift_Left(Y, 15) and 16#efc6_0000#); Y := Y xor Shift_Right(Y, 18); -- return tempered number return Y; end Gen_U32; function Get_State return State_Type is begin return State; end Get_State; end MT;