Home | History | Annotate | Download | only in math
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.math;
     18 
     19 import java.util.Random;
     20 
     21 /** This class implements the xorshift128+ algorithm that is a very fast, top-quality 64-bit pseudo-random number generator. The
     22  * quality of this PRNG is much higher than {@link Random}'s, and its cycle length is 2<sup>128</sup>&nbsp;&minus;&nbsp;1, which
     23  * is more than enough for any single-thread application. More details and algorithms can be found <a
     24  * href="http://xorshift.di.unimi.it/">here</a>.
     25  * <p>
     26  * Instances of RandomXS128 are not thread-safe.
     27  *
     28  * @author Inferno
     29  * @author davebaol */
     30 public class RandomXS128 extends Random {
     31 
     32 	/** Normalization constant for double. */
     33 	private static final double NORM_DOUBLE = 1.0 / (1L << 53);
     34 
     35 	/** Normalization constant for float. */
     36 	private static final double NORM_FLOAT = 1.0 / (1L << 24);
     37 
     38 	/** The first half of the internal state of this pseudo-random number generator. */
     39 	private long seed0;
     40 
     41 	/** The second half of the internal state of this pseudo-random number generator. */
     42 	private long seed1;
     43 
     44 	/** Creates a new random number generator. This constructor sets the seed of the random number generator to a value very likely
     45 	 * to be distinct from any other invocation of this constructor.
     46 	 * <p>
     47 	 * This implementation creates a {@link Random} instance to generate the initial seed. */
     48 	public RandomXS128 () {
     49 		setSeed(new Random().nextLong());
     50 	}
     51 
     52 	/** Creates a new random number generator using a single {@code long} seed.
     53 	 * @param seed the initial seed */
     54 	public RandomXS128 (long seed) {
     55 		setSeed(seed);
     56 	}
     57 
     58 	/** Creates a new random number generator using two {@code long} seeds.
     59 	 * @param seed0 the first part of the initial seed
     60 	 * @param seed1 the second part of the initial seed */
     61 	public RandomXS128 (long seed0, long seed1) {
     62 		setState(seed0, seed1);
     63 	}
     64 
     65 	/** Returns the next pseudo-random, uniformly distributed {@code long} value from this random number generator's sequence.
     66 	 * <p>
     67 	 * Subclasses should override this, as this is used by all other methods. */
     68 	@Override
     69 	public long nextLong () {
     70 		long s1 = this.seed0;
     71 		final long s0 = this.seed1;
     72 		this.seed0 = s0;
     73 		s1 ^= s1 << 23;
     74 		return (this.seed1 = (s1 ^ s0 ^ (s1 >>> 17) ^ (s0 >>> 26))) + s0;
     75 	}
     76 
     77 	/** This protected method is final because, contrary to the superclass, it's not used anymore by the other methods. */
     78 	@Override
     79 	protected final int next (int bits) {
     80 		return (int)(nextLong() & ((1L << bits) - 1));
     81 	}
     82 
     83 	/** Returns the next pseudo-random, uniformly distributed {@code int} value from this random number generator's sequence.
     84 	 * <p>
     85 	 * This implementation uses {@link #nextLong()} internally. */
     86 	@Override
     87 	public int nextInt () {
     88 		return (int)nextLong();
     89 	}
     90 
     91 	/** Returns a pseudo-random, uniformly distributed {@code int} value between 0 (inclusive) and the specified value (exclusive),
     92 	 * drawn from this random number generator's sequence.
     93 	 * <p>
     94 	 * This implementation uses {@link #nextLong()} internally.
     95 	 * @param n the positive bound on the random number to be returned.
     96 	 * @return the next pseudo-random {@code int} value between {@code 0} (inclusive) and {@code n} (exclusive). */
     97 	@Override
     98 	public int nextInt (final int n) {
     99 		return (int)nextLong(n);
    100 	}
    101 
    102 	/** Returns a pseudo-random, uniformly distributed {@code long} value between 0 (inclusive) and the specified value (exclusive),
    103 	 * drawn from this random number generator's sequence. The algorithm used to generate the value guarantees that the result is
    104 	 * uniform, provided that the sequence of 64-bit values produced by this generator is.
    105 	 * <p>
    106 	 * This implementation uses {@link #nextLong()} internally.
    107 	 * @param n the positive bound on the random number to be returned.
    108 	 * @return the next pseudo-random {@code long} value between {@code 0} (inclusive) and {@code n} (exclusive). */
    109 	public long nextLong (final long n) {
    110 		if (n <= 0) throw new IllegalArgumentException("n must be positive");
    111 		for (;;) {
    112 			final long bits = nextLong() >>> 1;
    113 			final long value = bits % n;
    114 			if (bits - value + (n - 1) >= 0) return value;
    115 		}
    116 	}
    117 
    118 	/** Returns a pseudo-random, uniformly distributed {@code double} value between 0.0 and 1.0 from this random number generator's
    119 	 * sequence.
    120 	 * <p>
    121 	 * This implementation uses {@link #nextLong()} internally. */
    122 	@Override
    123 	public double nextDouble () {
    124 		return (nextLong() >>> 11) * NORM_DOUBLE;
    125 	}
    126 
    127 	/** Returns a pseudo-random, uniformly distributed {@code float} value between 0.0 and 1.0 from this random number generator's
    128 	 * sequence.
    129 	 * <p>
    130 	 * This implementation uses {@link #nextLong()} internally. */
    131 	@Override
    132 	public float nextFloat () {
    133 		return (float)((nextLong() >>> 40) * NORM_FLOAT);
    134 	}
    135 
    136 	/** Returns a pseudo-random, uniformly distributed {@code boolean } value from this random number generator's sequence.
    137 	 * <p>
    138 	 * This implementation uses {@link #nextLong()} internally. */
    139 	@Override
    140 	public boolean nextBoolean () {
    141 		return (nextLong() & 1) != 0;
    142 	}
    143 
    144 	/** Generates random bytes and places them into a user-supplied byte array. The number of random bytes produced is equal to the
    145 	 * length of the byte array.
    146 	 * <p>
    147 	 * This implementation uses {@link #nextLong()} internally. */
    148 	@Override
    149 	public void nextBytes (final byte[] bytes) {
    150 		int n = 0;
    151 		int i = bytes.length;
    152 		while (i != 0) {
    153 			n = i < 8 ? i : 8; // min(i, 8);
    154 			for (long bits = nextLong(); n-- != 0; bits >>= 8)
    155 				bytes[--i] = (byte)bits;
    156 		}
    157 	}
    158 
    159 	/** Sets the internal seed of this generator based on the given {@code long} value.
    160 	 * <p>
    161 	 * The given seed is passed twice through a hash function. This way, if the user passes a small value we avoid the short
    162 	 * irregular transient associated with states having a very small number of bits set.
    163 	 * @param seed a nonzero seed for this generator (if zero, the generator will be seeded with {@link Long#MIN_VALUE}). */
    164 	@Override
    165 	public void setSeed (final long seed) {
    166 		long seed0 = murmurHash3(seed == 0 ? Long.MIN_VALUE : seed);
    167 		setState(seed0, murmurHash3(seed0));
    168 	}
    169 
    170 	/** Sets the internal state of this generator.
    171 	 * @param seed0 the first part of the internal state
    172 	 * @param seed1 the second part of the internal state */
    173 	public void setState (final long seed0, final long seed1) {
    174 		this.seed0 = seed0;
    175 		this.seed1 = seed1;
    176 	}
    177 
    178 	/**
    179 	 * Returns the internal seeds to allow state saving.
    180 	 * @param seed must be 0 or 1, designating which of the 2 long seeds to return
    181 	 * @return the internal seed that can be used in setState
    182 	 */
    183 	public long getState(int seed) {
    184 		return seed == 0 ? seed0 : seed1;
    185 	}
    186 
    187 	private final static long murmurHash3 (long x) {
    188 		x ^= x >>> 33;
    189 		x *= 0xff51afd7ed558ccdL;
    190 		x ^= x >>> 33;
    191 		x *= 0xc4ceb9fe1a85ec53L;
    192 		x ^= x >>> 33;
    193 
    194 		return x;
    195 	}
    196 
    197 }
    198