public class Starfish32RNG extends java.lang.Object implements StatefulRandomness, java.io.Serializable
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
.
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.
Constructor and 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 using
setSeed(int) across the two parts of state
this has. |
Starfish32RNG(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). |
Starfish32RNG(long seed)
Constructs this Lathe32RNG by splitting the given seed across the two parts of state this has with
setState(long) . |
Modifier and Type | Method and 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(java.lang.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.
|
java.lang.String |
toString() |
public Starfish32RNG()
public Starfish32RNG(int seed)
setSeed(int)
across the two parts of state
this has.seed
- an int that won't be used exactly, but will affect both components of statepublic Starfish32RNG(long seed)
setState(long)
.seed
- a long that will be split across both components of statepublic Starfish32RNG(int stateA, int stateB)
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).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 statepublic int next(int bits)
RandomnessSource
next
in interface RandomnessSource
bits
- the number of bits to be returnedpublic int nextInt()
public long nextLong()
RandomnessSource
nextLong
in interface RandomnessSource
public Starfish32RNG copy()
copy
in interface RandomnessSource
copy
in interface StatefulRandomness
public void setSeed(int seed)
seed
- the int to use to produce this generator's statepublic int getStateA()
public void setStateA(int stateA)
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().stateA
- any intpublic int getStateB()
public void setStateB(int stateB)
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().stateB
- any intpublic void setState(int stateA, int stateB)
stateA
- any int (if stateA and stateB are both 0, this will be treated as 1)stateB
- any intpublic long getState()
getState
in interface StatefulRandomness
public void setState(long state)
setState
in interface StatefulRandomness
state
- a 64-bit long. You should avoid passing 0; this implementation will treat it as 1.public java.lang.String toString()
toString
in class java.lang.Object
public boolean equals(java.lang.Object o)
equals
in class java.lang.Object
public int hashCode()
hashCode
in class java.lang.Object
Copyright © Eben Howard 2012–2022. All rights reserved.