View Javadoc

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  			//super.seed=Integer.MAXValue --> seed & UMASK==0
99  			//We set the seed again and enforce a different value.
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 		// mag01[x] = x * MATRIX_A for x=0,1
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) // generate N words at one time
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; // TEMPERING_SHIFT_U(y)
144 		y ^= (y << 7) & TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
145 		y ^= (y << 15) & TEMPERING_MASK_C; // TEMPERING_SHIFT_T(y)
146 		y ^= (y >>> 18); // TEMPERING_SHIFT_L(y)
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 }