Skip to content

Commit a0f9705

Browse files
committed
fix the initial state of the MT and get rid of members holding the state
1 parent e17f399 commit a0f9705

File tree

3 files changed

+24
-36
lines changed

3 files changed

+24
-36
lines changed

src/main/java/ro/derbederos/untwist/FreePascalRandom.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ public class FreePascalRandom extends ReversibleMersenneTwister {
3737

3838
/**
3939
* Creates a new random number generator.
40-
* <p>The instance is initialized using the current time plus the
41-
* system identity hash code of this instance as the seed.</p>
40+
* <p>
41+
* The instance is initialized using the current time plus the
42+
* system identity hash code of this instance as the seed.
4243
*/
4344
public FreePascalRandom() {
4445
super();

src/main/java/ro/derbederos/untwist/MersenneTwisterPy3k.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ public class MersenneTwisterPy3k extends ReversibleMersenneTwister {
3232

3333
/**
3434
* Creates a new random number generator.
35-
* <p>The instance is initialized using the current time plus the
36-
* system identity hash code of this instance as the seed.</p>
35+
* <p>
36+
* The instance is initialized using the current time plus the
37+
* system identity hash code of this instance as the seed.
3738
*/
3839
public MersenneTwisterPy3k() {
3940
super();

src/main/java/ro/derbederos/untwist/ReversibleMersenneTwister.java

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,6 @@ public class ReversibleMersenneTwister extends ReverseBitsStreamGenerator implem
106106
*/
107107
private int mti;
108108

109-
// used to store the first and last element of the initial state
110-
// because, either first or last element can't be restored
111-
private final int[] mt_initial = new int[2];
112-
private long twists;
113-
114109
/**
115110
* Creates a new random number generator.
116111
* <p>
@@ -168,11 +163,6 @@ private void initGenRand(int seed) {
168163
}
169164

170165
clear(); // Clear normal deviate cache
171-
172-
// Saving initial state separately
173-
mt_initial[0] = mt[0];
174-
mt_initial[1] = mt[N - 1];
175-
twists = 0;
176166
}
177167

178168
/**
@@ -189,6 +179,8 @@ private void initGenRand(int seed) {
189179
@Override
190180
public void setSeed(int seed) {
191181
initGenRand(seed);
182+
fixState();
183+
clear();
192184
}
193185

194186
/**
@@ -245,19 +237,15 @@ public void setSeed(int[] seed) {
245237
}
246238

247239
mt[0] = 0x80000000; // MSB is 1; assuring non-zero initial array
248-
240+
fixState();
249241
clear(); // Clear normal deviate cache
250-
251-
// Saving initial state separately
252-
mt_initial[0] = mt[0];
253-
mt_initial[1] = mt[N - 1];
254-
twists = 0;
255242
}
256243

257244
/**
258245
* Reinitialize the generator as if just built with the given long seed.
259-
* <p>The state of the generator is exactly the same as a new
260-
* generator built with the same seed.</p>
246+
* <p>
247+
* The state of the generator is exactly the same as a new
248+
* generator built with the same seed.
261249
*
262250
* @param seed the initial seed (64 bits integer)
263251
*/
@@ -266,13 +254,21 @@ public void setSeed(long seed) {
266254
setSeed(new int[]{(int) (seed >>> 32), (int) (seed & 0xFFFFFFFFL)});
267255
}
268256

257+
private void fixState() {
258+
// fixing the state so going in reverse first
259+
// and next go forward should work just fine
260+
twist();
261+
untwist();
262+
}
263+
269264
/**
270265
* Generate next pseudorandom number.
271-
* <p>This method is the core generation algorithm. It is used by all the
266+
* <p>
267+
* This method is the core generation algorithm. It is used by all the
272268
* public generation methods for the various primitive types {@link
273269
* #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()},
274270
* {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()},
275-
* {@link #next(int)} and {@link #nextLong()}.</p>
271+
* {@link #next(int)} and {@link #nextLong()}.
276272
* <p>
277273
* Part of the <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c">original code</a>.
278274
* Modified version of method {@code genrand_int32} to return exactly {@code bits} bits.
@@ -312,10 +308,6 @@ void twist() {
312308
int x = (mt[i] & 0x80000000) | (mt[(i + 1) % N] & 0x7FFFFFFF);
313309
mt[i] = mt[(i + M) % N] ^ (x >>> 1) ^ MAG01[x & 0x1];
314310
}
315-
if (++twists == 0) {
316-
mt[0] = mt_initial[0];
317-
mt[N - 1] = mt_initial[1];
318-
}
319311
}
320312

321313
/**
@@ -344,8 +336,7 @@ void untwist() {
344336
for (int i = 623; i >= 0; i--) {
345337
int result;
346338
// first we calculate the first bit
347-
int tmp = mt[i];
348-
tmp ^= mt[(i + M) % N];
339+
int tmp = mt[i] ^ mt[(i + M) % N];
349340
// if the first bit is odd, unapply magic
350341
if ((tmp & 0x80000000) == 0x80000000) {
351342
tmp ^= 0x9908B0DF;
@@ -354,8 +345,7 @@ void untwist() {
354345
result = (tmp << 1) & 0x80000000;
355346

356347
// work out the remaining 31 bits
357-
tmp = mt[(i - 1 + N) % N];
358-
tmp ^= mt[(i + M - 1) % N];
348+
tmp = mt[(i - 1 + N) % N] ^ mt[(i + M - 1) % N];
359349
if ((tmp & 0x80000000) == 0x80000000) {
360350
tmp ^= 0x9908B0DF;
361351
// since it was odd, the last bit must have been 1
@@ -365,10 +355,6 @@ void untwist() {
365355
result |= (tmp << 1) & 0x7FFFFFFF;
366356
mt[i] = result;
367357
}
368-
if (--twists == 0) {
369-
mt[0] = mt_initial[0];
370-
mt[N - 1] = mt_initial[1];
371-
}
372358
}
373359

374360
/**

0 commit comments

Comments
 (0)