Class Lathe32RNG

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

public final class Lathe32RNG
extends Object
implements StatefulRandomness, Serializable
A modification of Blackman and Vigna's xoroshiro128+ generator using two 32-bit ints of state instead of two 64-bit longs, as well as modifying the output with two additional operations on the existing state; this is both the fastest generator on GWT I have found without statistical failures, and a StatefulRandomness. This algorithm is sometimes called xoroshiro64++ and is mentioned in this paper by Blackman and Vigna (in section 10.7; the 'r' constant is 10, which seems to usually do well on those same authors' HWD test). Lathe32RNG passes the full 32TB battery of PractRand's statistical tests, and does so with 3 "unusual" anomalies, no more-serious anomalies, and no failures. It isn't especially likely that this can pass much more than 32TB of testing (judging by related attempts, 128TB would be a likely failure point), but because multi-threaded code is either impossible or impractical on GWT, actually using that many numbers would take a very long time (generating them would take about 3 nanoseconds per int, but it would take more than 2 to the 43 ints to start to approach detectable failures, and detecting the failures in anything but the worst case would take more than a day). In statistical testing, xoroshiro with the '+' scrambler always fails some binary matrix rank tests, but smaller-state versions fail other tests as well. The changes Lathe makes apply only to the output of xoroshiro64+ (in Vigna's and Blackman's terms, they are a scrambler), not its well-tested state transition, and these changes eliminate all statistical failures on 32TB of tested data, avoiding the failures the small-state variant of xoroshiro suffers on BinaryRank, BCFN, DC6, and FPF. It avoids multiplication (except in setSeed(int), which needs to use a different algorithm to spread a seed out across twice as much state), like xoroshiro and much of the xorshift family of generators, and any arithmetic it performs is safe for GWT. Lathe makes an extremely small set of changes to xoroshiro64+, running xoroshiro64+ as normal (holding on to the result as well as the initial stateA, called s[0] in the original xoroshiro code) and then bitwise-rotating the result and adding the (now previous) stateA. Although no bits of xoroshiro are truly free of artifacts, some are harder to find issues with (see this article by PCG-Random's author for more detail). It is unclear if the changes made here would improve the larger-state version, but they probably would help to some extent with at least the binary rank failures. The period is identical to xoroshiro with two 32-bit states, at 0xFFFFFFFFFFFFFFFF or 2 to the 64 minus 1. This generator is slightly slower than xoroshiro without the small extra steps applied to the output, but about as fast as Oriole32RNG (this has a smaller period and smaller state but implements StatefulRandomness). Some simple tests on bytes instead of ints showed that the technique used here produces all possible bytes with equal frequency when run on bytes as state, with the exception of producing 0 one less time (because both states cannot be 0 at the same time). This gives some confidence for the algorithm used here, but the algorithm is still only one-dimensionally equidistributed (the same as xoroshiro128+), meaning it produces some pairs of ints more frequently than others. You may want to prefer Starfish32RNG, which is the current default in GWTRNG, because it can produce all pairs of ints and all longs (except one), and has noticeably better quality even on some short generated sequences.
The name comes from a tool that rotates very quickly to remove undesirable parts of an object, akin to how this generator adds an extra bitwise rotation to xoroshiro64+ to remove several types of undesirable statistical failures from its test results.
Original version here for xorshiro128+; this version uses different constants by the same author, Sebastiano Vigna. It does not use the constants used in other xoroshiro64 scrambled generators, instead using similar-quality ones from the earlier constants link.
Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) Ported and modified in 2018 by Tommy Ettinger
Author:
Sebastiano Vigna, David Blackman, Tommy Ettinger (if there's a flaw, use SquidLib's or Sarong'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
    Lathe32RNG()
    Creates a new generator seeded using two calls to Math.random().
    Lathe32RNG​(int seed)
    Constructs this Lathe32RNG by dispersing the bits of seed using setSeed(int) across the two parts of state this has.
    Lathe32RNG​(int stateA, int stateB)
    Constructs this Lathe32RNG by calling setState(int, int) on stateA and stateB as given; see that method for the specific details (stateA and stateB are kept as-is unless they are both 0).
    Lathe32RNG​(long seed)
    Constructs this Lathe32RNG by splitting the given seed across the two parts of state this has with setState(long).
  • Method Summary

    Modifier and Type Method Description
    Lathe32RNG 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 getState()
    Get the current internal state of the StatefulRandomness as a long.
    int getStateA()  
    int getStateB()  
    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.
    int nextInt()
    Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
    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.
    void setSeed​(int seed)
    Sets the state of this generator using one int, running it through Zog32RNG's algorithm two times to get two ints.
    void setState​(int stateA, int stateB)
    Sets the current internal state of this Lathe32RNG with three ints, where stateA and stateB can each be any int unless they are both 0 (which will be treated as if stateA is 1 and stateB is 0).
    void setState​(long state)
    Set the current internal state of this StatefulRandomness with a long.
    void setStateA​(int stateA)
    Sets the first part of the state to the given int.
    void setStateB​(int stateB)
    Sets the second part of the state to the given int.
    String toString()  

    Methods inherited from class java.lang.Object

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

    • Lathe32RNG

      public Lathe32RNG()
      Creates a new generator seeded using two calls to Math.random().
    • Lathe32RNG

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

      public Lathe32RNG​(long seed)
      Constructs this Lathe32RNG by splitting the given seed across the two parts of state this has with setState(long).
      Parameters:
      seed - a long that will be split across both components of state
    • Lathe32RNG

      public Lathe32RNG​(int stateA, int stateB)
      Constructs this Lathe32RNG by calling setState(int, int) on stateA and stateB 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
    • nextInt

      public final 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
    • 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 Lathe32RNG 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
      Specified by:
      copy in interface StatefulRandomness
      Returns:
      a copy of this RandomnessSource
    • setSeed

      public void setSeed​(int seed)
      Sets the state of this generator using one int, running it through Zog32RNG's algorithm two times to get two ints. If the states would both be 0, state A is assigned 1 instead.
      Parameters:
      seed - the int to use to produce this generator's state
    • getStateA

      public int getStateA()
    • setStateA

      public void setStateA​(int stateA)
      Sets the first part of the state to the given int. As a special case, if the parameter is 0 and stateB is already 0, this will set stateA to 1 instead, since both states cannot be 0 at the same time. Usually, you should use setState(int, int) to set both states at once, but the result will be the same if you call setStateA() and then setStateB() or if you call setStateB() and then setStateA().
      Parameters:
      stateA - any int
    • getStateB

      public int getStateB()
    • setStateB

      public void setStateB​(int stateB)
      Sets the second part of the state to the given int. As a special case, if the parameter is 0 and stateA is already 0, this will set stateA to 1 and stateB to 0, since both cannot be 0 at the same time. Usually, you should use setState(int, int) to set both states at once, but the result will be the same if you call setStateA() and then setStateB() or if you call setStateB() and then setStateA().
      Parameters:
      stateB - any int
    • setState

      public void setState​(int stateA, int stateB)
      Sets the current internal state of this Lathe32RNG with three ints, where stateA and stateB can each be any int unless they are both 0 (which will be treated as if stateA is 1 and stateB is 0).
      Parameters:
      stateA - any int (if stateA and stateB are both 0, this will be treated as 1)
      stateB - any int
    • getState

      public long getState()
      Get the current internal state of the StatefulRandomness as a long.
      Specified by:
      getState in interface StatefulRandomness
      Returns:
      the current internal state of this object.
    • setState

      public void setState​(long state)
      Set the current internal state of this StatefulRandomness with a long.
      Specified by:
      setState in interface StatefulRandomness
      Parameters:
      state - a 64-bit long. You should avoid passing 0; this implementation will treat it as 1.
    • 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