1 package nl.tudelft.simulation.jstats.streams;
2
3 /***
4 * A java implementation of the Mersenne Twister pseudo random number generator.
5 * <P>
6 * This is a Java version of the C-program for MT19937: Integer version.
7 * genrand() generates one pseudorandom unsigned integer (32bit) which is
8 * uniformly distributed among 0 to 2^32-1 for each call. sgenrand(seed) set
9 * initial values to the working area of 624 words. (seed is any 32-bit integer
10 * except for 0).
11 * <p>
12 * Orignally Coded by Takuji Nishimura, considering the suggestions by Topher
13 * Cooper and Marc Rieffel in July-Aug. 1997. More information can be found at
14 * <A HREF="http://www.math.keio.ac.jp/matumoto/emt.html">
15 * http://www.math.keio.ac.jp/matumoto/emt.html </A>.
16 * <P>
17 * Makoto Matsumoto and Takuji Nishimura, the original authors ask "When you use
18 * this, send an email to: matumoto@math.keio.ac.jp with an appropriate
19 * reference to your work" You might also point out this was a translation.
20 * <p>
21 * (c) copyright 2004 <a href="http://www.simulation.tudelft.nl">Delft
22 * University of Technology </a>, the Netherlands. <br>
23 * See for project information <a href="http://www.simulation.tudelft.nl">
24 * www.simulation.tudelft.nl </a> <br>
25 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
26 * License (GPL) </a>, no warranty <br>
27 *
28 * @author <a href="http://www.simulation.tudelft.nl/people/jacobs.html">Peter
29 * Jacobs </a>
30 * @version 1.8 2004-03-18
31 * @since 1.0
32 */
33 public class MersenneTwister extends RandomNumberGenerator
34 {
35 /*** Period parameter N */
36 private static final int N = 624;
37
38 /*** Period parameter M */
39 private static final int M = 397;
40
41 /*** constant vector a */
42 private static final int MATRIX_A = 0x9908b0df;
43
44 /*** most significant w-r bits */
45 private static final int UPPER_MASK = 0x80000000;
46
47 /*** least significant w-r bits */
48 private static final int LOWER_MASK = 0x7fffffff;
49
50 /*** tempering mask B */
51 private static final int TEMPERING_MASK_B = 0x9d2c5680;
52
53 /*** tempering mask B */
54 private static final int TEMPERING_MASK_C = 0xefc60000;
55
56 /*** unsigned mask for promoting int -> long */
57 private static final int UMASK = (1 << 31) - 1;
58
59 /*** the array for the state vector */
60 private int[] mt;
61
62 /*** The counter mti==N+1 means mt[N] is not initialized */
63 private int mti;
64
65 /*** magic01 */
66 private int[] mag01;
67
68 /***
69 * constructs a new Mersenne Twister.
70 * <code>System.currentTimeMillis()</code> is used as seed value.
71 *
72 */
73 public MersenneTwister()
74 {
75 this(System.currentTimeMillis());
76 }
77
78 /***
79 * Constructor using a given seed.
80 *
81 * @param seed The initial seed.
82 */
83 public MersenneTwister(final long seed)
84 {
85 super(seed);
86 }
87
88 /***
89 * initalizes the MersenneTwister
90 */
91 private void initialize()
92 {
93 this.mt = new int[N];
94
95 this.mt[0] = ((int) super.seed) & UMASK;
96 if (this.mt[0] == 0)
97 {
98
99
100 this.setSeed(System.currentTimeMillis());
101 }
102 for (this.mti = 1; this.mti < N; this.mti++)
103 {
104 this.mt[this.mti] = (69069 * this.mt[this.mti - 1]);
105 }
106
107
108 this.mag01 = new int[2];
109 this.mag01[0] = 0x0;
110 this.mag01[1] = MATRIX_A;
111 }
112
113 /***
114 * @see nl.tudelft.simulation.jstats.streams.RandomNumberGenerator#next(int)
115 */
116 protected synchronized long next(final int bits)
117 {
118 if (bits < 0 || bits > 64)
119 {
120 throw new IllegalArgumentException("bits (" + bits
121 + ") not in range [0,64]");
122 }
123 int y;
124 if (this.mti >= N)
125 {
126 int kk;
127 for (kk = 0; kk < N - M; kk++)
128 {
129 y = (this.mt[kk] & UPPER_MASK) | (this.mt[kk + 1] & LOWER_MASK);
130 this.mt[kk] = this.mt[kk + M] ^ (y >>> 1) ^ this.mag01[y & 0x1];
131 }
132 for (; kk < N - 1; kk++)
133 {
134 y = (this.mt[kk] & UPPER_MASK) | (this.mt[kk + 1] & LOWER_MASK);
135 this.mt[kk] = this.mt[kk + (M - N)] ^ (y >>> 1)
136 ^ this.mag01[y & 0x1];
137 }
138 y = (this.mt[N - 1] & UPPER_MASK) | (this.mt[0] & LOWER_MASK);
139 this.mt[N - 1] = this.mt[M - 1] ^ (y >>> 1) ^ this.mag01[y & 0x1];
140 this.mti = 0;
141 }
142 y = this.mt[this.mti++];
143 y ^= y >>> 11;
144 y ^= (y << 7) & TEMPERING_MASK_B;
145 y ^= (y << 15) & TEMPERING_MASK_C;
146 y ^= (y >>> 18);
147 if (bits <= 32)
148 {
149 return y >>> (32 - bits);
150 }
151 return y << 32 + this.next(bits - 32);
152 }
153
154 /***
155 * @see nl.tudelft.simulation.jstats.streams.StreamInterface#setSeed(long)
156 */
157 public synchronized void setSeed(final long seed)
158 {
159 super.seed = seed;
160 this.initialize();
161 }
162 }