package org.gwtnode.examples.scimark.impl; /* Random.java based on Java Numerical Toolkit (JNT) Random.UniformSequence class. We do not use Java's own java.util.Random so that we can compare results with equivalent C and Fortran coces. */ @SuppressWarnings("all") public class Random { /* ------------------------------------------------------------------------------ CLASS VARIABLES ------------------------------------------------------------------------------ */ int seed = 0; private int m[]; private int i = 4; private int j = 16; private final int mdig = 32; private final int one = 1; private final int m1 = (one << mdig-2) + ((one << mdig-2)-one); private final int m2 = one << mdig/2; /* For mdig = 32 : m1 = 2147483647, m2 = 65536 For mdig = 64 : m1 = 9223372036854775807, m2 = 4294967296 */ private double dm1 = 1.0 / (double) m1; private boolean haveRange = false; private double left = 0.0; private double right = 1.0; private double width = 1.0; /* ------------------------------------------------------------------------------ CONSTRUCTORS ------------------------------------------------------------------------------ */ /** Initializes a sequence of uniformly distributed quasi random numbers with a seed based on the system clock. */ public Random () { initialize( (int) System.currentTimeMillis()); } /** Initializes a sequence of uniformly distributed quasi random numbers on a given half-open interval [left,right) with a seed based on the system clock. @param <B>left</B> (double)<BR> The left endpoint of the half-open interval [left,right). @param <B>right</B> (double)<BR> The right endpoint of the half-open interval [left,right). */ public Random ( double left, double right) { initialize( (int) System.currentTimeMillis() ); this.left = left; this.right = right; width = right - left; haveRange = true; } /** Initializes a sequence of uniformly distributed quasi random numbers with a given seed. @param <B>seed</B> (int)<BR> The seed of the random number generator. Two sequences with the same seed will be identical. */ public Random (int seed) { initialize( seed); } /** Initializes a sequence of uniformly distributed quasi random numbers with a given seed on a given half-open interval [left,right). @param <B>seed</B> (int)<BR> The seed of the random number generator. Two sequences with the same seed will be identical. @param <B>left</B> (double)<BR> The left endpoint of the half-open interval [left,right). @param <B>right</B> (double)<BR> The right endpoint of the half-open interval [left,right). */ public Random (int seed, double left, double right) { initialize( seed); this.left = left; this.right = right; width = right - left; haveRange = true; } /* ------------------------------------------------------------------------------ PUBLIC METHODS ------------------------------------------------------------------------------ */ /** Returns the next random number in the sequence. */ public final synchronized double nextDouble () { int k; double nextValue; k = m[i] - m[j]; if (k < 0) k += m1; m[j] = k; if (i == 0) i = 16; else i--; if (j == 0) j = 16 ; else j--; if (haveRange) return left + dm1 * (double) k * width; else return dm1 * (double) k; } /** Returns the next N random numbers in the sequence, as a vector. */ public final synchronized void nextDoubles (double x[]) { int N = x.length; int remainder = N & 3; // N mod 4 if (haveRange) { for (int count=0; count<N; count++) { int k = m[i] - m[j]; if (i == 0) i = 16; else i--; if (k < 0) k += m1; m[j] = k; if (j == 0) j = 16; else j--; x[count] = left + dm1 * (double) k * width; } } else { for (int count=0; count<remainder; count++) { int k = m[i] - m[j]; if (i == 0) i = 16; else i--; if (k < 0) k += m1; m[j] = k; if (j == 0) j = 16; else j--; x[count] = dm1 * (double) k; } for (int count=remainder; count<N; count+=4) { int k = m[i] - m[j]; if (i == 0) i = 16; else i--; if (k < 0) k += m1; m[j] = k; if (j == 0) j = 16; else j--; x[count] = dm1 * (double) k; k = m[i] - m[j]; if (i == 0) i = 16; else i--; if (k < 0) k += m1; m[j] = k; if (j == 0) j = 16; else j--; x[count+1] = dm1 * (double) k; k = m[i] - m[j]; if (i == 0) i = 16; else i--; if (k < 0) k += m1; m[j] = k; if (j == 0) j = 16; else j--; x[count+2] = dm1 * (double) k; k = m[i] - m[j]; if (i == 0) i = 16; else i--; if (k < 0) k += m1; m[j] = k; if (j == 0) j = 16; else j--; x[count+3] = dm1 * (double) k; } } } /*---------------------------------------------------------------------------- PRIVATE METHODS ------------------------------------------------------------------------ */ private void initialize (int seed) { int jseed, k0, k1, j0, j1, iloop; this.seed = seed; m = new int[17]; jseed = Math.min(Math.abs(seed),m1); if (jseed % 2 == 0) --jseed; k0 = 9069 % m2; k1 = 9069 / m2; j0 = jseed % m2; j1 = jseed / m2; for (iloop = 0; iloop < 17; ++iloop) { jseed = j0 * k0; j1 = (jseed / m2 + j0 * k1 + j1 * k0) % (m2 / 2); j0 = jseed % m2; m[iloop] = j0 + m2 * j1; } i = 4; j = 16; } }