Package squidpony.squidmath
Class Mover32RNG
java.lang.Object
squidpony.squidmath.Mover32RNG
- All Implemented Interfaces:
Serializable
,RandomnessSource
public final class Mover32RNG extends Object implements RandomnessSource
One of Mark Overton's subcycle generators from this article,
specifically a cmr^cmr with two 32-bit states; this is the fastest 32-bit generator that still passes statistical
tests, plus it's optimized for GWT (sometimes). It has a period of just under 2 to the 64, 0xFFF1F6F18B2A1330, which
is roughly 2 to the 63.999691, and allows 2 to the 32 initial seeds.
This seems to do well in PractRand testing (32 TB passed), but this is not a generator Overton tested. "Chaotic" generators like this one tend to score well in PractRand, but it isn't clear if they will fail other tests (in particular, they can't generate all possible long values, and also can't generate 0 or possibly some other ints). As for desktop/server speed, this is faster than
Its period is 0xFFF1F6F18B2A1330 for the largest cycle, which it always initializes into if
This is a RandomnessSource but not a StatefulRandomness because it needs to take care and avoid seeds that would put it in a short-period subcycle. It uses two generators with different cycle lengths, and skips at most 65536 times into each generator's cycle independently when seeding. It uses constants to store 128 known midpoints for each generator, which ensures it calculates an advance for each generator at most 511 times.
The name comes from M. Overton, who discovered this category of subcycle generators, and also how this generator can really move when it comes to speed.
Created by Tommy Ettinger on 8/6/2018.
This seems to do well in PractRand testing (32 TB passed), but this is not a generator Overton tested. "Chaotic" generators like this one tend to score well in PractRand, but it isn't clear if they will fail other tests (in particular, they can't generate all possible long values, and also can't generate 0 or possibly some other ints). As for desktop/server speed, this is faster than
Starfish32RNG
(which is also high-quality) and is also faster
than Lathe32RNG
(which is very fast but has quality issues). However, this is slower than Lathe32RNG when
using GWT and viewing in Firefox; for some reason Starfish32RNG
optimizes well on Firefox and less well on
Chrome, but Mover does ver well in older Chrome (faster than Lathe) and rather poorly on Firefox. It doesn't do
amazingly well in current Chrome versions, however, and Lathe beats it most of the time there. On 64-bit desktop or
server Java, you may want to prefer Mover64RNG
, which is the same algorithm using larger words and constants,
or MiniMover64RNG
, which is even faster but probably has a shorter period than this generator (millions of
seeds have been checked to ensure a minimum period of 2 to the 20 for it, though). While each of the two parts
of a Mover32RNG can have their full period evaluated, making the total period possible to calculate, the same cannot
be said for Mover64RNG or MiniMover64RNG (their maximum periods are high enough for most usage, but the actual totals
are still unknown).
Its period is 0xFFF1F6F18B2A1330 for the largest cycle, which it always initializes into if
setState(int)
is
used. setState() only allows 2 to the 32 starting states, but less than 2 to the 64 states are in the largest cycle,
so using a long or two ints to set the state seems ill-advised. The generator has two similar parts, each updated
without needing to read from the other part. Each is a 32-bit CMR generator, which multiplies a state by a constant,
rotates by another constant, and stores that as the next state. The particular constants used here were found by
randomly picking 16-bit odd numbers as multipliers, checking the period for every non-zero rotation, and reporting
the multiplier and rotation amount when a period was found that was greater than 0xFF000000. Better multipliers are
almost guaranteed to exist, but finding them would be a challenge.
This is a RandomnessSource but not a StatefulRandomness because it needs to take care and avoid seeds that would put it in a short-period subcycle. It uses two generators with different cycle lengths, and skips at most 65536 times into each generator's cycle independently when seeding. It uses constants to store 128 known midpoints for each generator, which ensures it calculates an advance for each generator at most 511 times.
The name comes from M. Overton, who discovered this category of subcycle generators, and also how this generator can really move when it comes to speed.
Created by Tommy Ettinger on 8/6/2018.
- Author:
- Mark Overton, Tommy Ettinger
- See Also:
- Serialized Form
-
Constructor Summary
Constructors Constructor Description Mover32RNG()
Mover32RNG(int state)
Mover32RNG(int stateA, int stateB)
Not advised for external use; preferMover32RNG(int)
because it guarantees a good subcycle. -
Method Summary
Modifier and Type Method Description Mover32RNG
copy()
Produces a copy of this Mover32RNG 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()
Gets the "A" part of the state; if this generator was set withMover32RNG()
,Mover32RNG(int)
, orsetState(int)
, then this will be on the optimal subcycle, otherwise it may not be.int
getStateB()
Gets the "B" part of the state; if this generator was set withMover32RNG()
,Mover32RNG(int)
, orsetState(int)
, then this will be on the optimal subcycle, otherwise it may not be.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()
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
setState(int s)
void
setStateA(int stateA)
Sets the "A" part of the state to any int, which may put the generator in a low-period subcycle.void
setStateB(int stateB)
Sets the "B" part of the state to any int, which may put the generator in a low-period subcycle.String
toString()
-
Constructor Details
-
Mover32RNG
public Mover32RNG() -
Mover32RNG
-
Mover32RNG
Not advised for external use; preferMover32RNG(int)
because it guarantees a good subcycle. This constructor allows all subcycles to be produced, including ones with a shorter period.- Parameters:
stateA
-stateB
-
-
-
Method Details
-
setState
-
nextInt
-
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 Mover32RNG 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 need 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 Mover32RNG
-
getStateA
Gets the "A" part of the state; if this generator was set withMover32RNG()
,Mover32RNG(int)
, orsetState(int)
, then this will be on the optimal subcycle, otherwise it may not be.- Returns:
- the "A" part of the state, an int
-
getStateB
Gets the "B" part of the state; if this generator was set withMover32RNG()
,Mover32RNG(int)
, orsetState(int)
, then this will be on the optimal subcycle, otherwise it may not be.- Returns:
- the "B" part of the state, an int
-
setStateA
Sets the "A" part of the state to any int, which may put the generator in a low-period subcycle. UsesetState(int)
to guarantee a good subcycle.- Parameters:
stateA
- any int
-
setStateB
Sets the "B" part of the state to any int, which may put the generator in a low-period subcycle. UsesetState(int)
to guarantee a good subcycle.- Parameters:
stateB
- any int
-
toString
-
equals
-
hashCode
-