001/*
002Written in 2015 by Sebastiano Vigna (vigna@acm.org)
003
004To the extent possible under law, the author has dedicated all copyright
005and related and neighboring rights to this software to the public domain
006worldwide. This software is distributed without any warranty.
007
008See <http://creativecommons.org/publicdomain/zero/1.0/>. */
009package squidpony.squidmath;
010
011import squidpony.StringKit;
012
013import java.io.Serializable;
014
015/**
016 * This is a SplittableRandom-style generator, meant to have a tiny state
017 * that permits storing many different generators with low overhead.
018 * It should be rather fast, though no guarantees can be made on all hardware.
019 * It should be faster than using SplittableRandom from Java 8 because it has a
020 * single "gamma" value that prevents it from being split but also makes runtime
021 * a bit quicker. It is based on using a unary hash on a large-increment counter,
022 * which makes even the first item obtained from similarly-seeded LightRNGs very
023 * likely to be very different. This is an advantage over non-hash-based RNGs.
024 * <br>
025 * This generator is especially fast on OpenJ9, version 0.17.0 or later (from
026 * late 2019), and can be several times faster there than on HotSpot.
027 * <br>
028 * Written in 2015 by Sebastiano Vigna (vigna@acm.org)
029 * @author Sebastiano Vigna
030 * @author Tommy Ettinger
031 */
032public final class LightRNG implements RandomnessSource, StatefulRandomness, SkippingRandomness, Serializable
033{
034        private static final long serialVersionUID = -374415589203474497L;
035
036    public long state; /* The state can be seeded with any value. */
037
038    /** Creates a new generator seeded using Math.random. */
039    public LightRNG() {
040        this((long) ((Math.random() - 0.5) * 0x10000000000000L)
041                ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L));
042    }
043
044    public LightRNG( final long seed ) {
045        setSeed(seed);
046    }
047
048    /**
049     * Gets a pseudo-random int with at most the specified count of bits; for example, if bits is 3 this can return any
050     * int between 0 and 2 to the 3 (that is, 8), exclusive on the upper end. That would mean 7 could be returned, but
051     * no higher ints, and 0 could be returned, but no lower ints.
052     * 
053     * The algorithm used here changed on March 8, 2018 when LightRNG was remade the default generator in SquidLib.
054     * The older method is available as {@link #compatibleNext(int)}, but its use is discouraged; it's slightly slower 
055     * for no good reason.
056     * @param bits the number of bits to be returned; if 0 or less, or if 32 or greater, can return any 32-bit int
057     * @return a pseudo-random int that uses at most the specified amount of bits
058     */
059    @Override
060    public final int next( int bits ) {
061        long z = state += 0x9E3779B97F4A7C15L;
062        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
063        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
064        return (int)(z ^ (z >>> 31)) >>> (32 - bits);
065    }
066    /**
067     * Gets a pseudo-random int with at most the specified count of bits; for example, if bits is 3 this can return any
068     * int between 0 and 2 to the 3 (that is, 8), exclusive on the upper end. That would mean 7 could be returned, but
069     * no higher ints, and 0 could be returned, but no lower ints.
070     *
071     * The algorithm used here is the older version of {@link #next(int)} before some things changed on March 8 2018.
072     * Using this method is discouraged unless you need to reproduce values exactly; it's slightly slower for no good
073     * reason. Calling {@code next(32)} and {@code compatibleNext(32)} should have identical results, but other values
074     * for bits will probably be different.
075     * @param bits the number of bits to be returned; if 0 or less, or if 32 or greater, can return any 32-bit int
076     * @return a pseudo-random int that uses at most the specified amount of bits
077     */
078    public final int compatibleNext( int bits ) {
079        long z = state += 0x9E3779B97F4A7C15L;
080        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
081        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
082        return (int)( (z ^ (z >>> 31)) & ( 1L << bits ) - 1 );
083    }
084    /**
085     * Can return any long, positive or negative, of any size permissible in a 64-bit signed integer.
086     * @return any long, all 64 bits are random
087     */
088    @Override
089    public final long nextLong() {
090        long z = state += 0x9E3779B97F4A7C15L;
091        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
092        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
093        return z ^ (z >>> 31);
094    }
095
096    /**
097     * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
098     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to
099     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
100     *
101     * @return a copy of this RandomnessSource
102     */
103    @Override
104    public LightRNG copy() {
105        return new LightRNG(state);
106    }
107
108    /**
109     * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
110     * @return any int, all 32 bits are random
111     */
112    public int nextInt() {
113        long z = state += 0x9E3779B97F4A7C15L;
114        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
115        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
116        return (int) (z ^ (z >>> 31)); 
117    }
118
119    /**
120     * Returns a random non-negative integer between 0 (inclusive) and the given bound (exclusive),
121     * or 0 if the bound is 0. The bound can be negative, which will produce 0 or a negative result.
122     * Uses an aggressively optimized technique that has some bias, but mostly for values of
123     * bound over 1 billion. This method uses the same technique as {@link RNG#nextIntHasty(int)},
124     * and like that method will always advance state exactly once (equivalent to one call to
125     * {@link #nextLong()}).
126     * <br>
127     * Credit goes to Daniel Lemire, http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
128     *
129     * @param bound the outer bound (exclusive), can be negative or positive
130     * @return the found number
131     */
132    public int nextInt( final int bound ) {
133        long z = state += 0x9E3779B97F4A7C15L;
134        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
135        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
136        return (int) ((bound * ((z ^ (z >>> 31)) & 0x7FFFFFFFL)) >> 31);
137    }
138
139    /**
140     * Like {@link #compatibleNext(int)}, but for compatibility with {@link #nextInt(int)}.
141     * Exclusive on the upper bound.  The lower bound is 0.
142     * @param bound the upper bound; should be positive
143     * @return a random int less than n and at least equal to 0
144     */
145    public int compatibleNextInt( final int bound ) {
146        if (bound <= 0) return 0;
147        int threshold = (0x7fffffff - bound + 1) % bound;
148        for (; ; ) {
149            int bits = (int) (nextLong() & 0x7fffffff);
150            if (bits >= threshold)
151                return bits % bound;
152        }
153    }
154    /**
155     * Inclusive lower, exclusive upper. Although you should usually use a higher value for upper than for lower, you
156     * can use a lower "upper" than "lower" and this will still work, producing an int between the two bounds.
157     * @param lower the lower bound, inclusive, can be positive or negative
158     * @param upper the upper bound, exclusive, can be positive or negative, usually should be greater than lower
159     * @return a random int between lower (inclusive) and upper (exclusive)
160     */
161    public int nextInt( final int lower, final int upper ) {
162        return lower + nextInt(upper - lower);
163    }
164
165    /**
166     * Inclusive lower, exclusive upper.
167     * @param lower the lower bound, inclusive, can be positive or negative
168     * @param upper the upper bound, exclusive, should be positive, must be greater than lower
169     * @return a random int between lower (inclusive) and upper (exclusive)
170     */
171    public int compatibleNextInt( final int lower, final int upper ) {
172        if ( upper - lower <= 0 ) throw new IllegalArgumentException("Upper bound must be greater than lower bound");
173        return lower + compatibleNextInt(upper - lower);
174    }
175
176    /**
177     * Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive
178     * result.
179     * @param bound the outer exclusive bound; may be positive or negative
180     * @return a random long between 0 (inclusive) and bound (exclusive)
181     */
182    public long nextLong(long bound) {
183        long rand = nextLong();
184        final long randLow = rand & 0xFFFFFFFFL;
185        final long boundLow = bound & 0xFFFFFFFFL;
186        rand >>>= 32;
187        bound >>= 32;
188        final long t = rand * boundLow + (randLow * boundLow >>> 32);
189        return rand * bound + (t >> 32) + (randLow * bound + (t & 0xFFFFFFFFL) >> 32);
190    }
191    
192    /**
193     * Inclusive inner, exclusive outer; both inner and outer can be positive or negative.
194     * @param inner the inner bound, inclusive, can be positive or negative
195     * @param outer the outer bound, exclusive, can be positive or negative and may be greater than or less than inner
196     * @return a random long that may be equal to inner and will otherwise be between inner and outer
197     */
198    public long nextLong(final long inner, final long outer) {
199        return inner + nextLong(outer - inner);
200    }
201
202
203    /**
204     * Exclusive on the upper bound. The lower bound is 0. Unlike {@link #nextInt(int)} or {@link #nextLong(long)}, this
205     * may sometimes advance the state more than once, depending on what numbers are produced internally and the bound.
206     * {@link #nextLong(long)} is preferred because it is much faster and reliably advances the state only once. Because
207     * this method uses rejection sampling, getting multiple random longs to "smooth the odds" when the bound is such
208     * that it can't fairly distribute one random long across all possible outcomes, it may be more "fair" than
209     * {@link #nextLong(long)}, though it could potentially consume more of the period faster if pathologically bad
210     * bounds were used very often, and if enough of the period is gone then statistical flaws may become detectable.
211     * @param bound the upper bound; if this isn't positive, this method always returns 0
212     * @return a random long less than n and at least equal to 0
213     */
214    public long compatibleNextLong(final long bound) {
215        if ( bound <= 0 ) return 0;
216        long threshold = (0x7fffffffffffffffL - bound + 1) % bound;
217        for (;;) {
218            long bits = nextLong() & 0x7fffffffffffffffL;
219            if (bits >= threshold)
220                return bits % bound;
221        }
222    }
223
224    /**
225     * Inclusive lower, exclusive upper.
226     * @param lower the lower bound, inclusive, can be positive or negative
227     * @param upper the upper bound, exclusive, should be positive, must be greater than lower
228     * @return a random long at least equal to lower and less than upper
229     */
230    public long compatibleNextLong( final long lower, final long upper ) {
231        if ( upper - lower <= 0 )  throw new IllegalArgumentException("Upper bound must be greater than lower bound");
232        return lower + compatibleNextLong(upper - lower);
233    }
234    /**
235     * Gets a uniform random double in the range [0.0,1.0)
236     * @return a random double at least equal to 0.0 and less than 1.0
237     */
238    public double nextDouble() {
239        long z = state += 0x9E3779B97F4A7C15L;
240        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
241        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
242        return ((z ^ (z >>> 31)) & 0x1fffffffffffffL) * 0x1p-53;
243    }
244
245    /**
246     * Gets a uniform random double in the range [0.0,outer) given a positive parameter outer. If outer
247     * is negative, it will be the (exclusive) lower bound and 0.0 will be the (inclusive) upper bound.
248     * @param outer the exclusive outer bound, can be negative
249     * @return a random double between 0.0 (inclusive) and outer (exclusive)
250     */
251    public double nextDouble(final double outer) {
252        return nextDouble() * outer;
253    }
254
255    /**
256     * Gets a uniform random float in the range [0.0,1.0)
257     * @return a random float at least equal to 0.0 and less than 1.0
258     */
259    public float nextFloat() {
260        long z = state += 0x9E3779B97F4A7C15L;
261        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
262        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
263        return ((z ^ (z >>> 31)) & 0xffffffL) * 0x1p-24f;
264
265    }
266
267    /**
268     * Gets a random value, true or false.
269     * Calls nextLong() once.
270     * @return a random true or false value.
271     */
272    public boolean nextBoolean() {
273        return nextLong() < 0L;
274    }
275
276    /**
277     * Given a byte array as a parameter, this will fill the array with random bytes (modifying it
278     * in-place). Calls nextLong() {@code Math.ceil(bytes.length / 8.0)} times.
279     * @param bytes a byte array that will have its contents overwritten with random bytes.
280     */
281    public void nextBytes( final byte[] bytes ) {
282        int i = bytes.length, n;
283        while( i != 0 ) {
284            n = Math.min( i, 8 );
285            for ( long bits = nextLong(); n-- != 0; bits >>>= 8 ) bytes[ --i ] = (byte)bits;
286        }
287    }
288
289
290
291    /**
292     * Sets the seed of this generator (which is also the current state).
293     * @param seed the seed to use for this LightRNG, as if it was constructed with this seed.
294     */
295    public void setSeed( final long seed ) {
296        state = seed;
297    }
298    /**
299     * Sets the seed (also the current state) of this generator.
300     * @param seed the seed to use for this LightRNG, as if it was constructed with this seed.
301     */
302    @Override
303    public void setState( final long seed ) {
304        state = seed;
305    }
306    /**
307     * Gets the current state of this generator.
308     * @return the current seed of this LightRNG, changed once per call to nextLong()
309     */
310    @Override
311    public long getState() {
312        return state;
313    }
314
315    /**
316     * Advances or rolls back the LightRNG's state without actually generating each number. Skips forward
317     * or backward a number of steps specified by advance, where a step is equal to one call to nextLong(),
318     * and returns the random number produced at that step (you can get the state with {@link #getState()}).
319     *
320     * @param advance Number of future generations to skip over; can be negative to backtrack, 0 gets the most recent generated number
321     * @return the random long generated after skipping advance numbers
322     */
323    @Override
324    public long skip(long advance) {
325        long z = (state += 0x9E3779B97F4A7C15L * advance);
326        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
327        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
328        return z ^ (z >>> 31);
329    }
330
331
332    @Override
333    public String toString() {
334        return "LightRNG with state 0x" + StringKit.hex(state) + 'L';
335    }
336
337    @Override
338    public boolean equals(Object o) {
339        if (this == o) return true;
340        if (o == null || getClass() != o.getClass()) return false;
341
342        LightRNG lightRNG = (LightRNG) o;
343
344        return state == lightRNG.state;
345    }
346
347    @Override
348    public int hashCode() {
349        return (int) (state ^ (state >>> 32));
350    }
351
352    public static long determine(long state)
353    {
354        return ((state = ((state = ((state *= 0x9E3779B97F4A7C15L) ^ state >>> 30) * 0xBF58476D1CE4E5B9L) ^ state >>> 27) * 0x94D049BB133111EBL) ^ state >>> 31);
355    }
356    public static long determine(final int a, final int b)
357    {
358        long state = 0x9E3779B97F4A7C15L + (a & 0xFFFFFFFFL) + ((long)b << 32);
359        state = ((state >>> 30) ^ state) * 0xBF58476D1CE4E5B9L;
360        state = (state ^ (state >>> 27)) * 0x94D049BB133111EBL;
361        return state ^ (state >>> 31);
362    }
363
364    public static int determineBounded(long state, final int bound)
365    {
366        return (int)((bound * (((state = ((state = ((state *= 0x9E3779B97F4A7C15L) ^ state >>> 30) * 0xBF58476D1CE4E5B9L) ^ state >>> 27) * 0x94D049BB133111EBL) ^ state >>> 31) & 0x7FFFFFFFL)) >> 31);
367    }
368
369    /**
370     * Returns a random float that is deterministic based on state; if state is the same on two calls to this, this will
371     * return the same float. This is expected to be called with a changing variable, e.g. {@code determine(++state)},
372     * where the increment for state should be odd but otherwise doesn't really matter. This multiplies state by
373     * {@code 0x9E3779B97F4A7C15L} within this method, so using a small increment won't be much different from using a
374     * very large one, as long as it is odd. The period is 2 to the 64 if you increment or decrement by 1, but there are
375     * only 2 to the 30 possible floats between 0 and 1.
376     * @param state a variable that should be different every time you want a different random result;
377     *              using {@code determine(++state)} is recommended to go forwards or {@code determine(--state)} to
378     *              generate numbers in reverse order
379     * @return a pseudo-random float between 0f (inclusive) and 1f (exclusive), determined by {@code state}
380     */
381    public static float determineFloat(long state) { return (((state = ((state = ((state *= 0x9E3779B97F4A7C15L) ^ state >>> 30) * 0xBF58476D1CE4E5B9L) ^ state >>> 27) * 0x94D049BB133111EBL) ^ state >>> 31) & 0xFFFFFF) * 0x1p-24f; }
382
383    /**
384     * Returns a random double that is deterministic based on state; if state is the same on two calls to this, this
385     * will return the same float. This is expected to be called with a changing variable, e.g.
386     * {@code determine(++state)}, where the increment for state should be odd but otherwise doesn't really matter. This
387     * multiplies state by {@code 0x9E3779B97F4A7C15L} within this method, so using a small increment won't be much
388     * different from using a very large one, as long as it is odd. The period is 2 to the 64 if you increment or
389     * decrement by 1, but there are only 2 to the 62 possible doubles between 0 and 1.
390     * @param state a variable that should be different every time you want a different random result;
391     *              using {@code determine(++state)} is recommended to go forwards or {@code determine(--state)} to
392     *              generate numbers in reverse order
393     * @return a pseudo-random double between 0.0 (inclusive) and 1.0 (exclusive), determined by {@code state}
394     */
395    public static double determineDouble(long state) { return (((state = ((state = ((state *= 0x9E3779B97F4A7C15L) ^ state >>> 30) * 0xBF58476D1CE4E5B9L) ^ state >>> 27) * 0x94D049BB133111EBL) ^ state >>> 31) & 0x1FFFFFFFFFFFFFL) * 0x1p-53; }
396}