package org.jwildfire.create.tina.random;
import java.util.Random;
public class ZigguratRandom extends Random
{
/**
* This class was found here /github.com/OliverColeman/bain/blob/master/src/com/ojcoleman/bain/misc/Ziggurat.java
* permission was asked here: /github.com/OliverColeman/bain/issues/1
*
* Assuming this is public domain until we can find Andreas Schouten or a similar Ziggurat algo is implemented
* schouten-blog.de is unaccessible as of April 18 2015
* original:
*
* This class implements the ziggurat algorithm for normal distributed random numbers as provided by George Marsaglia and Wai Wan Tsang in 2000.
*
* @author Andreas Schouten (andreas@schouten-blog.de) ?
* @author George Marsaglia
* @author Wai Wan Tsang
*
* The constants seem to be based on the original paper here, so this fits the JWildFire license
* Credit / Citation:
* [Oct 2000 George Marsaglia, Wai Wan Tsang] The ziggurat method for generating random variables
* http://www.jstatsoft.org/v05/i08
* http://creativecommons.org/licenses/by/3.0/
*
* === enhancements to original ===
* Converted from int to long in SHR3, stripped out methods not needed by JWildFire
*/
private static final long serialVersionUID = 1L;
public ZigguratRandom() {
this(System.nanoTime());
}
public ZigguratRandom(long seed) {
super();
setSeed(seed);
zigset();
}
public double nextDouble() {
return UNI();
}
public void setSeed(long seed) {
jsr ^= (int) seed;
super.setSeed(seed);
}
private long jsr = 123456768;
private static int[] kn;
private static double[] wn, fn;
private static boolean initialized = false;
private long SHR3() {
long jz = jsr;
long jzr = jsr;
jzr ^= (jzr << 13);
jzr ^= (jzr >>> 17);
jzr ^= (jzr << 5);
jsr = jzr;
return jz + jzr;
}
private double UNI() {
return 0.5 * (1.0 + (double)SHR3() / (double)Long.MIN_VALUE);
}
private static synchronized void zigset() {
if (initialized)
return;
initialized = true;
wn = new double[128];
fn = new double[128];
kn = new int[128];
double m1 = 2147483648.0;
double dn = 3.442619855899, tn = dn, vn = 9.91256303526217e-3, q;
int i;
/* Set up tables for RNOR */
q = vn / Math.exp(-.5 * dn * dn);
kn[0] = (int) ((dn / q) * m1);
kn[1] = 0;
wn[0] = q / m1;
wn[127] = dn / m1;
fn[0] = 1.;
fn[127] = Math.exp(-.5 * dn * dn);
for (i = 126; i >= 0; i--) {
dn = Math.sqrt(-2. * Math.log(vn / dn + Math.exp(-.5 * dn * dn)));
kn[i + 1] = (int) ((dn / tn) * m1);
tn = dn;
fn[i] = Math.exp(-.5 * dn * dn);
wn[i] = dn / m1;
}
}
}