public class StrangerRNG extends java.lang.Object implements RandomnessSource, java.io.Serializable
long
states that changes its state with complex ways it can connect states to
other states. This has been backported from jdkgdxds. This generator has a known minimum period of (2 to the 65) - 2,
but a shorter probable maximum period than FourWheelRNG
(which has no guarantee on minimum period). It is a
very fast generator on Java 16 and newer, though slower than FourWheelRNG when multiplication is fast on the platform
in question. It's about 30% faster than Java 17's built-in Xoshiro256PlusPlus when also run on Java 17; both use no
multiplication and have the same state size. It's unusually slower on Java 8, relative to more recent JDKs like 16 or
17; on Java 8 specifically, you might prefer FourWheelRNG or TricycleRNG
.
0x9E3779B97F4A7C15
(or 11.4 quintillion) steps forward. States
C and D are more typical; C incorporates a rotated D and B, while D incorporates C, A, and a large additive constant.
This class returns the C state as it was before next state is calculated, as an optimization, so it is recommended
that you set the state with one long, or with three longs that are sufficiently random already for your purposes.
Both the one- and three-parameter setSeed() methods separate the A and B states by many steps; the one-parameter
setSeed() also randomizes state C so the first result returned will be randomly different from the seed.
Modifier and Type | Field and Description |
---|---|
protected long |
stateA
Can be any long value except 0.
|
protected long |
stateB
Can be any long value except 0, and should be very distant from stateA in the xorshift sequence.
|
protected long |
stateC
Can be any long value; will be returned verbatim from
nextLong() and only change for the next call. |
protected long |
stateD
Can be any long value.
|
Constructor and Description |
---|
StrangerRNG()
Creates a new generator seeded using Math.random.
|
StrangerRNG(long seed) |
StrangerRNG(long seedA,
long seedB,
long seedC,
long seedD) |
Modifier and Type | Method and Description |
---|---|
StrangerRNG |
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 |
getStateA() |
long |
getStateB() |
long |
getStateC() |
long |
getStateD() |
int |
hashCode() |
static long |
jump(long state)
Jumps
state ahead by 0x9E3779B97F4A7C15 steps of the generator StrangerRandom uses for its stateA
and stateB. |
int |
next(int bits)
Using this method, any algorithm that might use the built-in Java Random
can interface with this randomness source.
|
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.
|
long |
previousLong() |
void |
setSeed(long seed)
This initializes all 4 states of the generator to random values based on the given seed.
|
void |
setState(long stateA,
long stateC,
long stateD)
Sets the state with three variables, ensuring that the result has states A and B
sufficiently separated from each other, while keeping states C and D as given.
|
void |
setState(long stateA,
long stateB,
long stateC,
long stateD)
Sets the state completely to the given four state variables, unless stateA or stateB are 0.
|
void |
setStateA(long stateA)
Sets the first part of the state.
|
void |
setStateB(long stateB)
Sets the second part of the state.
|
void |
setStateC(long stateC)
Sets the third part of the state.
|
void |
setStateD(long stateD)
Sets the fourth part of the state.
|
java.lang.String |
toString() |
protected long stateA
protected long stateB
protected long stateC
nextLong()
and only change for the next call.protected long stateD
public StrangerRNG()
public StrangerRNG(long seed)
public StrangerRNG(long seedA, long seedB, long seedC, long seedD)
public static long jump(long state)
state
ahead by 0x9E3779B97F4A7C15 steps of the generator StrangerRandom uses for its stateA
and stateB. When used how it is here, it ensures stateB is 11.4 quintillion steps ahead of stateA in their
shared sequence, or 7 quintillion behind if you look at it another way. It would typically take years of
continuously running this generator at 100GB/s to have stateA become any state that stateB has already been.
Users only need this function if setting stateB by-hand; in that case, state
should be their stateA.
state
- the initial state of a 7-9 xorshift generatorpublic void setSeed(long seed)
nextLong()
(because stateC
is guaranteed to be
different for every non-zero seed
). This ensures stateB is a sufficient distance
from stateA in their shared sequence, and also does some randomizing on the seed before it
assigns the result to stateC. This isn't an instantaneously-fast method to call like some
versions of setSeed(), but it shouldn't be too slow unless it is called before every
generated number (even then, it might be fine).seed
- the initial seed; may be any longpublic long getStateA()
public void setStateA(long stateA)
stateA
- can be any long except 0; this treats 0 as 0xD3833E804F4C574BLpublic long getStateB()
public void setStateB(long stateB)
stateB
- can be any long except 0; this treats 0 as 0x790B300BF9FE738FLpublic long getStateC()
public void setStateC(long stateC)
nextLong()
immediately after this, it will return the given stateC
as-is, so you
may want to call some random generation methods (such as nextLong()) and discard
the results after setting the state.stateC
- can be any longpublic long getStateD()
public void setStateD(long stateD)
stateD
- can be any longpublic void setState(long stateA, long stateB, long stateC, long stateD)
setStateA(long)
, setStateB(long)
,
setStateC(long)
, and setStateD(long)
as a group. You may want
to call nextLong()
a few times after setting the states like this, unless
the value for stateC (in particular) is already adequately random; the first call
to nextLong()
, if it is made immediately after calling this, will return stateC
as-is.stateA
- the first state; can be any long; can be any long except 0stateB
- the second state; can be any long; can be any long except 0stateC
- the third state; this will be returned as-is if the next call is to nextLong()
stateD
- the fourth state; can be any longpublic void setState(long stateA, long stateC, long stateD)
jump(long)
. If stateA is
given as 0, this uses 0xD3833E804F4C574BL instead for stateA and 0x790B300BF9FE738FL
for stateB. States C and D can each be any long.stateA
- the long value to use for stateA and also used to get stateB; can be any long except 0stateC
- the long value to use for stateC; this will be returned as-is if the next call is to nextLong()
stateD
- the long value to use for stateD; can be any longpublic long nextLong()
RandomnessSource
nextLong
in interface RandomnessSource
public long previousLong()
public int next(int bits)
RandomnessSource
next
in interface RandomnessSource
bits
- the number of bits to be returnedpublic StrangerRNG copy()
copy
in interface RandomnessSource
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.