package com.bigdata.testutil;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
/**
* XorShift - provides a pseudo random number generator without synchronization
* which is used for unit tests in which we do not want to introduce side
* effects from synchronization by the test harness on the object under test.
*
* @author Brian Goetz and Tim Peierls
* @author Bryan Thompson
*/
public class XorShift {
private static final AtomicInteger seq = new AtomicInteger(8862213);
private int x = -1831433054;
public XorShift(final int seed) {
x = seed;
}
public XorShift() {
this((int) System.nanoTime() + seq.getAndAdd(129));
}
public int next() {
x ^= x << 6;
x ^= x >>> 21;
x ^= (x << 7);
return x;
}
/** For compatibility with {@link Random#nextInt()}. */
public int nextInt() {
return next();
}
/** For compatibility with {@link Random#nextBoolean()}. */
public boolean nextBoolean() {
final int b = next();
/*
* mask a bit and test for non-zero. this uses bit ONE which tends to
* produce true and false with a uniform distribution as demonstrated by
* the main() routine.
*/
return (b & 1/* mask */) != 0;
}
/** For compatibility with {@link Random#nextFloat()}. */
public float nextFloat() {
return Float.intBitsToFloat(next());
}
/**
* Utility for looking at various distributions generated by
* {@link XorShift}.
*
* @param args
*/
public static void main(final String[] args) {
final XorShift r = new XorShift();
// final Random r = new Random();
final int ntrials = 1000;
{
int ntrue = 0;
for (int i = 0; i < ntrials; i++) {
if (r.nextBoolean())
ntrue++;
}
System.out.println("ntrials=" + ntrials + ", ntrue=" + ntrue);
}
{
/*
* Generate random values and take their running sum.
*
* Note: This does not check for overflow, but it uses long for the
* sum and int for the random values.
*/
long sum = 0;
final int[] a = new int[ntrials];
for (int i = 0; i < ntrials; i++) {
final int n = r.nextInt();
a[i] = n;
sum += n;
}
// The mean of those random values.
final double mean = sum / (double) ntrials;
/*
* Compute the sum of squares of the difference between the random
* values and their mean.
*/
double sse = 0; // sum squared error.
final double[] diffs = new double[ntrials];
for (int i = 0; i < ntrials; i++) {
double d = (mean - (double) a[i]); // difference from mean
d *= d;// squared
diffs[i] = d;
sse += d;
}
final double var = sse / ntrials; // variance.
final double stdev = Math.sqrt(var); // standard deviation.
System.out.println("ntrials=" + ntrials + ", sum=" + sum + ", sse="
+ sse + ", var=" + var + ", stdev=" + stdev);
}
}
}