Sarong provides Stand-Alone RandOm Number Generators, essentially pulled directly from the author's work in SquidLib, but with scope reduced to just random number generators and hashing functions for arrays and text (useful for String seeds for RNGs).
If you need a fast pseudo-random number generator with good quality, you may be satisfied with
Java 8's java.util.SplittableRandom
class in many cases. However, SplittableRandom is only present
in Java 8, is not necessarily available on GWT, and its period (the number of numbers that it can
generate before it repeats the sequence) is a relatively low 2^64
. Each of these issues has some way
it can be addressed. For platform and version support, sarong.LightRNG
uses the same algorithm as
SplittableRandom, called SplitMix64, and is similarly fast, but is additionally available on Java 6
or 7 (plus GWT and Android) because sarong is highly compatible. As for the low period, you can switch
to sarong.XoRoRNG
(which implements XoRoShiRo 128+, one of the best generators in C but about the
same speed as LightRNG here on the JVM) to get a period of (2^128)-1
, or sarong.discouraged.ThunderRNG
(which
is pretty much a novel algorithm, and is a good deal faster than LightRNG but has worse statistical
traits) to get a period of about 2^127
, although the period is definitely lower for less-significant
bits in the generated numbers and probably lower for some of the higher bits as well. At the extreme
end, there's sarong.LongPeriodRNG
, which has a period of (2^1024)-1
, and sarong.IsaacRNG
, which
has a period that can be described simply with "really, really big", and though it is at minimum 2^40
for worst-case seeds, the period is on average 2^8295
. There's also sarong.PintRNG
, which is meant
specifically for GWT, and avoids arithmetic with long
values wherever possible because that tends to
be much slower on GWT. PintRNG is a simple modification of sarong.PermutedRNG
; both are based on
PCG-Random, and though PCG is excellent in C/C++, here on the JVM it can
only be recommended in very limited circumstances -- it has excellent statistical qualities but a low
period (same as LightRNG) and is slower all around due to JVM quirks. Sarong also supplies two
"quasi-random number generators," which get numbers from sub-random sequences instead of pseudo-random
ones and generally have properties that can be considered desirable when producing random points in
2D, 3D, or higher dimensions that should not be too close to each other in distance. Neither
sarong.SobolQRNG
nor sarong.VanDerCorputQRNG
will probably be seen much outside some specialized
usage; see their JavaDocs for more information.
Usually you'd use LightRNG, LongPeriodRNG, PintRNG, XoRoRNG, or any other class implementing
sarong.RandomnessSource
by giving it to the constructor for sarong.RNG
, a wrapper that adds
many features, including:
- A wide variety of methods for common usage, like
nextLong(long)
orbetween(double, double)
. - The ability to get a
java.util.Random
subclass that produces numbers with the same properties as the RandomnessSource that RNG uses. - Methods to shuffle arrays or Collections, as well as to generate random orderings that can be applied to order collections in certain other libraries (SquidLib uses this, and work is being done on the Salp data structures library to make use of this and similar features). You may want a more specialized variant on RNG, and there are several already.
sarong.StatefulRNG
is a simple subclass of RNG that almost always uses LightRNG for its RandomnessSource implementation, but in turn allows getting and setting the current state as a long.sarong.DeckRNG
is an interesting "sub-randomizing" variant on a normal RNG that generates 16 results at a time, each one in a different range of values (always with as many in the lower half as in the upper half of values) and hands them out like it's dealing cards, ensuring that no perceived "streak of bad luck" can persist very long, and when low numbers have been returned for a few generations, high numbers are sure to follow soon. It essentially makes the Gambler's Fallacy into a reliable trait of the RNG.sarong.EditRNG
allows tweaking the distribution of the RNG to favor lower or higher averages, as well as more or less central results (that is, how often it produces values that are close to or far from the average). It is related tosarong.RandomBias
, which can be used to process any numbers to add a bias like EditRNG is able to.
You may also want to use the hashing functions this has in sarong.util.CrossHash
for some reason;
they are rather fast and work cross-platform, but they can't compare on desktop usage to dedicated
hashing libraries like CityHash and XXHash. It's possible the speed will be competitive with some of
those hashes, though. All three kinds this currently supplies are faster than the implementation of
SipHash that once was here, and SipHash was removed because it was roughly 7-8x slower than Wisp,
the default hash used here, with little noticeable quality change. CrossHash supplies four different
types of hash algorithm, each able to generate 64-bit and 32-bit hashes. The default is used with
just CrossHash.hash64()
or CrossHash.hash()
and is nicknamed Wisp; it is the fastest of the four
hash types, has good quality, and may have particular benefits on GWT since the 32-bit hash() methods
don't use the slow, emulated 64-bit math on GWT unless hashing long or double arrays. It also avoids
certain other code that only performs well on certain Java runtime environments (Long.rotateLeft
needs a somewhat-modern processor and a JRE run with the -server flag to be as fast as it can be, and
Wisp avoids using this while Lightning and Storm do not). An alternative is Lightning, which has
rather high quality and good speed, and doesn't have any serious flaws in inputs found so far.
Lightning doesn't have any ability to "salt" the hash, changing the generated values in an
unpredictable way using an extra parameter at construction; CrossHash.Storm
does, and so it offers
essentially the best quality of any of the three. Storm is slightly slower than Lightning, but
CrossHash.Falcon
is faster than both, though it is slower than the default Wisp. Falcon has a
significant flaw if you generate 32-bit hashes using long
or double
arrays for input; half of
the bits in each input are discarded, and this is especially bad for double
arrays because much of
the information is in the upper (discarded) half of bits. You should only use Falcon if you either
only use 64-bit results or only give 32-bit types for input (including Object arrays, which are OK);
otherwise use Wisp or Lightning.
This project has no run-time dependencies other than Java 6 or higher and should work on GWT. To add sarong as a dependency for Maven, Gradle, or some other JVM build tool, you can use the info on Maven Central or, for the easy cases of Maven and Gradle:
Maven dependency, latest stable:
<dependency>
<groupId>com.github.tommyettinger</groupId>
<artifactId>sarong</artifactId>
<version>0.5</version>
</dependency>
Gradle dependency, latest stable:
compile 'com.github.tommyettinger:sarong:0.5'
I hope this can be useful!