A wrapper class for working with random number generators in a more friendly way.
Implements
IRNG, which covers most of the API surface, but RNG implements
a decent amount of additional methods. You should consider if your code needs
these additional methods, and if not you should use IRNG as the type for when you
need some random number generator.
Includes methods for getting values between two numbers and for getting
random elements from a collection or array. There are methods to shuffle
a collection and to get a random ordering that can be applied as one shuffle
across multiple collections, such as via
OrderedMap#reorder(int...),
ArrayTools#reorder(ArrayList,int...), and so on. You can construct
an RNG with all sorts of RandomnessSource implementations, and choosing them
is usually not a big concern because the default works very well. If you target
GWT, then it is suggested that you use
GWTRNG instead of RNG; both
implement
IRNG, which is enough for most usage across SquidLib, but
GWTRNG is optimized heavily for better performance on GWT, even returning long
values faster than implementations that natively do their math on longs. It has
worse performance on 64-bit PCs and mobile devices, but should also have better
performance on 32-bit PCs and mobile devices.
But if you do want advice on what RandomnessSource to use...
DiverRNGis the default, and is the fastest generator that passes most tests and can
produce all 64-bit values, and though relative to many of the others it has a
significantly shorter period (the amount of random numbers it will go through
before repeating the sequence), this almost never matters in games, and is
primarily relevant for massively-parallel scientific programs. DiverRNG has a
period of
pow(2, 64) as opposed to
XoRoRNG's
pow(2, 128) - 1, or
LongPeriodRNG's
pow(2, 1024) - 1.
LightRNG is a solid choice and a former default RandomnessSource;
additional features of LightRNG are exposed in
MoonwalkRNG and using
MoonwalkRNG is recommended if you need unusual features like skipping backwards
in a random number sequence, taking a result of a nextLong() call and reversing
it to get the state that produced it, or calculating the distance in number of
nextLong() calls between two results of nextLong() calls. LightRNG is a
StatefulRandomness, which lets it be used in
StatefulRNG, and so is
DiverRNG, but LightRNG is also a
SkippingRandomness, which means you can
leap forward or backwards in its sequence very efficiently (DiverRNG is not a
SkippingRandomness).
ThrustAltRNG provides similar qualities to LightRNG,
and is one of the fastest generators here, but can't produce all possible 64-bit
values (possibly some 32-bit values as well); it was the default at one point so
you may want to keep compatibility with some versions by specifying ThrustAltRNG.
The defaults have changed in the past as issues are found in various generators;
LightRNG has high quality all-around but is slower than the other defaults,
ThrustAltRNG can't produce all results, LinnormRNG passed tests in an earlier
version of the PractRand test suite but now fails in the current version, and now
the default is DiverRNG, which shares the known issue of LightRNG and LinnormRNG
that it can't produce the same result twice from
#nextLong() until the
generator exhausts its period and repeats its output from the beginning.
For most cases, you should decide between DiverRNG, ThrustAltRNG, LightRNG,
LongPeriodRNG, MiniMover64RNG, and XoshiroStarPhi32RNG based on your priorities.
Some tasks are better solved by using a different class, usually
GWTRNG,
which can always be serialized on GWT to save its state easily and is usually the
fastest substitute for RNG on that platform. DiverRNG is the best if you want high
speed, very good quality of randomness, and expect to generate a reasonable quantity
of numbers for a game (less than 18446744073709551616 numbers) without any single
results being impossible. LightRNG is the second-best at the above criteria, but is
the best option if you need an RNG that can skip backwards or jump forwards without
incurring speed penalties. LongPeriodRNG is best if you for some reason need a massive
amount of random numbers (as in, ten quintillion would be far too little) or want to
split up such a large generator into unrelated subsequences. XoshiroStarPhi32RNG is
best if GWT is a possible target but you either need to generate more than
18446744073709551616 numbers (but less than 340282366920938463463374607431768211455
numbers) or you need to ensure that each 128-bit chunk of output is unique; if GWT is
a target but those specific needs don't matter, use GWTRNG. ThrustAltRNG and
MiniMover64RNG are both faster than DiverRNG usually (MiniMover64RNG is the fastest),
but because they are unable to generate some outputs, that may make them a poor choice
for some usage (ThrustAltRNG also has some bias toward specific numbers and produces
them more frequently, but not frequently enough to make it fail statistical tests, and
ThrustAltRNG can skip around in its output sequence like LightRNG).
JabRNG is
a mediocre choice for quality but is tied for the fastest with MiniMover64RNG.
There are many more RandomnessSource implementations! You might want significantly less
predictable random results, which
IsaacRNG can provide, along with a
large period. The quality of
PermutedRNG is also good, usually, and it
has a sound basis in PCG-Random, an involved library with many variants on its
RNGs.
There may be reasons why you would want a random number generator that uses 32-bit
math instead of the more common 64-bit math, but using a 32-bit int on desktop and
Android won't act the same as that same 32-bit int on GWT. Since GWT is stuck with
JavaScript's implementation of ints with doubles, overflow (which is needed for an
RNG) doesn't work with ints as expected, but does with GWT's implementation of longs.
If targeting GWT,
Lathe32RNG is significantly faster at producing int values
than any long-based generator, and will produce the same results on GWT as on desktop
or Android (not all 32-bit generators do this).
Starfish32RNG goes one step
further than Lathe32RNG at an even distribution, and has better quality, but is
slightly slower. While Lathe32RNG can produce all ints over the course of its period,
it will produce some pairs of ints, or longs, more often than others and will never
produce some longs. Starfish32RNG will produce all longs but one.
ThrustAlt32RNG,
Zag32RNG, and
Oriole32RNG are also GWT-safe, but other generators that
were thought to be GWT-friendly are not. These GWT-unsafe generators have other uses,
but should not be used on GWT:
PintRNG and
FlapRNG. All other generators
use longs, and so will be slower than the recommended Starfish32RNG or Lathe32RNG on GWT,
but much faster on 64-bit JREs.