/*
 * 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.*;

/**
 * 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 XSRandom implements java.io.Serializable {
    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 XSRandom() { this(++seedUniquifier + System.nanoTime()); }
    private static volatile long seedUniquifier = 8682522807148012L;

    /** 
     * Creates a new random number generator using a single 
     * <code>long</code> seed:
     *
     * @param   seed   the initial seed.
     */
    public XSRandom(long seed) {
        setSeed(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) {
        s0 = (int)(seed & 0xffffffff);
        s1 = (int)(seed >>> 32);
        // Other seeds randomly selected from other published
        // seeds for xorshift generators
        s2 = -715159705;
        s3 = 273326509;
        s4 = -1831433054;
        s5 = 123456789;
        s6 = 362436069;
        s7 = 521288629;
    }

    /**
     * Returns the next pseudorandom, uniformly distributed <code>int</code>
     * value from this random number generator's sequence. The general 
     * contract of <tt>nextInt</tt> is that one <tt>int</tt> value is 
     * pseudorandomly generated and returned. All 2<font size="-1"><sup>32
     * </sup></font> possible <tt>int</tt> values are produced with 
     * (approximately) equal probability. 
     *
     * @return  the next pseudorandom, uniformly distributed <code>int</code>
     *          value from this random number generator's sequence.
     */

    public int nextInt() {  
        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;
        int u0 = x0 ^ (x0 >>> 7);
        int u7 = x7 ^ (x7 << 13);
        return s0 = ((u7 ^ (u7 << 9)) ^
                     (x4 ^ (x4 << 7)) ^
                     (x3 ^ (x3 >>> 3)) ^
                     (x1 ^ (x1 >>> 10)) ^
                     (u0 ^ (u0 << 24)));
    }


    /**
     * Generates random bytes and places them into a user-supplied 
     * byte array.  The number of random bytes produced is equal to 
     * the length of the byte array.
     * 
     * @param bytes  the non-null byte array in which to put the 
     *               random bytes.
     */
    public void nextBytes(byte[] bytes) {
        for (int i = 0; i < bytes.length; ++i) 
            bytes[i] = (byte)(nextInt() & 0xff);
    }            

    /**
     * Returns a pseudorandom, uniformly distributed <tt>int</tt> value
     * between 0 (inclusive) and the specified value (exclusive), drawn from
     * this random number generator's sequence.  The general contract of
     * <tt>nextInt</tt> is that one <tt>int</tt> value in the specified range
     * is pseudorandomly generated and returned.  All <tt>n</tt> possible
     * <tt>int</tt> values are produced with (approximately) equal
     * probability.  
     * @param n the bound on the random number to be returned.  Must be
     *	      positive.
     * @return  a pseudorandom, uniformly distributed <tt>int</tt>
     *          value between 0 (inclusive) and n (exclusive).
     * @exception IllegalArgumentException n is not positive.
     */

    public int nextInt(int n) {
        if (n <= 0)
            throw new IllegalArgumentException("n must be positive");
        if ((n & (n - 1)) == 0)  // if a power of 2, just mask
            return (n - 1) & nextInt();

        for (;;) {
            int bits = nextInt() & 0x7fffffff;
            int val = bits % n;
            if (bits - val + (n-1) >= 0)
                return val;
        }
    }

    /**
     * Returns the next pseudorandom, uniformly distributed <code>long</code>
     * value from this random number generator's sequence. The general 
     * contract of <tt>nextLong</tt> is that one long value is pseudorandomly 
     * generated and returned. All 2<font size="-1"><sup>64</sup></font> 
     * possible <tt>long</tt> values are produced with (approximately) equal 
     * probability. 
     *
     * @return  the next pseudorandom, uniformly distributed <code>long</code>
     *          value from this random number generator's sequence.
     */
    public long nextLong() {
        return ((long)(nextInt()) << 32) + nextInt();
    }

    /**
     * Returns the next pseudorandom, uniformly distributed
     * <code>boolean</code> value from this random number generator's
     * sequence. The general contract of <tt>nextBoolean</tt> is that one
     * <tt>boolean</tt> value is pseudorandomly generated and returned.  The
     * values <code>true</code> and <code>false</code> are produced with
     * (approximately) equal probability. 
     * @return  the next pseudorandom, uniformly distributed
     *          <code>boolean</code> value from this random number generator's
     *		sequence.
     * @since 1.2
     */
    public boolean nextBoolean() {
        return (nextInt() & 1) != 0;
    }

    /**
     * Returns the next pseudorandom, uniformly distributed <code>float</code>
     * value between <code>0.0</code> and <code>1.0</code> from this random
     * number generator's sequence. <p>
     * The general contract of <tt>nextFloat</tt> is that one <tt>float</tt> 
     * value, chosen (approximately) uniformly from the range <tt>0.0f</tt> 
     * (inclusive) to <tt>1.0f</tt> (exclusive), is pseudorandomly
     * generated and returned. All 2<font size="-1"><sup>24</sup></font> 
     * possible <tt>float</tt> values of the form 
     * <i>m&nbsp;x&nbsp</i>2<font size="-1"><sup>-24</sup></font>, where 
     * <i>m</i> is a positive integer less than 2<font size="-1"><sup>24</sup>
     * </font>, are produced with (approximately) equal probability. 
     * @return  the next pseudorandom, uniformly distributed <code>float</code>
     *          value between <code>0.0</code> and <code>1.0</code> from this
     *          random number generator's sequence.
     */
    public float nextFloat() {
        return (nextInt() & 0xffffff) / ((float)(1 << 24));
    }

    /**
     * Returns the next pseudorandom, uniformly distributed 
     * <code>double</code> value between <code>0.0</code> and
     * <code>1.0</code> from this random number generator's sequence. <p>
     * The general contract of <tt>nextDouble</tt> is that one 
     * <tt>double</tt> value, chosen (approximately) uniformly from the 
     * range <tt>0.0d</tt> (inclusive) to <tt>1.0d</tt> (exclusive), is 
     * pseudorandomly generated and returned. All 
     * 2<font size="-1"><sup>53</sup></font> possible <tt>float</tt> 
     * values of the form <i>m&nbsp;x&nbsp;</i>2<font size="-1"><sup>-53</sup>
     * </font>, where <i>m</i> is a positive integer less than 
     * 2<font size="-1"><sup>53</sup></font>, are produced with 
     * (approximately) equal probability. 
     *
     * @return  the next pseudorandom, uniformly distributed 
     *          <code>double</code> value between <code>0.0</code> and
     *          <code>1.0</code> from this random number generator's sequence.
     */
    public double nextDouble() {
        return (nextLong() & 0x001fffffffffffffL) / ((double)(1L << 53));
    }

}     
