Package squidpony.squidmath
Class XoRoRNG
java.lang.Object
squidpony.squidmath.XoRoRNG
- All Implemented Interfaces:
Serializable
,RandomnessSource
public final class XoRoRNG extends Object implements RandomnessSource, Serializable
A port of Blackman and Vigna's xoroshiro128+ generator; should be very fast and produce medium-quality output.
Testing shows it is within 5% the speed of LightRNG, sometimes faster and sometimes slower, and has a larger period.
It's called XoRo because it involves Xor as well as Rotate operations on the 128-bit pseudo-random state. Note that
xoroshiro128+ fails some statistical quality tests systematically, and fails others often; if this could be a concern
for you,
Original version here.
Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
DiverRNG
, which is the default for RNG
, will be faster and won't fail tests, and
though its period is shorter, it would still take years to exhaust on one core generating only random numbers.
LightRNG
is also very fast, but relative to XoRoRNG it has a significantly shorter period (the amount of
random numbers it will go through before repeating), at pow(2, 64)
as opposed to XoRoRNG's
pow(2, 128) - 1
, but LightRNG also allows the current RNG state to be retrieved and altered with
getState()
and setState()
. For most cases, you should decide between DiverRNG, LightRNG, XoRoRNG,
and other RandomnessSource implementations based on your needs for period length and state manipulation (DiverRNG
is also used internally by almost all StatefulRNG objects). You might want significantly less predictable random
results, which IsaacRNG
can provide, along with a large period. You may want a very long period of random
numbers, which would suggest LongPeriodRNG
as a good choice or MersenneTwister
as a potential
alternative. You may want better performance on 32-bit machines or on GWT, where Starfish32RNG
is currently
the best choice most of the time, and Lathe32RNG
can be faster but has slightly worse quality (both of these
generators use a 32-bit variant on the xoroshiro algorithm but change the output scrambler). These all can generate
pseudo-random numbers in a handful of nanoseconds (with the key exception of 64-bit generators being used on GWT,
where they may take more than 100 nanoseconds per number), so unless you need a LOT of random numbers in a hurry,
they'll probably all be fine on performance. You may want to decide on the special features of a generator, indicated
by implementing StatefulRandomness
if their state can be read and written to, and/or
SkippingRandomness
if sections in the generator's sequence can be skipped in long forward or backward leaps.
Original version here.
Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
- Author:
- Sebastiano Vigna, David Blackman, Tommy Ettinger (if there's a flaw, use SquidLib'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 XoRoRNG()
Creates a new generator seeded using four calls to Math.random().XoRoRNG(long seed)
Constructs this XoRoRNG by dispersing the bits of seed usingsetSeed(long)
across the two parts of state this has.XoRoRNG(long stateA, long stateB)
Constructs this XoRoRNG by callingsetSeed(long, long)
on the arguments as given; see that method for the specific details (stateA and stateB are kept as-is unless they are both 0). -
Method Summary
Modifier and Type Method Description XoRoRNG
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
getStateA()
Gets the first component of this generator's two-part state, as a long.long
getStateB()
Gets the second component of this generator's two-part state, as a long.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.boolean
nextBoolean()
void
nextBytes(byte[] bytes)
double
nextDouble()
float
nextFloat()
int
nextInt()
Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.int
nextInt(int bound)
Exclusive on the outer bound; the inner bound is 0.int
nextInt(int inner, int outer)
Inclusive lower, exclusive upper.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
nextLong(long bound)
Exclusive on the outer bound; the inner bound is 0.long
nextLong(long inner, long outer)
Inclusive inner, exclusive outer; both inner and outer can be positive or negative.void
setSeed(long seed)
Sets the seed of this generator using one long, running that through LightRNG's algorithm twice to get the state.void
setSeed(long stateA, long stateB)
Sets the seed of this generator using two longs, using them without changes unless both are 0 (then it makes the state variable corresponding to stateA 1 instead).String
toString()
-
Constructor Details
-
XoRoRNG
public XoRoRNG()Creates a new generator seeded using four calls to Math.random(). -
XoRoRNG
Constructs this XoRoRNG by dispersing the bits of seed usingsetSeed(long)
across the two parts of state this has.- Parameters:
seed
- a long that won't be used exactly, but will affect both components of state
-
XoRoRNG
Constructs this XoRoRNG by callingsetSeed(long, long)
on the arguments 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
-
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
-
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
-
nextInt
Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive result.- Parameters:
bound
- the outer exclusive bound; may be positive or negative- Returns:
- a random int between 0 (inclusive) and bound (exclusive)
-
nextInt
Inclusive lower, exclusive upper.- Parameters:
inner
- the inner bound, inclusive, can be positive or negativeouter
- the outer bound, exclusive, should be positive, should usually be greater than inner- Returns:
- a random int that may be equal to inner and will otherwise be between inner and outer
-
nextLong
Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive result.- Parameters:
bound
- the outer exclusive bound; may be positive or negative- Returns:
- a random long between 0 (inclusive) and bound (exclusive)
-
nextLong
Inclusive inner, exclusive outer; both inner and outer can be positive or negative.- Parameters:
inner
- the inner bound, inclusive, can be positive or negativeouter
- the outer bound, exclusive, can be positive or negative and may be greater than or less than inner- Returns:
- a random long that may be equal to inner and will otherwise be between inner and outer
-
nextDouble
-
nextFloat
-
nextBoolean
-
nextBytes
-
setSeed
Sets the seed of this generator using one long, running that through LightRNG's algorithm twice to get the state.- Parameters:
seed
- the number to use as the seed
-
setSeed
Sets the seed of this generator using two longs, using them without changes unless both are 0 (then it makes the state variable corresponding to stateA 1 instead).- 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
-
getStateA
Gets the first component of this generator's two-part state, as a long. This can be 0 on its own, but will never be 0 at the same time as the other component of state,getStateB()
. You can set the state with two exact values usingsetSeed(long, long)
, but the alternative overloadsetSeed(long)
won't use the state without changing it (it needs to cover 128 bits with a 64-bit value).- Returns:
- the first component of this generator's state
-
getStateB
Gets the second component of this generator's two-part state, as a long. This can be 0 on its own, but will never be 0 at the same time as the other component of state,getStateA()
. You can set the state with two exact values usingsetSeed(long, long)
, but the alternative overloadsetSeed(long)
won't use the state without changing it (it needs to cover 128 bits with a 64-bit value).- Returns:
- the second component of this generator's state
-
toString
-
equals
-
hashCode
-