/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/licenses/publicdomain
 */

//package java.util;
import java.io.*;
import java.util.*;

/**
 * A faster variant of java.util.Random. Instances of this class
 * generate high-quality random numbers that pass the "Diehard" test,
 * but generation methods are generally faster that those of
 * <tt>java.util.Random</tt> because they use a cheaper
 * non-thread-safe generation algorithm. Additionally, this class does
 * not define <tt>protected</tt> extension methods, and does not
 * support the <tt>Random.nextGaussian</tt> method.
 * 
 */
public class XRandom extends java.util.Random {
    static final long serialVersionUID = 3903584987241029169L;

    /*
     * Adapted from Panneton & L'Ecuyer 
     * "On the Xorshift random number generators", 2004.
     */

    private int s0, s1, s2, s3, s4, s5, s6, s7;

    /**
     * Creates a new random number generator. This constructor sets
     * the seed of the random number generator to a value very likely
     * to be distinct from any other invocation of this constructor.
     */
    public XRandom() { 
        super(); 
    }

    /** 
     * Creates a new random number generator using a single 
     * <code>long</code> seed:
     *
     * @param   seed   the initial seed.
     */
    public XRandom(long seed) {
        super(seed);
    }

    /**
     * Sets the seed of this random number generator using a single 
     * <code>long</code> seed. The general contract of <tt>setSeed</tt> 
     * is that it alters the state of this random number generator
     * object so as to be in exactly the same state as if it had just 
     * been created with the argument <tt>seed</tt> as a seed. 
     * @param   seed   the initial seed.
     */
    public void setSeed(long seed) {
        super.setSeed(seed);
        int a = s0 = (int)(seed & 0xffffffff);
        int b = s1 = (int)(seed >>> 32);
        // Use simple xorshift mixed with arbitrary seeds for s2-s7
        a ^= (a ^= (a ^= a << 13) >>> 17) << 5; 
        s2 = a + -715159705;
        b ^= (b ^= (b ^= b << 13) >>> 17) << 5; 
        s3 = b + 273326509;
        a ^= (a ^= (a ^= a << 13) >>> 17) << 5; 
        s4 = a + -1831433054;
        b ^= (b ^= (b ^= b << 13) >>> 17) << 5; 
        s5 = b + 0x61c88647;
        a ^= (a ^= (a ^= a << 13) >>> 17) << 5; 
        s6 = a + 362436069;
        b ^= (b ^= (b ^= b << 13) >>> 17) << 5; 
        if ( (s7 = b + 521288629) == 0)
             s7 = 1; // ensure at least one nonzero
    }

    /**
     * Generates the next pseudorandom number. 
     */
    protected final int next(int bits) {  
        int x7 = s7;
        s7 = s6; 
        s6 = s5; 
        int x4 = s5 = s4;
        int x3 = s4 = s3;
        s3 = s2; 
        int x1 = s2 = s1;
        int x0 = s1 = s0;
        x0 ^= (x0 >>>  7);
        x7 ^= (x7 <<  13);
        return (s0 = ((x7 ^ (x7 <<   9)) ^
                      (x4 ^ (x4 <<   7)) ^
                      (x3 ^ (x3 >>>  3)) ^
                      (x1 ^ (x1 >>> 10)) ^
                      (x0 ^ (x0 <<  24)))) >>> (32 - bits);
    }


}     
