001package squidpony.squidmath;
002
003import java.io.Serializable;
004import java.util.ArrayList;
005import java.util.Arrays;
006import java.util.Collection;
007import java.util.Collections;
008import java.util.Iterator;
009import java.util.List;
010
011/**
012 * A helper class for implementing {@link IRNG} without so much busy-work.
013 * You need to provide implementations for the abstract methods {@link #nextInt()}, {@link #next(int)},
014 * {@link #nextLong()}, {@link #nextBoolean()}, {@link #nextDouble()}, {@link #nextFloat()}, {@link #copy()}, and
015 * {@link #toSerializable()}, many of which may be built off of each other and some of which have sample code in their
016 * documentation strings in this class.
017 * <br>
018 * Big thanks to smelc for the concept in his hgameshrogue library.
019 * @author Tommy Ettinger
020 * @author smelC
021 */
022public abstract class AbstractRNG implements IRNG {
023    /**
024     * Get up to 32 bits (inclusive) of random output; the int this produces
025     * will not require more than {@code bits} bits to represent.
026     *
027     * @param bits an int between 1 and 32, both inclusive
028     * @return a random number that fits in the specified number of bits
029     */
030    @Override
031    public abstract int next(int bits);
032    /**
033     * Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive).
034     *
035     * @return a 32-bit random int.
036     */
037    @Override
038    public abstract int nextInt();
039
040    /**
041     * Returns a random non-negative integer below the given bound, or 0 if the bound is 0 or
042     * negative.
043     *
044     * @param bound the upper bound (exclusive)
045     * @return the found number
046     */
047    @Override
048    public int nextInt(int bound) {
049        return (int) ((bound * ((long)next(31))) >>> 31) & ~(bound >> 31);
050    }
051
052    /**
053     * Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive).
054     *
055     * @return a 64-bit random long.
056     */
057    @Override
058    public abstract long nextLong();
059
060    /**
061     * Exclusive on bound (which must be positive), with an inner bound of 0.
062     * If bound is negative or 0 this always returns 0.
063     * <br>
064     * Credit for this method goes to <a href="https://oroboro.com/large-random-in-range/">Rafael Baptista's blog</a>
065     * for the original idea, and the JDK10 Math class' usage of Karatsuba multiplication for the current algorithm. 
066     * This method is drastically faster than the previous implementation when the bound varies often (roughly 4x
067     * faster, possibly more). It also always gets exactly one random long, so by default it advances the state as much
068     * as {@link #nextLong()}; subclasses can generate two ints instead of one long if they prefer.
069     * 
070     * @param bound the outer exclusive bound; should be positive, otherwise this always returns 0L
071     * @return a random long between 0 (inclusive) and bound (exclusive)
072     */
073    @Override
074    public long nextLong(long bound) {
075        long rand = nextLong();
076        if (bound <= 0) return 0;
077        final long randLow = rand & 0xFFFFFFFFL;
078        final long boundLow = bound & 0xFFFFFFFFL;
079        rand >>>= 32;
080        bound >>>= 32;
081        final long a = rand * bound;
082        final long b = randLow * boundLow;
083        return (((b >>> 32) + (rand + randLow) * (bound + boundLow) - a - b) >>> 32) + a;
084    }
085
086    /**
087     * Get a random bit of state, interpreted as true or false with approximately equal likelihood.
088     * <br>
089     * Note: This is abstract because some implementations may be best served by using {@link #next(int)} to get 1 bit,
090     * returning {@code next(1) == 1}, but others will get much better results with a sign check by calling their choice
091     * of {@link #nextInt()} or {@link #nextLong()} and returning {@code nextInt() < 0} or {@code nextLong < 0L}. For
092     * example, an implementation that uses a linear congruential generator without truncating some lower bits will have
093     * very-low-period results for the bottom bit (alternating true and false), but perfectly fine results from a sign
094     * check. There are tested issues on the bottom (at least 2) bits of {@link XoRoRNG}, but again not on a sign check.
095     * @return a random boolean.
096     */
097    @Override
098    public abstract boolean nextBoolean();
099    /**
100     * Gets a random double between 0.0 inclusive and 1.0 exclusive.
101     * This returns a maximum of 0.9999999999999999 because that is the largest double value that is less than 1.0 .
102     * <br>
103     * This is abstract because some generators may natively work with double or float values, but others may need to
104     * convert a long to a double as with {@code (nextLong() & 0x1fffffffffffffL) * 0x1p-53}, which is recommended if
105     * longs are fast to produce.
106     * @return a double between 0.0 (inclusive) and 0.9999999999999999 (inclusive)
107     */
108    @Override
109    public abstract double nextDouble();
110    /**
111     * This returns a random double between 0.0 (inclusive) and outer (exclusive). The value for outer can be positive
112     * or negative. Because of how math on doubles works, there are at most 2 to the 53 values this can return for any
113     * given outer bound, and very large values for outer will not necessarily produce all numbers you might expect.
114     *
115     * @param outer the outer exclusive bound as a double; can be negative or positive
116     * @return a double between 0.0 (inclusive) and outer (exclusive)
117     */
118    @Override
119    public double nextDouble(double outer) {
120        return nextDouble() * outer;
121    }
122
123    /**
124     * Gets a random float between 0.0f inclusive and 1.0f exclusive.
125     * This returns a maximum of 0.99999994 because that is the largest float value that is less than 1.0f .
126     * <br>
127     * This is abstract because some generators may natively work with double or float values, but others may need to
128     * convert an int or long to a float as with {@code (nextInt() & 0xffffff) * 0x1p-24f},
129     * {@code (nextLong() & 0xffffffL) * 0x1p-24f}, or {@code next(24) * 0x1p-24f}, any of which can work when the
130     * method they call is high-quality and fast. You probably would want to use nextInt() or next() if your
131     * implementation is natively 32-bit and is slower at producing longs, for example.
132     * @return a float between 0f (inclusive) and 0.99999994f (inclusive)
133     */
134    @Override
135    public abstract float nextFloat();
136    /**
137     * This returns a random float between 0.0f (inclusive) and outer (exclusive). The value for outer can be positive
138     * or negative. Because of how math on floats works, there are at most 2 to the 24 values this can return for any
139     * given outer bound, and very large values for outer will not necessarily produce all numbers you might expect.
140     *
141     * @param outer the outer exclusive bound as a float; can be negative or positive
142     * @return a float between 0f (inclusive) and outer (exclusive)
143     */
144    @Override
145    public float nextFloat(float outer) {
146        return nextFloat() * outer;
147    }
148    /**
149     * Exclusive on bound (which may be positive or negative), with an inner bound of 0.
150     * If bound is negative this returns a negative long; if bound is positive this returns a positive long. The bound
151     * can even be 0, which will cause this to return 0L every time. This uses a biased technique to get numbers from
152     * large ranges, but the amount of bias is incredibly small (expected to be under 1/1000 if enough random ranged
153     * numbers are requested, which is about the same as an unbiased method that was also considered). It may have
154     * noticeable bias if the generator's period is exhausted by only calls to this method. Unlike all unbiased methods,
155     * this advances the state by an equivalent to exactly one call to {@link #nextLong()}, where rejection sampling
156     * would sometimes advance by one call, but other times by arbitrarily many more.
157     * <br>
158     * Credit for this method goes to <a href="https://oroboro.com/large-random-in-range/">Rafael Baptista's blog</a>
159     * for the original idea, and the JDK10 Math class' usage of Hacker's Delight code for the current algorithm. 
160     * This method is drastically faster than the previous implementation when the bound varies often (roughly 4x
161     * faster, possibly more). It also always gets exactly one random long, so by default it advances the state as much
162     * as {@link #nextLong()}; subclasses that are better at generating ints can override this and generate two ints
163     * instead of one long that needs separating internally.
164     *
165     * @param bound the outer exclusive bound; can be positive or negative
166     * @return a random long between 0 (inclusive) and bound (exclusive)
167     */
168    @Override
169    public long nextSignedLong(long bound) {
170        long rand = nextLong();
171        final long randLow = rand & 0xFFFFFFFFL;
172        final long boundLow = bound & 0xFFFFFFFFL;
173        rand >>>= 32;
174        bound >>= 32;
175        final long t = rand * boundLow + (randLow * boundLow >>> 32);
176        return rand * bound + (t >> 32) + (randLow * bound + (t & 0xFFFFFFFFL) >> 32);
177    }
178
179    /**
180     * Returns a random non-negative integer between 0 (inclusive) and the given bound (exclusive),
181     * or 0 if the bound is 0. The bound can be negative, which will produce 0 or a negative result.
182     * <br>
183     * Credit goes to Daniel Lemire, http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
184     *
185     * @param bound the outer bound (exclusive), can be negative or positive
186     * @return the found number
187     */
188    @Override
189    public int nextSignedInt(final int bound) {
190        return (int) ((bound * (nextInt() & 0xFFFFFFFFL)) >> 32);
191    }
192
193    /**
194     * Returns a value between min (inclusive) and max (exclusive) as ints.
195     * <br>
196     * The inclusive and exclusive behavior is to match the behavior of the similar
197     * method that deals with floating point values.
198     * <br>
199     * If {@code min} and {@code max} happen to be the same, {@code min} is returned
200     * (breaking the exclusive behavior, but it's convenient to do so).
201     *
202     * @param min the minimum bound on the return value (inclusive)
203     * @param max the maximum bound on the return value (exclusive)
204     * @return the found value
205     */
206    @Override
207    public int between(int min, int max) {
208        return nextInt(max - min) + min;
209    }
210
211    /**
212     * Returns a value between min (inclusive) and max (exclusive) as longs.
213     * <br>
214     * The inclusive and exclusive behavior is to match the behavior of the similar
215     * method that deals with floating point values.
216     * <br>
217     * If {@code min} and {@code max} happen to be the same, {@code min} is returned
218     * (breaking the exclusive behavior, but it's convenient to do so).
219     *
220     * @param min the minimum bound on the return value (inclusive)
221     * @param max the maximum bound on the return value (exclusive)
222     * @return the found value
223     */
224    @Override
225    public long between(long min, long max) {
226        return nextLong(max - min) + min;
227    }
228
229    /**
230     * Returns a value from a uniform distribution from min (inclusive) to max
231     * (exclusive).
232     *
233     * @param min the minimum bound on the return value (inclusive)
234     * @param max the maximum bound on the return value (exclusive)
235     * @return the found value
236     */
237    @Override
238    public double between(double min, double max) {
239        return nextDouble(max - min) + min;
240    }
241
242    /**
243     * Returns a random element from the provided array and maintains object
244     * type.
245     *
246     * @param array the array to get an element from
247     * @return the randomly selected element
248     */
249    @Override
250    public <T> T getRandomElement(T[] array) {
251        if (array.length < 1) {
252            return null;
253        }
254        return array[nextInt(array.length)];
255    }
256
257    /**
258     * Returns a random element from the provided list. If the list is empty
259     * then null is returned. This will perform well on Lists that allow random access,
260     * but will not perform as well on {@link java.util.LinkedList} or similar classes
261     * that need to iterate one-by-one in their {@link List#get(int)} method.
262     *
263     * @param list the list to get an element from
264     * @return the randomly selected element
265     */
266    @Override
267    public <T> T getRandomElement(List<T> list) {
268        if (list.isEmpty()) {
269            return null;
270        }
271        return list.get(nextInt(list.size()));
272    }
273
274    /**
275     * Returns a random element from the provided Collection, which should have predictable iteration order if you want
276     * predictable behavior for identical RNG seeds, though it will get a random element just fine for any Collection
277     * (just not predictably in all cases). If you give this a Set, it should be a LinkedHashSet or some form of sorted
278     * Set like TreeSet if you want predictable results. Any List or Queue should be fine. Map does not implement
279     * Collection, thank you very much Java library designers, so you can't actually pass a Map to this, though you can
280     * pass the keys or values. If coll is empty, returns null.
281     * <br>
282     * Requires iterating through a random amount of coll's elements, so performance depends on the size of coll but is
283     * likely to be decent, as long as iteration isn't unusually slow. This replaces {@code getRandomElement(Queue)},
284     * since Queue implements Collection and the older Queue-using implementation was probably less efficient.
285     * <br>
286     * You should generally prefer {@link #getRandomElement(List)} whenever possible, or in some cases you can use
287     * methods that get a random value on the Collection (or Map, in the case of OrderedMap) itself.
288     *
289     * @param coll the Collection to get an element from; remember, Map does not implement Collection
290     * @return the randomly selected element
291     */
292    @Override
293    public <T> T getRandomElement(Collection<T> coll) {
294        int n;
295        if ((n = coll.size()) <= 0) {
296            return null;
297        }
298        n = nextInt(n);
299        T t = null;
300        Iterator<T> it = coll.iterator();
301        while (n-- >= 0 && it.hasNext())
302            t = it.next();
303        return t;
304    }
305
306    /**
307     * Mutates the array arr by switching the contents at pos1 and pos2.
308     * @param arr an array of T; must not be null
309     * @param pos1 an index into arr; must be at least 0 and no greater than arr.length
310     * @param pos2 an index into arr; must be at least 0 and no greater than arr.length
311     */
312    protected static <T> void swap(T[] arr, int pos1, int pos2) {
313        final T tmp = arr[pos1];
314        arr[pos1] = arr[pos2];
315        arr[pos2] = tmp;
316    }
317
318    /**
319     * Shuffle an array using the Fisher-Yates algorithm and returns a shuffled copy, freshly-allocated, without
320     * modifying elements.
321     * <br>
322     * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>.
323     *
324     * @param elements an array of T; will not be modified
325     * @return a shuffled copy of elements
326     */
327    @Override
328    public <T> T[] shuffle(T[] elements) {
329        final int size = elements.length;
330        final T[] array = Arrays.copyOf(elements, size);
331        for (int i = size; i > 1; i--) {
332            swap(array, i - 1, nextInt(i));
333        }
334        return array;
335    }
336
337    /**
338     * Shuffles an array in-place using the Fisher-Yates algorithm.
339     * If you don't want the array modified, use {@link #shuffle(Object[], Object[])}.
340     * <br>
341     * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>.
342     *
343     * @param elements an array of T; <b>will</b> be modified
344     * @return elements after shuffling it in-place
345     */
346    @Override
347    public <T> T[] shuffleInPlace(T[] elements) {
348        final int size = elements.length;
349        for (int i = size; i > 1; i--) {
350            swap(elements, i - 1, nextInt(i));
351        }
352        return elements;
353    }
354
355    /**
356     * Shuffle an array using the Fisher-Yates algorithm. If possible, create a new array or reuse an existing array
357     * with the same length as elements and pass it in as dest; the dest array will contain the shuffled contents of
358     * elements and will also be returned as-is. If dest does not have the same length as elements, this will throw an
359     * IllegalArgumentException
360     * <br>
361     * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>.
362     *
363     * @param elements an array of T; will not be modified
364     * @param <T>      can be any non-primitive type.
365     * @param dest     Where to put the shuffle. If it does not have the same length as {@code elements}, this will
366     *                 throw an IllegalArgumentException.
367     * @return {@code dest} after modifications
368     */
369    @Override
370    public <T> T[] shuffle(T[] elements, T[] dest) {
371        if (dest.length != elements.length)
372            throw new IllegalArgumentException("Not allowed! In AbstractRNG.shuffle(), elements and dest must not have the same length.");
373        System.arraycopy(elements, 0, dest, 0, elements.length);
374        shuffleInPlace(dest);
375        return dest;
376    }
377
378    /**
379     * Shuffles a {@link Collection} of T using the Fisher-Yates algorithm and returns an ArrayList of T.
380     * <br>
381     * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>.
382     *
383     * @param elements a Collection of T; will not be modified
384     * @return a shuffled ArrayList containing the whole of elements in pseudo-random order.
385     */
386    @Override
387    public <T> ArrayList<T> shuffle(Collection<T> elements) {
388        return shuffle(elements, null);
389    }
390
391    /**
392     * Shuffles a {@link Collection} of T using the Fisher-Yates algorithm and puts it in a buffer.
393     * The result is allocated if {@code buf} is null or if {@code buf} isn't empty,
394     * otherwise {@code elements} is poured into {@code buf}.
395     * <br>
396     * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>.
397     *
398     * @param elements a Collection of T; will not be modified
399     * @param buf      a buffer as an ArrayList that will be filled with the shuffled contents of elements;
400     *                 if null or non-empty, a new ArrayList will be allocated and returned
401     * @return a shuffled ArrayList containing the whole of elements in pseudo-random order, which may be {@code buf}
402     */
403    @Override
404    public <T> ArrayList<T> shuffle(Collection<T> elements, ArrayList<T> buf) {
405        final ArrayList<T> al;
406        if (buf == null || !buf.isEmpty())
407            al = new ArrayList<>(elements);
408        else {
409            al = buf;
410            al.addAll(elements);
411        }
412        final int n = al.size();
413        for (int i = n; i > 1; i--) {
414            Collections.swap(al, nextInt(i), i - 1);
415        }
416        return al;
417    }
418
419    /**
420     * Shuffles a Collection of T items in-place using the Fisher-Yates algorithm.
421     * This only shuffles List data structures.
422     * If you don't want the array modified, use {@link #shuffle(Collection)}, which returns a List as well.
423     * <br>
424     * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>.
425     *
426     * @param elements a Collection of T; <b>will</b> be modified
427     * @return elements after shuffling it in-place
428     */
429    @Override
430    public <T> List<T> shuffleInPlace(List<T> elements) {
431        final int n = elements.size();
432        for (int i = n; i > 1; i--) {
433            Collections.swap(elements, nextInt(i), i - 1);
434        }
435        return elements;
436    }
437
438    /**
439     * Generates a random permutation of the range from 0 (inclusive) to length (exclusive).
440     * Useful for passing to OrderedMap or OrderedSet's reorder() methods.
441     *
442     * @param length the size of the ordering to produce
443     * @return a random ordering containing all ints from 0 to length (exclusive)
444     */
445    @Override
446    public int[] randomOrdering(int length) {
447        if (length <= 0)
448            return new int[0];
449        return randomOrdering(length, new int[length]);
450    }
451
452    /**
453     * Generates a random permutation of the range from 0 (inclusive) to length (exclusive) and stores it in
454     * the dest parameter, avoiding allocations.
455     * Useful for passing to OrderedMap or OrderedSet's reorder() methods.
456     *
457     * @param length the size of the ordering to produce; the smaller of {@code dest.length} and length will be used
458     * @param dest   the destination array; will be modified
459     * @return dest, filled with a random ordering containing all ints from 0 to length (exclusive)
460     */
461    @Override
462    public int[] randomOrdering(int length, int[] dest) {
463        if (dest == null) return null;
464
465        final int n = Math.min(length, dest.length);
466        for (int i = 0; i < n; i++) {
467            dest[i] = i;
468        }
469        for (int i = n - 1; i > 0; i--) {
470            final int r = nextInt(i+1),
471                    t = dest[r];
472            dest[r] = dest[i];
473            dest[i] = t;
474        }
475        return dest;
476    }
477    /**
478     * Gets a random portion of data (an array), assigns that portion to output (an array) so that it fills as much as
479     * it can, and then returns output. Will only use a given position in the given data at most once; uses a Feistel
480     * Network to accomplish this without allocations. Internally, makes 2 calls to {@link #nextInt()}, regardless of
481     * the data being randomized.
482     * <br>
483     * Uses approximately the same code as {@link LowStorageShuffler}, but without any object or array allocations.
484     *
485     * @param data   an array of T; will not be modified.
486     * @param output an array of T that will be overwritten; should always be instantiated with the portion length
487     * @param <T>    can be any non-primitive type.
488     * @return output, after {@code Math.min(output.length, data.length)} unique items have been put into it from data
489     */
490    @Override
491    public <T> T[] randomPortion(T[] data, T[] output) {
492        final int length = data.length, n = Math.min(length, output.length);
493        // calculate next power of 4.  Needed since the balanced Feistel network needs
494        // an even number of bits to work with
495        int pow4 = HashCommon.nextPowerOfTwo(length);
496        pow4 = ((pow4 | pow4 << 1) & 0x55555554) - 1;
497        // calculate our left and right masks to split our indices for the Feistel network
498        final int halfBits = Integer.bitCount(pow4) >>> 1;
499        final int rightMask = pow4 >>> halfBits;
500        final int leftMask = pow4 ^ rightMask;
501        final int key0 = nextInt(), key1 = nextInt();
502        int index = 0;
503        for (int i = 0; i < n; i++) {
504            int shuffleIndex;
505            // index is the index to start searching for the next number at
506            while (index <= pow4)
507            {
508                // break our index into the left and right half
509                int left = (index & leftMask) >>> halfBits;
510                int right = (index & rightMask);
511                // do 2 Feistel rounds
512                int newRight = left ^ (LowStorageShuffler.round(right, key0) & rightMask);
513                left = right;
514                right = newRight;
515                newRight = left ^ (LowStorageShuffler.round(right, key1) & rightMask);
516                shuffleIndex = right << halfBits | newRight;
517                index++;
518
519                // if we found a valid index, return it!
520                if (shuffleIndex < length) {
521                    output[i] = data[shuffleIndex];
522                    break;
523                }
524            }
525        }
526        return output;
527    }
528
529    /**
530     * Creates a copy of this IRNG; it will generate the same random numbers, given the same calls in order, as this
531     * IRNG at the point copy() is called. The copy will not share references with this IRNG. If this IRNG does not
532     * permit copying itself, it is suggested to either throw an {@link UnsupportedOperationException} or return a new
533     * IRNG of the same type but with a random seed, with the latter meant as a partial defense against cheating.
534     * <br>
535     * This is abstract because every implementation is likely to have different specifics for this.
536     * @return a copy of this IRNG
537     */
538    @Override
539    public abstract IRNG copy();
540
541    /**
542     * Gets a view of this IRNG in a way that implements {@link Serializable}, which may simply be this IRNG if it
543     * implements Serializable as well as IRNG.
544     * <br>
545     * For implementors: It is suggested to return an {@link RNG} initialized by calling
546     * {@link RNG#RNG(long)} with {@link #nextLong()} if you are unable to save the current state of this IRNG and the
547     * caller still needs something saved. This won't preserve the current state or the choice of IRNG implementation,
548     * however, so it is simply a last resort in case you don't want to throw an exception.
549     *
550     * @return a {@link Serializable} view of this IRNG or a similar one; may be {@code this}
551     */
552    @Override
553    public abstract Serializable toSerializable();
554}