Package squidpony.squidmath
Class Starfish32RNG
java.lang.Object
squidpony.squidmath.Starfish32RNG
- All Implemented Interfaces:
Serializable
,RandomnessSource
,StatefulRandomness
public final class Starfish32RNG extends Object implements StatefulRandomness, Serializable
A modification of Blackman and Vigna's xoroshiro64** generator; uses two 32-bit ints of state like
This avoids an issue in xoroshiro** generators where many multipliers, when applied to the output of a xoroshiro** generator, will cause the modified output to rapidly fail binary matrix rank tests. It has its own issue where subtracting
The name comes from the single Star operation used (relative to the StarStar scrambler) and the addition of the golden ratio, or phi, which sounds close to fish.
Original version here for xoroshiro64**.
Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) Ported and modified in 2018 by Tommy Ettinger
Lathe32RNG
but has better equidistribution. Starfish is 2-dimensionally equidistributed, so it can return all long values except
for one, while Lathe is 1-dimensionally equidistributed so it can return all int values but not all longs. Starfish
passes all 32TB of PractRand's statistical tests, and does so with no anomalies and no failures (the best possible
outcome). It also passes at least one seed of TestU01's BigCrush in both forward and reverse with no failures. In
statistical testing, xoroshiro128+ always fails some binary matrix rank tests, but that uses a pair of 64-bit states,
and when the states are reduced to 32-bits, these small-word versions fail other tests as well. Starfish uses a
simpler variant on xoroshiro64** that reduces some issues with that generator and trades them for better-understood
issues. Starfish does not change xoroshiro's well-tested state transition, but it doesn't base the output on the sum
of the two states (like xoroshiro128+), instead using the first state only for output (exactly like xoroshiro64** and
similar to xoshiro256**). Any arithmetic it performs is safe for GWT. Starfish adds an extremely small amount of
extra code to xoroshiro, running xoroshiro's state transition as normal, using stateA (or s[0] in the original
xoroshiro code) multiplied by 31 as the initial result, then bitwise-rotating that initial result by 28 and adding a
constant that is close to 2 to the 32 times the golden ratio, specifically 0x9E3779BD
. 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 a little slower than xoroshiro64+ or
Lathe, but has better distribution than either. It is equivalent to the algorithm used in GWTRNG
.
This avoids an issue in xoroshiro** generators where many multipliers, when applied to the output of a xoroshiro** generator, will cause the modified output to rapidly fail binary matrix rank tests. It has its own issue where subtracting
0x9E3779BD
or a number with a low Hamming distance from 0x9E3779BD
from every output will
cause similar binary matrix rank failures. It should be clear that this is not a cryptographic generator, but I am
not claiming this is a rock-solid or all-purpose generator either; if a hostile user is trying to subvert a Starfish
generator and can access full outputs, it is a cakewalk to find or create issues.
The name comes from the single Star operation used (relative to the StarStar scrambler) and the addition of the golden ratio, or phi, which sounds close to fish.
Original version here for xoroshiro64**.
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 Starfish32RNG()
Creates a new generator seeded using two calls to Math.random().Starfish32RNG(int seed)
Constructs this Lathe32RNG by dispersing the bits of seed usingsetSeed(int)
across the two parts of state this has.Starfish32RNG(int stateA, int stateB)
Constructs this Lathe32RNG by callingsetState(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).Starfish32RNG(long seed)
Constructs this Lathe32RNG by splitting the given seed across the two parts of state this has withsetState(long)
. -
Method Summary
Modifier and Type Method Description Starfish32RNG
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()
-
Constructor Details
-
Starfish32RNG
public Starfish32RNG()Creates a new generator seeded using two calls to Math.random(). -
Starfish32RNG
Constructs this Lathe32RNG by dispersing the bits of seed usingsetSeed(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
-
Starfish32RNG
Constructs this Lathe32RNG by splitting the given seed across the two parts of state this has withsetState(long)
.- Parameters:
seed
- a long that will be split across both components of state
-
Starfish32RNG
Constructs this Lathe32RNG by callingsetState(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 0stateB
- the number to use as the second 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
- Specified by:
copy
in interfaceStatefulRandomness
- Returns:
- a copy of this RandomnessSource
-
setSeed
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
-
setStateA
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 usesetState(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
-
setStateB
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 usesetState(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
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
Get the current internal state of the StatefulRandomness as a long.- Specified by:
getState
in interfaceStatefulRandomness
- Returns:
- the current internal state of this object.
-
setState
Set the current internal state of this StatefulRandomness with a long.- Specified by:
setState
in interfaceStatefulRandomness
- Parameters:
state
- a 64-bit long. You should avoid passing 0; this implementation will treat it as 1.
-
toString
-
equals
-
hashCode
-