Class XoshiroStarPhi32RNG

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

public final class XoshiroStarPhi32RNG
extends Object
implements RandomnessSource, Serializable
A modification of Blackman and Vigna's xoshiro128 generator with a different "scrambler" than the default; this generator has four 32-bit states and passes at least 32TB of PractRand (with one "unusual" anomaly at 4TB). It is four-dimensionally equidistributed, which is an uncommon feature of a PRNG, and means every output is equally likely not just when one value is generated with nextInt(), but also that when up to four 32-bit values are generated and treated as up to a 128-bit output, then all possible 128-bit outputs are equally likely (with the exception of the 128-bit value 0x9E3779BD9E3779BD9E3779BD9E3779BD, which won't ever be generated as a group even though 0x9E3779BD can occur up to three times in four results). The scrambler simply multiplies a state variable by 31, rotates that value left by 23, and adds a number obtained from the golden ratio, phi (0x9E3779BD). It may have all sorts of issues since this scrambler hasn't been analyzed much, but 128 bits of state help make most issues less severe, and the same scrambler works well for xoroshiro with 32-bit states (used in Starfish32RNG). A clear known flaw is that if you subtract the same golden-ratio-based number from each result, the resulting modified generator will quickly fail binary matrix rank tests. This could be ameliorated by employing a fifth state variable that increments in a Weyl sequence, which is what Oriole32RNG does, and adding that instead of the golden ratio, though this would eliminate the 4-dimensional equidistribution. XoshiroStarPhi32RNG is optimized for GWT, like Lathe32RNG and Starfish32RNG, which means any non-bitwise math in the source is followed by bitwise math later, and this sometimes can result in obtuse-looking code along the lines of int foo = bar + 0x9E3779BD | 0;.
This generator seems to be a little faster than xoshiro with the StarStar scrambler, while offering the same period and distribution. It does not have one group of vulnerabilities held by the "StarStar" scrambler, where multiplying the result by numbers even somewhat similar to the modulus-2-to-the-32 multiplicative inverse of the last multiplier used in the StarStar scrambler usually results in a binary rank failure in as little as 512MB of PractRand testing. As far as I can tell, that failure occurs in the StarStar version whenever the output is reliably multiplied by an integer where the last byte is 0x39 (or 57 in decimal), additionally affects at least some multipliers that have their last 7 bits equal to 0b0111001 (the same as in 0x39 before, but requiring only 7 bits to be equivalent), and this seems to be related to the choice of rotation amount (the StarStar scrambler rotates by 7 places). This generator does have a different vulnerability when a specific number is subtracted from the output each time (for the purpose of transparency, 0x9E3779BD). This flaw may occur with similar subtracted numbers as well, probably affecting any subtrahends with a low Hamming distance from 0x9E3779BD, considering less-significant bits as more relevant to the distance than more-significant bits.
Original version here for xoshiro128**, by Sebastiano Vigna and David Blackman.
Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) StarPhi scrambler written 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
    XoshiroStarPhi32RNG()
    Creates a new generator seeded using four calls to Math.random().
    XoshiroStarPhi32RNG​(int seed)
    Constructs this XoshiroStarPhi32RNG by dispersing the bits of seed using setSeed(int) across the four parts of state this has.
    XoshiroStarPhi32RNG​(int stateA, int stateB, int stateC, int stateD)
    Constructs this XoshiroStarPhi32RNG by calling setState(int, int, int, int) on stateA and stateB as given; see that method for the specific details (the states are kept as-is unless they are all 0).
    XoshiroStarPhi32RNG​(long seed)
    Constructs this XoshiroStarPhi32RNG by dispersing the bits of seed using setSeed(long) across the four parts of state this has.
  • Method Summary

    Modifier and Type Method Description
    XoshiroStarPhi32RNG 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)  
    int getStateA()  
    int getStateB()  
    int getStateC()  
    int getStateD()  
    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 a GWT-compatible variant of SplitMix32 four times to get four ints of state, all guaranteed to be different.
    void setSeed​(long seed)
    Sets the state of this generator using one long, running it through a GWT-compatible variant of SplitMix32 four times to get four ints of state, guaranteed to repeat a state no more than two times.
    void setState​(int stateA, int stateB, int stateC, int stateD)
    Sets the current internal state of this XoshiroStarPhi32RNG with four ints, where each can be any int unless they are all 0 (which will be treated as if stateA is 1 and the rest are 0).
    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.
    void setStateC​(int stateC)
    Sets the third part of the state to the given int.
    void setStateD​(int stateD)
    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

    • XoshiroStarPhi32RNG

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

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

      public XoshiroStarPhi32RNG​(long seed)
      Constructs this XoshiroStarPhi32RNG by dispersing the bits of seed using setSeed(long) across the four parts of state this has.
      Parameters:
      seed - a long that will be split across all components of state
    • XoshiroStarPhi32RNG

      public XoshiroStarPhi32RNG​(int stateA, int stateB, int stateC, int stateD)
      Constructs this XoshiroStarPhi32RNG by calling setState(int, int, int, int) on stateA and stateB as given; see that method for the specific details (the states are kept as-is unless they are all 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
      stateC - the number to use as the third part of the state
      stateD - the number to use as the fourth 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

      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
    • setSeed

      public void setSeed​(int seed)
      Sets the state of this generator using one int, running it through a GWT-compatible variant of SplitMix32 four times to get four ints of state, all guaranteed to be different.
      Parameters:
      seed - the int to use to produce this generator's states
    • setSeed

      public void setSeed​(long seed)
      Sets the state of this generator using one long, running it through a GWT-compatible variant of SplitMix32 four times to get four ints of state, guaranteed to repeat a state no more than two times.
      Parameters:
      seed - the long to use to produce this generator's states
    • 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 this would set all states to be 0, this will set stateA to 1 instead. Usually, you should use setState(int, int, int, int) to set all four states at once, but the result will be the same if you set the four states individually.
      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 this would set all states to be 0, this will set stateA to 1 in addition to setting stateB to 0. Usually, you should use setState(int, int, int, int) to set all four states at once, but the result will be the same if you set the four states individually.
      Parameters:
      stateB - any int
    • getStateC

      public int getStateC()
    • setStateC

      public void setStateC​(int stateC)
      Sets the third part of the state to the given int. As a special case, if the parameter is 0 and this would set all states to be 0, this will set stateA to 1 in addition to setting stateC to 0. Usually, you should use setState(int, int, int, int) to set all four states at once, but the result will be the same if you set the four states individually.
      Parameters:
      stateC - any int
    • getStateD

      public int getStateD()
    • setStateD

      public void setStateD​(int stateD)
      Sets the second part of the state to the given int. As a special case, if the parameter is 0 and this would set all states to be 0, this will set stateA to 1 in addition to setting stateD to 0. Usually, you should use setState(int, int, int, int) to set all four states at once, but the result will be the same if you set the four states individually.
      Parameters:
      stateD - any int
    • setState

      public void setState​(int stateA, int stateB, int stateC, int stateD)
      Sets the current internal state of this XoshiroStarPhi32RNG with four ints, where each can be any int unless they are all 0 (which will be treated as if stateA is 1 and the rest are 0).
      Parameters:
      stateA - any int (if all parameters are both 0, this will be treated as 1)
      stateB - any int
      stateC - any int
      stateD - any int
    • 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