I implemented the Mersenne Twister in Modula-3 some time ago, however when I test it out (the same test data that the authors of the Mersenne Twister used), the output is different. I tested this code on both 32 and 64 bit machines, and they both give me the same results, but the results are different from that of the original Mersenne Twister code.<div>
<br></div><div>Here's the code:</div><div><br></div><div>INTERFACE MT19937ar;</div><div><br></div><div>IMPORT Word;</div><div><br></div><div>PROCEDURE initGenrand(s: Word.T);</div><div>PROCEDURE initByArray(key: ARRAY OF Word.T; length: INTEGER);</div>
<div><br></div><div>PROCEDURE genrandInt32(): Word.T;</div><div>PROCEDURE genrandInt31(): INTEGER;</div><div>PROCEDURE genrandReal1(): REAL;</div><div>PROCEDURE genrandReal2(): REAL;</div><div>PROCEDURE genrandReal3(): REAL;</div>
<div><br></div><div>END MT19937ar.</div><div><br></div><div>(*********)</div><div><br></div><div><div>MODULE MT19937ar;</div><div><br></div><div>IMPORT Word;</div><div>FROM Word IMPORT And, Xor, Or, RightShift, LeftShift;</div>
<div><br></div><div>CONST</div><div> n = 624;</div><div> m = 397;</div><div> matrix_a = 16_9908b0df;</div><div> upper_mask = 16_80000000;</div><div> lower_mask = 16_7fffffff;</div><div><br></div><div>VAR</div><div> mt: ARRAY [0..n] OF Word.T;</div>
<div> mti := n + 1;</div><div><br></div><div>PROCEDURE initGenrand(s: Word.T) =</div><div> BEGIN</div><div> mt[0] := And(s, 16_ffffffff);</div><div> FOR mti := 1 TO n - 1 DO</div><div> mt[mti] := 1812433253 * (Xor(mt[mti-1], RightShift(mt[mti-1], 30))) + mti;</div>
<div> mt[mti] := And(mt[mti], 16_ffffffff);</div><div> END;</div><div> END initGenrand;</div><div><br></div><div>PROCEDURE initByArray(key: ARRAY OF Word.T; length: INTEGER) =</div><div> VAR i, j, k: INTEGER;</div>
<div> BEGIN</div><div> i := 1; j := 0;</div><div> initGenrand(19650218);</div><div> IF n > length THEN k := n ELSE k := length; END;</div><div> </div><div> WHILE k # 0 DO</div><div> mt[i] := Xor(mt[i], Xor(mt[i-1], RightShift(mt[i-1], 30)) * 1664525) + </div>
<div> key[j] + j;</div><div> mt[i] := And(mt[i], 16_ffffffff);</div><div> INC(i); INC(j);</div><div> </div><div> IF i >= n THEN </div><div> mt[0] := mt[n-1];</div><div> i := 1;</div>
<div> END;</div><div><br></div><div> IF j >= length THEN</div><div> j := 0;</div><div> END;</div><div> DEC(k);</div><div> END;</div><div><br></div><div> k := n - 1;</div><div> WHILE k # 0 DO</div>
<div> mt[i] := Xor(mt[i], Xor(mt[i-1], RightShift(mt[i-1], 30)) * 1566083941) - i;</div><div> mt[i] := And(mt[i], 16_ffffffff);</div><div> INC(i);</div><div> </div><div> IF i >= n THEN</div><div>
mt[0] := mt[n-1];</div><div> i := 1;</div><div> END;</div><div> DEC(k);</div><div> END;</div><div><br></div><div> mt[0] := 16_80000000;</div><div> END initByArray;</div><div><br></div><div>
PROCEDURE genrandInt32(): Word.T =</div><div> VAR y: Word.T;</div><div> k: INTEGER := 0;</div><div> mag01 := ARRAY [0..1] OF Word.T {0, matrix_a};</div><div> </div><div> BEGIN</div><div> IF mti >= n THEN</div>
<div> IF mti = (n + 1) THEN</div><div> initGenrand(5489);</div><div> END;</div><div><br></div><div> WHILE k < (n - m) DO</div><div> y := Or(And(mt[k], upper_mask), And(mt[k+1], lower_mask));</div>
<div> mt[k] := Xor(Xor(mt[k+m], RightShift(y, 1)), mag01[And(y, 1)]);</div><div> INC(k);</div><div> END;</div><div> </div><div> WHILE k < (n - 1) DO</div><div> y := Or(And(mt[k], upper_mask), And(mt[k+1], lower_mask));</div>
<div> mt[k] := Xor(Xor(mt[k+(m-n)], RightShift(y, 1)), mag01[And(y, 1)]);</div><div> INC(k);</div><div> END;</div><div><br></div><div> y := Or(And(mt[n-1], upper_mask), And(mt[0], lower_mask));</div>
<div> mt[n-1] := Xor(Xor(mt[m-1], RightShift(y, 1)), mag01[And(y, 1)]);</div><div> mti := 0;</div><div> END;</div><div><br></div><div> y := mt[mti];</div><div> INC(mti);</div><div><br></div><div> y := Xor(y, RightShift(y, 11));</div>
<div> y := Xor(y, And(LeftShift(y, 7), 16_9d2c5680));</div><div> y := Xor(y, And(LeftShift(y, 15), 16_efc60000));</div><div> y := Xor(y, RightShift(y, 18));</div><div><br></div><div> RETURN y;</div><div> END genrandInt32;</div>
<div><br></div><div>PROCEDURE genrandInt31(): INTEGER =</div><div> BEGIN</div><div> RETURN RightShift(genrandInt32(), 1);</div><div> END genrandInt31;</div><div><br></div><div>PROCEDURE genrandReal1(): REAL =</div><div>
BEGIN</div><div> RETURN FLOAT(genrandInt32(), REAL) * (1.0 / 4294967295.0);</div><div> END genrandReal1;</div><div><br></div><div>PROCEDURE genrandReal2(): REAL =</div><div> BEGIN</div><div> RETURN FLOAT(genrandInt32(), REAL) * (1.0 / 4294967296.0);</div>
<div> END genrandReal2;</div><div><br></div><div>PROCEDURE genrandReal3(): REAL =</div><div> BEGIN</div><div> RETURN (FLOAT(genrandInt32(), REAL) + 0.5) * (1.0 / 4294967296.0);</div><div> END genrandReal3;</div><div>
<br></div><div>BEGIN</div><div>END MT19937ar.</div></div><div><br></div><div>(********)</div><div><br></div><div><div>MODULE Main;</div><div><br></div><div>IMPORT IO, Fmt, MT19937ar;</div><div><br></div><div>VAR init := ARRAY [0..3] OF INTEGER {16_123, 16_234, 16_345, 16_456};</div>
<div> len := 4;</div><div><br></div><div>BEGIN</div><div> MT19937ar.initByArray(init, len);</div><div> IO.Put("Random integers: ");</div><div> FOR i := 1 TO 999 DO</div><div> IO.Put(Fmt.Unsigned(MT19937ar.genrandInt32(), base := 10));</div>
<div> IO.Put(" ");</div><div> IF (i MOD 5) = 4 THEN IO.Put("\n"); END;</div><div> END;</div><div> IO.Put("\n");</div><div>END Main.</div></div><div><br></div><div>And here is the first few numbers it outputs:</div>
<div><br></div><div>3499211612 581869302 3890346734 3586334585 ...</div><div><br></div><div>Compare that to the first few numbers of output from the original Mersenne Twister code, in C:</div><div><br></div><div>1067595299 955945823 477289528 4107218783 ...</div>
<div><br></div><div>Anyone know why they are different? Is the code wrong, or is it an implementation difference, or what?</div>