Class XoRoRNG

java.lang.Object
squidpony.squidmath.XoRoRNG
All Implemented Interfaces:
Serializable, RandomnessSource

public final class XoRoRNG
extends Object
implements RandomnessSource, Serializable
A port of Blackman and Vigna's xoroshiro128+ generator; should be very fast and produce medium-quality output. Testing shows it is within 5% the speed of LightRNG, sometimes faster and sometimes slower, and has a larger period. It's called XoRo because it involves Xor as well as Rotate operations on the 128-bit pseudo-random state. Note that xoroshiro128+ fails some statistical quality tests systematically, and fails others often; if this could be a concern for you, DiverRNG, which is the default for RNG, will be faster and won't fail tests, and though its period is shorter, it would still take years to exhaust on one core generating only random numbers.
LightRNG is also very fast, but relative to XoRoRNG it has a significantly shorter period (the amount of random numbers it will go through before repeating), at pow(2, 64) as opposed to XoRoRNG's pow(2, 128) - 1, but LightRNG also allows the current RNG state to be retrieved and altered with getState() and setState(). For most cases, you should decide between DiverRNG, LightRNG, XoRoRNG, and other RandomnessSource implementations based on your needs for period length and state manipulation (DiverRNG is also used internally by almost all StatefulRNG objects). You might want significantly less predictable random results, which IsaacRNG can provide, along with a large period. You may want a very long period of random numbers, which would suggest LongPeriodRNG as a good choice or MersenneTwister as a potential alternative. You may want better performance on 32-bit machines or on GWT, where Starfish32RNG is currently the best choice most of the time, and Lathe32RNG can be faster but has slightly worse quality (both of these generators use a 32-bit variant on the xoroshiro algorithm but change the output scrambler). These all can generate pseudo-random numbers in a handful of nanoseconds (with the key exception of 64-bit generators being used on GWT, where they may take more than 100 nanoseconds per number), so unless you need a LOT of random numbers in a hurry, they'll probably all be fine on performance. You may want to decide on the special features of a generator, indicated by implementing StatefulRandomness if their state can be read and written to, and/or SkippingRandomness if sections in the generator's sequence can be skipped in long forward or backward leaps.
Original version here.
Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
Author:
Sebastiano Vigna, David Blackman, Tommy Ettinger (if there's a flaw, use SquidLib's issues and don't bother Vigna or Blackman, it's probably a mistake in SquidLib's implementation)
See Also:
Serialized Form
  • Constructor Summary

    Constructors 
    Constructor Description
    XoRoRNG()
    Creates a new generator seeded using four calls to Math.random().
    XoRoRNG​(long seed)
    Constructs this XoRoRNG by dispersing the bits of seed using setSeed(long) across the two parts of state this has.
    XoRoRNG​(long stateA, long stateB)
    Constructs this XoRoRNG by calling setSeed(long, long) on the arguments as given; see that method for the specific details (stateA and stateB are kept as-is unless they are both 0).
  • Method Summary

    Modifier and Type Method Description
    XoRoRNG copy()
    Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the copy, both will generate the same sequence of random numbers from the point copy() was called.
    boolean equals​(Object o)  
    long getStateA()
    Gets the first component of this generator's two-part state, as a long.
    long getStateB()
    Gets the second component of this generator's two-part state, as a long.
    int hashCode()  
    int next​(int bits)
    Using this method, any algorithm that might use the built-in Java Random can interface with this randomness source.
    boolean nextBoolean()  
    void nextBytes​(byte[] bytes)  
    double nextDouble()  
    float nextFloat()  
    int nextInt()
    Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
    int nextInt​(int bound)
    Exclusive on the outer bound; the inner bound is 0.
    int nextInt​(int inner, int outer)
    Inclusive lower, exclusive upper.
    long nextLong()
    Using this method, any algorithm that needs to efficiently generate more than 32 bits of random data can interface with this randomness source.
    long nextLong​(long bound)
    Exclusive on the outer bound; the inner bound is 0.
    long nextLong​(long inner, long outer)
    Inclusive inner, exclusive outer; both inner and outer can be positive or negative.
    void setSeed​(long seed)
    Sets the seed of this generator using one long, running that through LightRNG's algorithm twice to get the state.
    void setSeed​(long stateA, long stateB)
    Sets the seed of this generator using two longs, using them without changes unless both are 0 (then it makes the state variable corresponding to stateA 1 instead).
    String toString()  

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
  • Constructor Details

    • XoRoRNG

      public XoRoRNG()
      Creates a new generator seeded using four calls to Math.random().
    • XoRoRNG

      public XoRoRNG​(long seed)
      Constructs this XoRoRNG by dispersing the bits of seed using setSeed(long) across the two parts of state this has.
      Parameters:
      seed - a long that won't be used exactly, but will affect both components of state
    • XoRoRNG

      public XoRoRNG​(long stateA, long stateB)
      Constructs this XoRoRNG by calling setSeed(long, long) on the arguments as given; see that method for the specific details (stateA and stateB are kept as-is unless they are both 0).
      Parameters:
      stateA - the number to use as the first part of the state; this will be 1 instead if both seeds are 0
      stateB - the number to use as the second part of the state
  • Method Details

    • next

      public final int next​(int bits)
      Description copied from interface: RandomnessSource
      Using this method, any algorithm that might use the built-in Java Random can interface with this randomness source.
      Specified by:
      next in interface RandomnessSource
      Parameters:
      bits - the number of bits to be returned
      Returns:
      the integer containing the appropriate number of bits
    • nextLong

      public final long nextLong()
      Description copied from interface: RandomnessSource
      Using this method, any algorithm that needs to efficiently generate more than 32 bits of random data can interface with this randomness source. Get a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive).
      Specified by:
      nextLong in interface RandomnessSource
      Returns:
      a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive)
    • copy

      public XoRoRNG copy()
      Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to copy the state so it isn't shared, usually, and produce a new value with the same exact state.
      Specified by:
      copy in interface RandomnessSource
      Returns:
      a copy of this RandomnessSource
    • nextInt

      public int nextInt()
      Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
      Returns:
      any int, all 32 bits are random
    • nextInt

      public int nextInt​(int bound)
      Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive result.
      Parameters:
      bound - the outer exclusive bound; may be positive or negative
      Returns:
      a random int between 0 (inclusive) and bound (exclusive)
    • nextInt

      public int nextInt​(int inner, int outer)
      Inclusive lower, exclusive upper.
      Parameters:
      inner - the inner bound, inclusive, can be positive or negative
      outer - the outer bound, exclusive, should be positive, should usually be greater than inner
      Returns:
      a random int that may be equal to inner and will otherwise be between inner and outer
    • nextLong

      public long nextLong​(long bound)
      Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive result.
      Parameters:
      bound - the outer exclusive bound; may be positive or negative
      Returns:
      a random long between 0 (inclusive) and bound (exclusive)
    • nextLong

      public long nextLong​(long inner, long outer)
      Inclusive inner, exclusive outer; both inner and outer can be positive or negative.
      Parameters:
      inner - the inner bound, inclusive, can be positive or negative
      outer - the outer bound, exclusive, can be positive or negative and may be greater than or less than inner
      Returns:
      a random long that may be equal to inner and will otherwise be between inner and outer
    • nextDouble

      public double nextDouble()
    • nextFloat

      public float nextFloat()
    • nextBoolean

      public boolean nextBoolean()
    • nextBytes

      public void nextBytes​(byte[] bytes)
    • setSeed

      public void setSeed​(long seed)
      Sets the seed of this generator using one long, running that through LightRNG's algorithm twice to get the state.
      Parameters:
      seed - the number to use as the seed
    • setSeed

      public void setSeed​(long stateA, long stateB)
      Sets the seed of this generator using two longs, using them without changes unless both are 0 (then it makes the state variable corresponding to stateA 1 instead).
      Parameters:
      stateA - the number to use as the first part of the state; this will be 1 instead if both seeds are 0
      stateB - the number to use as the second part of the state
    • getStateA

      public long getStateA()
      Gets the first component of this generator's two-part state, as a long. This can be 0 on its own, but will never be 0 at the same time as the other component of state, getStateB(). You can set the state with two exact values using setSeed(long, long), but the alternative overload setSeed(long) won't use the state without changing it (it needs to cover 128 bits with a 64-bit value).
      Returns:
      the first component of this generator's state
    • getStateB

      public long getStateB()
      Gets the second component of this generator's two-part state, as a long. This can be 0 on its own, but will never be 0 at the same time as the other component of state, getStateA(). You can set the state with two exact values using setSeed(long, long), but the alternative overload setSeed(long) won't use the state without changing it (it needs to cover 128 bits with a 64-bit value).
      Returns:
      the second component of this generator's state
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • equals

      public boolean equals​(Object o)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object