/*
* Encog(tm) Core v3.4 - Java Version
* http://www.heatonresearch.com/encog/
* https://github.com/encog/encog-java-core
* Copyright 2008-2016 Heaton Research, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For more information on Heaton Research copyrights, licenses
* and trademarks visit:
* http://www.heatonresearch.com/copyright
*/
package org.encog.mathutil.randomize.generate;
/**
* The Mersenne twister is a pseudo random number generator developed in 1997 by Makoto Matsumoto and
* Takuji Nishimura that is based on a matrix linear recurrence over a finite binary field F2.
*
* References:
* http://www.cs.gmu.edu/~sean/research
* http://en.wikipedia.org/wiki/Mersenne_twister/
*
* Makato Matsumoto and Takuji Nishimura, "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform
* Pseudo-Random Number Generator", ACM Transactions on Modeling and. Computer Simulation,
* Vol. 8, No. 1, January 1998, pp 3--30.
*/
public class MersenneTwisterGenerateRandom extends AbstractBoxMuller {
private static final int N = 624;
private static final int M = 397;
private static final int MATRIX_A = 0x9908b0df;
private static final int UPPER_MASK = 0x80000000;
private static final int LOWER_MASK = 0x7fffffff;
private static final int TEMPERING_MASK_B = 0x9d2c5680;
private static final int TEMPERING_MASK_C = 0xefc60000;
private int stateVector[];
private int mti;
private int mag01[];
public MersenneTwisterGenerateRandom() {
this(System.currentTimeMillis());
}
public MersenneTwisterGenerateRandom(final long seed) {
setSeed(seed);
}
public MersenneTwisterGenerateRandom(final int[] array) {
setSeed(array);
}
public void setSeed(final long seed) {
stateVector = new int[N];
mag01 = new int[2];
mag01[0] = 0x0;
mag01[1] = MATRIX_A;
stateVector[0] = (int) seed;
for (mti = 1; mti < N; mti++) {
stateVector[mti] =
(1812433253 * (stateVector[mti - 1] ^ (stateVector[mti - 1] >>> 30)) + mti);
}
}
public void setSeed(final int[] array) {
int i, j, k;
setSeed(19650218);
i = 1;
j = 0;
k = (N > array.length ? N : array.length);
for (; k != 0; k--) {
stateVector[i] = (stateVector[i] ^ ((stateVector[i - 1] ^ (stateVector[i - 1] >>> 30)) * 1664525)) + array[j] + j;
i++;
j++;
if (i >= N) {
stateVector[0] = stateVector[N - 1];
i = 1;
}
if (j >= array.length) j = 0;
}
for (k = N - 1; k != 0; k--) {
stateVector[i] = (stateVector[i] ^ ((stateVector[i - 1] ^ (stateVector[i - 1] >>> 30)) * 1566083941)) - i;
i++;
if (i >= N) {
stateVector[0] = stateVector[N - 1];
i = 1;
}
}
stateVector[0] = 0x80000000;
}
protected int next(final int bits) {
int y;
if (mti >= N) {
int kk;
for (kk = 0; kk < N - M; kk++) {
y = (stateVector[kk] & UPPER_MASK) | (stateVector[kk + 1] & LOWER_MASK);
stateVector[kk] = stateVector[kk + M] ^ (y >>> 1) ^ mag01[y & 0x1];
}
for (; kk < N - 1; kk++) {
y = (stateVector[kk] & UPPER_MASK) | (stateVector[kk + 1] & LOWER_MASK);
stateVector[kk] = stateVector[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 0x1];
}
y = (stateVector[N - 1] & UPPER_MASK) | (stateVector[0] & LOWER_MASK);
stateVector[N - 1] = stateVector[M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
mti = 0;
}
y = stateVector[mti++];
y ^= y >>> 11;
y ^= (y << 7) & TEMPERING_MASK_B;
y ^= (y << 15) & TEMPERING_MASK_C;
y ^= (y >>> 18);
return y >>> (32 - bits);
}
@Override
public double nextDouble() {
return (((long) next(26) << 27) + next(27))
/ (double) (1L << 53);
}
public long nextLong() {
return ((long) next(32) << 32) + next(32);
}
/**
* {@inheritDoc}
*/
@Override
public boolean nextBoolean() {
return nextDouble() > 0.5;
}
/**
* {@inheritDoc}
*/
@Override
public float nextFloat() {
return (float) nextDouble();
}
/**
* {@inheritDoc}
*/
@Override
public int nextInt() {
return (int) nextLong();
}
}