A linear random method based on xor shifts
//package com.studiofortress.sf.util;
import java.util.Random;
/**
* a linear random method based on xor shifts--which is a fast way to do LFSR
* --ie one clock per bit is slow. This is faster per step that java Random.
*
* This does better than LCC generators (ie passes the monkey tests and DNA
* tests where LCG dont). In other words it does not have the hyperplane
* problem.
*
* This has a period of 2**128-1. This is quite easy to prove as follows.
*
* the counter can be shown to be a LFSR with period 2**64-1. However we have a
* simple counter in the stepped variable. That is after 2**64 counts stepped
* mod 2**64 == 0. Hence the phase is shifted by one and the period of stepped
* and counter are relatively prime. We combine them with Addition, which is
* slightly nonlinear due to carry. Of course we could just use a simple ++
* counter. But thats boring.
*
* We could use * for this as well and have a stronger condition for non
* lineararity.
*
* We speed up the nextDouble function as well.
*
* @author bob - http://www.javagaming.org/index.php/topic,18426.0.html
*/
final class Random64 extends Random
{
private static final double LONG_2_DOUBLE =1.0 / (double)(1L<<53);
private static final long MASK_53=(1l<<53)-1;
private static final long serialVersionUID =-6678124822567014769L;
private static final long PRIME =0xd4d6712ee634312dl;
private long counter ;
private long stepped ;
public Random64() {
super();
setSeed(System.nanoTime());
}
public Random64(long seed) {
super(seed);
setSeed(seed);
}
private void step(){
counter ^=(counter << 21);
counter ^=(counter >>> 35);
counter ^=(counter << 4);
stepped +=PRIME;
}
/**
* could use all 64 bits over 2 calls?
*/
@Override
protected int next(int bits) {
step();
// Hate the dumb mask
return (int) (((counter + stepped) >>> 31) & ((1l << bits) - 1));
}
@Override
public void setSeed(long seed) {
counter =seed;
if (counter == 0)
counter =1;
stepped=0;
step();
step();
step();
stepped=0;
}
/**
* uses only 32 bits of precision.
*/
@Override
public double nextDouble() {
step();
return ((counter+stepped) & MASK_53)*LONG_2_DOUBLE;
}
@Override
public long nextLong() {
step();
return counter+stepped;
}
}
Related examples in the same category