| package jnt.scimark2; |
| |
| /* 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. |
| */ |
| |
| 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; |
| |
| } |
| |
| } |