summaryrefslogtreecommitdiff
path: root/randomunit.pas
blob: 2b665f00076e9fa0e688df39f0cb52fc066cbfbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
unit randomunit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type
  tMersenneTwister = class
  private
    state: array[0..623] of longword;
    index: longint;
  public
    procedure init(seed: longword);
    function extract_number: longword;
    function random(ma: longword): longword; overload;
    function random: extended; overload;
    procedure generate_numbers;
  end;

implementation

// tMersenneTwister ************************************************************

procedure tMersenneTwister.init(seed: longword);
var
  i: longint;
begin
 index:=0;
 state[0]:=seed;
 for i:=1 to 623 do
   state[i]:=longword($ffffffff and (qword(1812433253) * qword(state[i-1] xor state[i-1] shr 30) + i)); // 0x6c078965
end;

function tMersenneTwister.extract_number: longword;
begin
 if index=0 then
   generate_numbers;

 result:=state[index];
 result:=result xor (result shr 11);
 result:=result xor longword(qword(result shl 7) and 2636928640);  // 0x9d2c5680
 result:=result xor longword(qword(result shl 15) and 4022730752); // 0xefc60000
 result:=result xor (result shr 18);

 index := (index + 1) mod 624;
end;

function tMersenneTwister.random(ma: longword): longword;
var
  i: longword;
begin
 repeat
   i:=extract_number;
 until i<((high(longword)+1) div qword(ma))*ma;
 result:=i mod ma;
end;

function tMersenneTwister.random: extended;
begin
 result:=(extract_number/(high(longword)+1) + extract_number)/(high(longword)+1);
end;

procedure tMersenneTwister.generate_numbers;
var
  i,y: longint;
begin
 for i:=0 to 623 do begin
   y:=longint((state[i] and $80000000) or            // bit 31 (32nd bit) of MT[i]
              (state[(i+1) mod 624] and $7fffffff)); // bits 0-30 (first 31 bits) of MT[...]
   state[i]:=state[(i + 397) mod 624] xor (y shr 1);
   if odd(y) then
     state[i]:=longword(state[i] xor 2567483615); // 0x9908b0df
 end;
end;

end.