/**
*
*/
package org.feature.model.utilities;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* According to the authors of
* Numerical Recipes: The Art of Scientific Computing
* two XORShift generators are combined with an LCG and a multiply with carry generator.
* taken from http://www.javamex.com/tutorials/random_numbers/numerical_recipes.shtml
*
* @author <a href=mailto:info@juliaschroeter.de>Julia Schroeter</a>
*
*/
public class HighQualityRandom extends Random {
/**
*
*/
private static final long serialVersionUID = 1L;
private Lock l = new ReentrantLock();
private long u;
private long v = 4101842887655102017L;
private long w = 1;
public HighQualityRandom() {
this(System.nanoTime());
}
public HighQualityRandom(long seed) {
l.lock();
u = seed ^ v;
nextLong();
v = u;
nextLong();
w = v;
nextLong();
l.unlock();
}
public long nextLong() {
l.lock();
try {
u = u * 2862933555777941757L + 7046029254386353087L;
v ^= v >>> 17;
v ^= v << 31;
v ^= v >>> 8;
w = 4294957665L * (w & 0xffffffff) + (w >>> 32);
long x = u ^ (u << 21);
x ^= x >>> 35;
x ^= x << 4;
long ret = (x + v) ^ w;
return ret;
}
finally {
l.unlock();
}
}
protected int next(int bits) {
return (int) (nextLong() >>> (64 - bits));
}
}