Package squidpony.squidmath
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
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
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 usingsetSeed(int)
across the four parts of state this has.XoshiroStarPhi32RNG(int stateA, int stateB, int stateC, int stateD)
Constructs this XoshiroStarPhi32RNG by callingsetState(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 usingsetSeed(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()
-
Constructor Details
-
XoshiroStarPhi32RNG
public XoshiroStarPhi32RNG()Creates a new generator seeded using four calls to Math.random(). -
XoshiroStarPhi32RNG
Constructs this XoshiroStarPhi32RNG by dispersing the bits of seed usingsetSeed(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
Constructs this XoshiroStarPhi32RNG by dispersing the bits of seed usingsetSeed(long)
across the four parts of state this has.- Parameters:
seed
- a long that will be split across all components of state
-
XoshiroStarPhi32RNG
Constructs this XoshiroStarPhi32RNG by callingsetState(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 0stateB
- the number to use as the second part of the statestateC
- the number to use as the third part of the statestateD
- the number to use as the fourth part of the state
-
-
Method Details
-
next
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 interfaceRandomnessSource
- Parameters:
bits
- the number of bits to be returned- Returns:
- the integer containing the appropriate number of bits
-
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
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 interfaceRandomnessSource
- 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 interfaceRandomnessSource
- Returns:
- a copy of this RandomnessSource
-
setSeed
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
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
-
setStateA
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 usesetState(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
-
setStateB
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 usesetState(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
-
setStateC
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 usesetState(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
-
setStateD
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 usesetState(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
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 intstateC
- any intstateD
- any int
-
toString
-
equals
-
hashCode
-