001package squidpony.squidmath;
002
003import squidpony.StringKit;
004
005import java.io.Serializable;
006
007/**
008 * A quasi-random number generator that goes through one of many sub-random sequences found by J.G. van der Corput.
009 * More specifically, this offers the standard family of van der Corput sequences, each defined by a (almost always
010 * prime) base number. Each sequence only changes the state by incrementing it (this works better in the normal usage as
011 * part of a 2D or 3D point generator). The state is internally stored in a 64-bit long that is incremented once per
012 * generated number. The important things to know about this class are: size of state affects speed (prefer smaller
013 * seeds, but quality is sometimes a bit poor at first if you start at 0); the base (when given) should be prime
014 * (smaller bases tend to yield better quality, but oddly, larger bases perform better); this doesn't generate very
015 * random numbers, and is classified as a quasi-random number generator (which can be good for making points that
016 * should not overlap); this is a StatefulRandomness with an additional method for generating quasi-random doubles,
017 * {@link #nextDouble()}; and there are several static methods offered for convenient generation of points on the
018 * related Halton sequence (as well as faster generation of doubles in the base-2 van der Corput sequence, and a special
019 * method that switches which base it uses depending on the index to seem even less clearly-patterned). There are also,
020 * for lack of a better place to put such small code, methods to generate points in the R2 sequence found by Martin
021 * Roberts, which is very similar in 2D to some Halton sequences but has better separation between points.
022 * <br>
023 * This generator allows a base (also called a radix) that changes the sequence significantly; a base should be prime,
024 * and this performs better in terms of time used with larger primes, though quality is also improved by preferring
025 * primes that aren't very large relative to the quantity of numbers expected to be generated. Unfortunately,
026 * performance is not especially similar to conventional PRNGs; smaller (positive) state values are processed more
027 * quickly than larger ones, or most negative states. At least one 64-bit integer modulus and one 64-bit integer
028 * division are required for any number to be produced, and the amount of both of these relatively-non-cheap operations
029 * increases linearly with the number of digits (in the specified base, which is usually not 10) needed to represent
030 * the current state. Since performance is not optimal, and the results are rather strange anyway relative to PRNGs,
031 * this should not be used as a direct substitute for a typical RandomnessSource (however, it is similar to, but simpler
032 * and faster than, {@link SobolQRNG}). So what's it good for?
033 * <br>
034 * A VanDerCorputSequence can be a nice building block for more complicated quasi-randomness, especially for points in
035 * 2D or 3D. There's a simple way that should almost always "just work" as the static method
036 * {@link #halton(int, int, int, int[])} here. If it doesn't meet your needs, there's a little more complexity involved.
037 * Using a VanDerCorputQRNG with base 3 for the x-axis and another VanDerCorputQRNG with base 5 for the y-axis,
038 * requesting a double from each to make points between (0.0, 0.0) and (1.0, 1.0), has an interesting trait that can be
039 * desirable for many kinds of positioning in 2D: once a point has been generated, an identical point will never be
040 * generated until floating-point precision runs out, but more than that, nearby points will almost never be generated
041 * for many generations, and most points will stay at a comfortable distance from each other if the bases are different
042 * and both prime (or, more technically, if they share no common denominators). This is also known as a Halton sequence,
043 * which is a group of sequences of points instead of simply numbers. The choices of 3 and 5 are examples; any two
044 * different primes will technically work for 2D (as well as any two numbers that share no common factor other than 1,
045 * that is, they are relatively coprime), but patterns can be noticeable with primes larger than about 7, with 11 and 13
046 * sometimes acceptable. Three VanDerCorputQRNG sequences could be used for a Halton sequence of 3D
047 * points, using three different prime bases, four for 4D, etc. SobolQRNG can be used for the same purpose, but the
048 * points it generates are typically more closely-aligned to a specific pattern, the pattern is symmetrical between all
049 * four quadrants of the square between (0.0, 0.0) and (1.0, 1.0) in 2D, and it probably extends into higher dimensions.
050 * Using one of the possible Halton sequences gives some more flexibility in the kinds of random-like points produced.
051 * Oddly, using a base-2 van der Corput sequence as the x axis in a Halton sequence and a base-39 van der Corput
052 * sequence as the y axis results in the greatest minimum distance between points found so far while still involving a
053 * base-2 sequence (which is preferential for performance). There, the minimum distance between the first 65536 points
054 * in the [0,1) range is 0.001147395; a runner-up is a y base of 13, which has a minimum distance of 0.000871727 . The
055 * (2,39) Halton sequence is used by {@link #halton(int, int, int)} and {@link #halton(int, int, int, int[])}.
056 * <br>
057 * Created by Tommy Ettinger on 11/18/2016. Uses code adapted from
058 * <a href="https://blog.demofox.org/2017/05/29/when-random-numbers-are-too-random-low-discrepancy-sequences/">Alan Wolfe's blog</a>,
059 * which turned out to be a lot faster than the previous way I had it implemented.
060 */
061public class VanDerCorputQRNG implements StatefulRandomness, RandomnessSource, Serializable {
062    private static final long serialVersionUID = 6;
063    public long state;
064    public final int base;
065    /**
066     * Constructs a new van der Corput sequence generator with base 7, starting point 37, and scrambling disabled.
067     */
068    public VanDerCorputQRNG()
069    {
070        base = 7;
071        state = 37;
072    }
073
074    /**
075     * Constructs a new van der Corput sequence generator with the given starting point in the sequence as a seed.
076     * Usually seed should be at least 20 with this constructor, but not drastically larger; 2000 is probably too much.
077     * This will use a base 7 van der Corput sequence and have scrambling disabled.
078     * @param seed the seed as a long that will be used as the starting point in the sequence; ideally positive but low
079     */
080    public VanDerCorputQRNG(long seed)
081    {
082        base = 7;
083        state = seed;
084    }
085
086    /**
087     * Constructs a new van der Corput sequence generator with the given base (a.k.a. radix; if given a base less than
088     * 2, this will use base 2 instead) and starting point in the sequence as a seed. Good choices for base are between
089     * 10 and 60 or so, and should usually be prime. Good choices for seed are larger than base but not by very much,
090     * and should generally be positive at construction time.
091     * @param base the base or radix used for this VanDerCorputQRNG; for most uses this should be prime but small-ish
092     * @param seed the seed as a long that will be used as the starting point in the sequence; ideally positive but low
093     */
094    public VanDerCorputQRNG(int base, long seed)
095    {
096        this.base = Math.max(base, 2);
097        state = seed;
098    }
099
100    /**
101     * Gets the next quasi-random long as a fraction of {@link Long#MAX_VALUE}; this can never produce a negative value.
102     * It is extremely unlikely to produce two identical values unless the state is very high or is negative; state
103     * increases by exactly 1 each time this, {@link #next(int)}, or {@link #nextDouble()} is called and can potentially
104     * wrap around to negative values after many generations.
105     * @return a quasi-random non-negative long; may return 0 rarely, probably can't return {@link Long#MAX_VALUE}
106     */
107    @Override
108    public long nextLong() {
109        long n = ++state & 0x7fffffffffffffffL;
110        if(base <= 2) {
111            return Long.reverse(n) >>> 1;
112        }
113        double denominator = base, res = 0.0;
114        while (n > 0)
115        {
116            res += (n % base) / denominator;
117            n /= base;
118            denominator *= base;
119        }
120        return (long) (res * Long.MAX_VALUE);
121    }
122
123    @Override
124    public int next(int bits) {
125        return (int)(nextLong()) >>> (32 - bits);
126    }
127
128    /**
129     * Gets the next quasi-random double from between 0.0 and 1.0 (normally both exclusive; only if state is negative or
130     * has wrapped around to a negative value can 0.0 ever be produced). It should be nearly impossible for this to
131     * return the same number twice unless floating-point precision has been exhausted or a very large amount of numbers
132     * have already been generated. Certain unusual bases may make this more likely.
133     * @return a quasi-random double that will always be less than 1.0 and will be no lower than 0.0
134     */
135    public double nextDouble() {
136        long n = ++state & 0x7fffffffffffffffL;
137        if(base <= 2) {
138            return (Long.reverse(n) >>> 11) * 0x1p-53;
139        }
140        double denominator = base, res = 0.0;
141        while (n > 0)
142        {
143            res += (n % base) / denominator;
144            n /= base;
145            denominator *= base;
146        }
147        return res;
148    }
149
150    @Override
151    public VanDerCorputQRNG copy() {
152        return new VanDerCorputQRNG(base, state);
153    }
154
155    @Override
156    public long getState() {
157        return state;
158    }
159
160    @Override
161    public void setState(long state) {
162        this.state = state;
163    }
164
165    @Override
166    public String toString() {
167        return "VanDerCorputQRNG with base " + base +
168                " and state 0x" + StringKit.hex(state) + "L";
169    }
170
171    @Override
172    public boolean equals(Object o) {
173        if (this == o) return true;
174        if (o == null || getClass() != o.getClass()) return false;
175
176        VanDerCorputQRNG that = (VanDerCorputQRNG) o;
177
178        return state == that.state && base == that.base;
179
180    }
181
182    @Override
183    public int hashCode() {
184        int result = (int) (state ^ (state >>> 32));
185        result = 31 * result + base | 0;
186        return 31 * result | 0;
187    }
188
189    /**
190     * Convenience method that gets a quasi-random 2D point between integer (0,0) inclusive and (width,height)
191     * exclusive and fills it into point. This is roughly equivalent to creating two VanDerCorputQRNG generators, one
192     * with {@code new VanDerCorputQRNG(2, index)} and the other with
193     * {@code new VanDerCorputQRNG(39, index)}, then getting an x-coordinate from the first with
194     * {@code (int)(nextDouble() * width)} and similarly for y with the other generator. The advantage here is you don't
195     * actually create any objects using this static method, only assigning to point, if valid. You might find an
196     * advantage in using values for index that start higher than 20 or so, but you can pass sequential values for index
197     * and generally get points that won't be near each other; this is not true for all parameters to Halton sequences,
198     * but it is true for this one.
199     * @param width the maximum exclusive bound for the x-positions (index 0) of points this can return
200     * @param height the maximum exclusive bound for the y-positions (index 1) of points this can return
201     * @param index an int that, if unique, positive, and not too large, will usually result in unique points
202     * @param point an int array that will be modified; should have length 2; if null or too small, a new array will be created
203     * @return point after modifications to the first two items, or a new array if point is null or too small
204     */
205    public static int[] halton(int width, int height, int index, int[] point)
206    {
207        if(point == null || point.length < 2)
208            point = new int[2];
209
210        double denominator = 39.0, resY = 0.0;
211        int n = (index+1 & 0x7fffffff);
212        while (n > 0)
213        {
214            resY += (n % 39) / denominator;
215            n /= 39;
216            denominator *= 39.0;
217        }
218        point[0] = (int)(width * (Integer.reverse(index + 1) >>> 1) * 0x1p-31);
219        point[1] = (int)(resY * height);
220        return point;
221    }
222    /**
223     * Convenience method that gets a quasi-random Coord between integer (0,0) inclusive and (width,height) exclusive
224     * and gets the corresponding Coord from the Coord pool. This is roughly equivalent to creating two VanDerCorputQRNG
225     * generators, one with {@code new VanDerCorputQRNG(2, index)} and the other with
226     * {@code new VanDerCorputQRNG(39, index)}, then getting an x-coordinate from the first with
227     * {@code (int)(nextDouble() * width)} and similarly for y with the other generator. You might find an advantage in
228     * using values for index that start higher than 20 or so, but you can pass sequential values for index and
229     * generally get points that won't be near each other; this is not true for all parameters to Halton sequences, but
230     * it is true for this one.
231     * @param width the maximum exclusive bound for the x-positions (index 0) of points this can return
232     * @param height the maximum exclusive bound for the y-positions (index 1) of points this can return
233     * @param index an int that, if unique, positive, and not too large, will usually result in unique points
234     * @return point after modifications to the first two items, or a new array if point is null or too small
235     */
236    public static Coord halton(int width, int height, int index)
237    {
238        return halton(width, height, 0, 0, index);
239    }
240    /**
241     * Convenience method that gets a quasi-random Coord between integer (0,0) inclusive and (width,height) exclusive
242     * and gets the corresponding Coord from the Coord pool. This is roughly equivalent to creating two VanDerCorputQRNG
243     * generators, one with {@code new VanDerCorputQRNG(2, index)} and the other with
244     * {@code new VanDerCorputQRNG(39, index)}, then getting an x-coordinate from the first with
245     * {@code (int)(nextDouble() * width)} and similarly for y with the other generator. You might find an advantage in
246     * using values for index that start higher than 20 or so, but you can pass sequential values for index and
247     * generally get points that won't be near each other; this is not true for all parameters to Halton sequences, but
248     * it is true for this one.
249     * @param width the width of the area this can cover
250     * @param height the height of the area this can cover
251     * @param xOffset the lowest x-coordinate this can produce, and also added to width to get the upper bound on x
252     * @param yOffset the lowest y-coordinate this can produce, and also added to height to get the upper bound on y
253     * @param index an int that, if unique, positive, and not too large, will usually result in unique points
254     * @return point after modifications to the first two items, or a new array if point is null or too small
255     */
256    public static Coord halton(int width, int height, int xOffset, int yOffset, int index)
257    {
258        double denominator = 39.0, resY = 0.0;
259        int n = (index+1 & 0x7fffffff);
260        while (n > 0)
261        {
262            resY += (n % 39) / denominator;
263            n /= 39;
264            denominator *= 39.0;
265        }
266        return Coord.get((int)(width * (Integer.reverse(index + 1) >>> 1) * 0x1p-31) + xOffset, (int)(resY * height) + yOffset);
267    }
268
269    /**
270     * Convenience method that gets a quasi-random 3D point between integer (0,0,0) inclusive and (width,height,depth)
271     * exclusive. This is roughly equivalent to creating three VanDerCorputQRNG generators, one with
272     * {@code new VanDerCorputQRNG(2, index)} another with {@code new VanDerCorputQRNG(3, index)},
273     * and another with {@code new VanDerCorputQRNG(5, index)}, then getting an x-coordinate from the first with
274     * {@code (int)(nextDouble() * width)} and similarly for y and z with the other generators. The advantage here is
275     * you don't actually create any objects using this static method, only assigning to point, if valid. You might find
276     * an advantage in using values for index that start higher than 20 or so, but you can pass sequential values for
277     * index and generally get points that won't be near each other; this is not true for all parameters to Halton
278     * sequences, but it is true for this one.
279     * @param width the maximum exclusive bound for the x-positions (index 0) of points this can return
280     * @param height the maximum exclusive bound for the y-positions (index 1) of points this can return
281     * @param depth the maximum exclusive bound for the z-positions (index 2) of points this can return
282     * @param index an int that, if unique, positive, and not too large, will usually result in unique points
283     * @param point an int array that will be modified; should have length 3; if null or too small, a new array will be created
284     * @return point after modifications to the first two items, or a new array if point is null or too small
285     */
286    public static int[] halton(int width, int height, int depth, int index, int[] point)
287    {
288        if(point == null || point.length < 3)
289            point = new int[3];
290
291        double denominator = 3.0, resY = 0.0, resZ = 0.0;
292        int n = (index+1 & 0x7fffffff);
293        while (n > 0)
294        {
295            resY += (n % 3) / denominator;
296            n /= 3;
297            denominator *= 3.0;
298        }
299
300        denominator = 5;
301        n = (index+1 & 0x7fffffff);
302        while (n > 0)
303        {
304            resZ += (n % 5) / denominator;
305            n /= 5;
306            denominator *= 5.0;
307        }
308        point[0] = (int)(width * (Integer.reverse(index + 1) >>> 1) * 0x1p-31);
309        point[1] = (int)(resY * height);
310        point[2] = (int)(resZ * depth);
311        return point;
312    }
313
314    /**
315     * Convenience method that gets a quasi-random Coord3D between integer (0,0,0) inclusive and (width,height,depth)
316     * exclusive. This is roughly equivalent to creating three VanDerCorputQRNG generators, one with
317     * {@code new VanDerCorputQRNG(2, index)} another with {@code new VanDerCorputQRNG(3, index)},
318     * and another with {@code new VanDerCorputQRNG(5, index)}, then getting an x-coordinate from the first with
319     * {@code (int)(nextDouble() * width)} and similarly for y and z with the other generators. This overload always
320     * creates a new Coord3D object, so you might prefer {@link #halton(int, int, int, int, int[])}, which can reuse an
321     * int array. You might find an advantage in using values for index that start higher than 20 or so, but you can
322     * pass sequential values for index and generally get points that won't be near each other; this is not true for all
323     * parameters to Halton sequences, but it is true for this one.
324     * @param width the maximum exclusive bound for the x-positions (index 0) of points this can return
325     * @param height the maximum exclusive bound for the y-positions (index 1) of points this can return
326     * @param depth the maximum exclusive bound for the z-positions (index 2) of points this can return
327     * @param index an int that, if unique, positive, and not too large, will usually result in unique points
328     * @return a new Coord3D with x,y,z between 0,0,0 (inclusive) and width,height,depth (exclusive)
329     */
330    public static Coord3D halton(int width, int height, int depth, int index)
331    {
332        double denominator = 3.0, resY = 0.0, resZ = 0.0;
333        int n = (index+1 & 0x7fffffff);
334        while (n > 0)
335        {
336            resY += (n % 3) / denominator;
337            n /= 3;
338            denominator *= 3.0;
339        }
340
341        denominator = 5;
342        n = (index+1 & 0x7fffffff);
343        while (n > 0)
344        {
345            resZ += (n % 5) / denominator;
346            n /= 5;
347            denominator *= 5.0;
348        }
349        return new Coord3D((int)(width * (Integer.reverse(index + 1) >>> 1) * 0x1p-31),
350                (int)(resY * height),
351                (int)(resZ * depth));
352    }
353
354    /**
355     * Convenience method to get a double from the van der Corput sequence with the given {@code base} at the requested
356     * {@code index} without needing to construct a VanDerCorputQRNG. You should use a prime number for base; 2, 3, 5,
357     * and 7 should be among the first choices to ensure optimal quality unless you are scrambling the index yourself.
358     * If speed is the priority, then larger prime bases counter-intuitively perform better than small ones; 0x1337,
359     * 0xDE4D, 0x510B and 0xACED are all probable primes (using {@link java.math.BigInteger#isProbablePrime(int)}) that
360     * may do well here for speed but will likely require some basic scrambling of the index order. This method on its
361     * own does not perform any scrambling on index other than incrementing it and ensuring it is positive (by
362     * discarding the sign bit; for all positive index values other than 0x7FFFFFFF, this has no effect). If you want
363     * to quickly scramble an int index {@code i} for this purpose, try
364     * {@code (i ^ (i << 7 | i >>> 25) ^ (i << 19 | i >>> 13))}, which may compile to SSE instructions on recent 
365     * desktop processors and won't risk losing precision on GWT.
366     * <br>
367     * Uses the same algorithm as {@link #determine2(int)} when base is 2, which should offer some speed improvement.
368     * The other bases use code adapted from
369     * <a href="https://blog.demofox.org/2017/05/29/when-random-numbers-are-too-random-low-discrepancy-sequences/">Alan Wolfe's blog</a>,
370     * which turned out to be a lot faster than the previous way I had it implemented.
371     * @param base a prime number to use as the base/radix of the van der Corput sequence
372     * @param index the position in the sequence of the requested base, as a non-negative int
373     * @return a quasi-random double between 0.0 (inclusive) and 1.0 (exclusive).
374     */
375    public static double determine(final int base, final int index)
376    {
377        if(base <= 2) {
378            return (Integer.reverse(index + 1) >>> 1) * 0x1p-31;
379        }
380        double denominator = base, res = 0.0;
381        int n = (index+1 & 0x7fffffff);
382        while (n > 0)
383        {
384            res += (n % base) / denominator;
385            n /= base;
386            denominator *= base;
387        }
388        return res;
389    }
390
391    /**
392     * Convenience method to get a double from the van der Corput sequence with the base 2 at the requested
393     * {@code index} without needing to construct a VanDerCorputQRNG. This does not perform any scrambling on index
394     * other than incrementing it and ensuring it is positive (by discarding the sign bit; for all positive index values
395     * other than 0x7FFFFFFF ({@link Integer#MAX_VALUE}), this has no effect).
396     * <br>
397     * Because binary manipulation of numbers is easier and more efficient, the technique used by this method is also
398     * used by {@link #determine(int, int)} when base is 2, and should be faster than other bases.
399     * @param index the position in the base-2 van der Corput sequence, as a non-negative int
400     * @return a quasi-random double between 0.0 (inclusive) and 1.0 (exclusive).
401     */
402    public static double determine2(int index)
403    {
404        return (Integer.reverse(index + 1) >>> 1) * 0x1p-31;
405    }
406    /**
407     * Method to get a double from the van der Corput sequence with the base 2 at a scrambling of the requested
408     * {@code index} without needing to construct a VanDerCorputQRNG. This performs different scrambling on index
409     * than the instance methods on this class perform, and it seems to do well enough while being a little simpler.
410     * This is meant to be usable as an alternative to a different base for a van der Corput sequence when you need two
411     * different sequences, and are already using base 2 via {@link #determine2(int)}.
412     * <br>
413     * Because binary manipulation of numbers is easier and more efficient, this method should be somewhat faster than
414     * the alternatives, like {@link #determine(int, int)} with base 2. It should take only slightly longer to run than
415     * {@link #determine2(int)}, due to the brief amount of time needed to scramble the index.
416     * @param index the position in the sequence of the requested base
417     * @return a quasi-random double between 0.0 (inclusive) and 1.0 (exclusive).
418     */
419    public static double determine2_scrambled(int index)
420    {
421        return (Integer.reverse(++index ^ (index << 7 | index >>> 25) ^ (index << 19 | index >>> 13)) >>> 1) * 0x1p-31;
422    }
423
424    private static final int[] lowPrimes = {2, 3, 2, 3, 5, 2, 3, 2};
425
426    /**
427     * Chooses one sequence from the van der Corput sequences with bases 2, 3, and 5, where 5 is used 1/8 of the time,
428     * 3 is used 3/8 of the time, and 2 is used 1/2 of the time, and returns a double from the chosen sequence at the
429     * specified {@code index}. The exact setup used for the choice this makes is potentially fragile, but in certain
430     * circumstances this does better than {@link SobolQRNG} at avoiding extremely close values (the kind that overlap
431     * on actual maps). Speed is not a concern here; this should be very much fast enough for the expected usage in
432     * map generation (it's used in {@link GreasedRegion#quasiRandomSeparated(double)}.
433     * @param index the index to use from one of the sequences; will also be used to select sequence
434     * @return a double from 0.0 (inclusive, but extremely rare) to 1.0 (exclusive); values will tend to spread apart
435     */
436    public static double determineMixed(int index)
437    {
438        return determine(lowPrimes[index & 7], index);
439    }
440
441    /**
442     * Given any int (0 is allowed), this gets a somewhat-sub-random float from 0.0 (inclusive) to 1.0 (exclusive)
443     * using the same implementation as {@link NumberTools#randomFloat(long)} but with index alterations. Only "weak"
444     * because it lacks the stronger certainty of subsequent numbers being separated that the Van der Corput sequence
445     * has. Not actually sub-random, but should be distributed fairly well (internally uses {@link ThrustAltRNG}'s
446     * algorithm, which does not guarantee that its outputs are unique).
447     * <br>
448     * Not all int values for index will produce unique results, since this produces a float and there are less distinct
449     * floats between 0.0 and 1.0 than there are all ints (1/512 as many floats in that range as ints, specifically).
450     * It should take a while calling this method before you hit an actual collision.
451     * @param index any int
452     * @return a float from 0.0 (inclusive) to 1.0 (exclusive) that should not be closely correlated to index
453     */
454    public static float weakDetermine(final int index)
455    {
456        return NumberTools.randomFloat((index >>> 19 | index << 13) ^ 0x13A5BA1D);
457        //return NumberTools.longBitsToDouble(0x3ff0000000000000L | ((index<<1|1) * 0x9E3779B97F4A7C15L * ~index
458        //        - ((index ^ ~(index * 11L)) * 0x632BE59BD9B4E019L)) >>> 12) - 1.0;
459        //return NumberTools.setExponent(
460        //        (NumberTools.setExponent((index<<1|1) * 0.618033988749895, 0x3ff))
461        //                * (0x232BE5 * (~index)), 0x3ff) - 1.0;
462    }
463
464    /**
465     * Like {@link #weakDetermine(int)}, but returns a float between -1.0f and 1.0f, exclusive on both. Uses
466     * {@link NumberTools#randomSignedFloat(long)} internally but alters the index parameter so calls with nearby values
467     * for index are less likely to have nearby results.
468     * @param index any int
469     * @return a sub-random float between -1.0f and 1.0f (both exclusive, unlike some other methods)
470     */
471    public static float weakSignedDetermine(final int index) {
472        return NumberTools.randomSignedFloat((index >>> 19 | index << 13) ^ 0x13A5BA1D);
473    }
474
475    /**
476     * Similar to {@link #determine(int, int)}, but can take bases that aren't prime and can sometimes produce a
477     * Halton-like sequence with almost-as-good distance between points. The base is allowed to be any odd long, 
478     * (negative bases are allowed). The index can technically also be negative, and if this is given 0 it will not
479     * return any specific number (it will vary with the base). This returns a double between 0.0 inclusive and 1.0
480     * exclusive. Better results have been found with larger bases (points tend to be more spread out). It is never as
481     * good at spreading out 2D points as a 2,3 Halton sequence, at least for any bases tried so far.
482     * <br>
483     * Earlier versions of this method wound up only producing points on parallel lines in 2D, never placing points in
484     * between those lines. This sometimes formed a hex-like grid that, as hexagons do, has optimal packing properties,
485     * which made the optimal distance seem very good despite the points having a clear pattern. This can still
486     * sometimes be useful; when you want optimal distance and don't have a case where a clear pattern on a grid is an
487     * issue, it can have high performance. The code for the old way is small, though not simple:
488     * {@code ((base * Integer.reverse(index) << 21) & 0x1fffffffffffffL) * 0x1p-53}, where base is an odd long and
489     * index is any int. It works best in one dimension.
490     * @param base any odd long
491     * @param index any int
492     * @return a double between 0.0 inclusive and 1.0 exclusive
493     */
494    public static double altDetermine(long base, final int index) { return (((base = (Long.reverse(base + index) ^ 0x5851F42D4C957F2DL) * 0x14057B7EF767814BL) >>> 11) ^ (base >>> 13) ^ (base >>> 14)) * 0x1p-53; }
495//    public static double altDetermine(long base, final int index) { return ((((index * 0x5851F42D4C957F2DL + base) * 0x5851F42D4C957F2DL + base) * 0x5851F42D4C957F2DL + base) >>> 11) * 0x1p-53; }
496
497    /**
498     * A quasi-random number generator of doubles between 0.0 inclusive and 1.0 exclusive, but that has issues when it
499     * would be used like a Halton sequence. Only ideal in 1D, this produces well-separated points that are aligned to
500     * parallel hyperplanes when called with different bases and each base used as an axis for more than 1 dimension.
501     * This can produce points with more separation in 2D than a Halton sequence can, but not often. Two bases that do
502     * this when used together are the ints 0xDE4DBEEF and 0x1337D00D (or in decimal, -565330193 and 322424845; note
503     * that 0xDE4DBEEF is a negative integer); they were tried as a gimmick but nothing else turned out better. They do
504     * still produce points on parallel lines, and like all bases, never points between those lines.
505     * <br>
506     * Note, the source of this method is one line, and you may see benefits from copying that code into the call-site
507     * with minor modifications. This returns
508     * {@code (((base * Integer.reverse(index)) << 21) & 0x1fffffffffffffL) * 0x1p-53;}, where base is a long and index
509     * is an int (as in the method signature). The multiplier 0x1p-53 is a very small hexadecimal double literal, using
510     * the same syntax as other parts of SquidLib use for packed floats; using this helps avoid precision loss. If you
511     * want a range larger than 0.0 to 1.0, you can change the multiplier {@code 0x1p-53} to some other constant, like
512     * declaring {@code final double upTo100 = 0x1p-53 * 100.0} before some code that wants quasi-random numbers between
513     * 0.0 inclusive and 100.0 exclusive, then using
514     * {@code (((base * Integer.reverse(index)) << 21) & 0x1fffffffffffffL) * upTo100;} to get those numbers. It isn't
515     * precise to use this technique to get numbers with an upper bound less than 1.0, because 0x1p-53 is about as small
516     * as a double can get with precision intact. In that case, you can use
517     * {@code (((base * Integer.reverse(index)) << 8) & 0xffffffffffL) * smallBound;} where smallBound has been declared
518     * as {@code final double smallBound = 0x1p-40 * 0.05;} (where 0.05 can be switched out for any double between
519     * 1.0/8192.0 and 1.0).
520     * @param base any odd long; the most significant 21 bits (except the sign bit) are effectively ignored
521     * @param index any int; if 0 this will return 0
522     * @return a double between 0.0 inclusive and 1.0 exclusive
523     */
524    public static double planarDetermine(long base, final int index) { return ((base * Integer.reverse(index) << 21) & 0x1fffffffffffffL) * 0x1p-53; }
525
526    /**
527     * Samples a quasi-random Coord sequence that is almost unique to the given seed, getting a Coord with x between
528     * xOffset (inclusive) and width + xOffset (exclusive), y between yOffset (inclusive) and height + yOffset
529     * (exclusive). The seed is "almost" unique because even seeds are discouraged; there is an identical sequence for
530     * every even seed produced by some odd seed. This generates a not-very random number, reverses its bits as other
531     * methods in this class do, then treats that single 32-bit int as two coordinates on a Z-order curve to get
532     * separate x and y from them. In practice these Coords are very well-dispersed if only a small amount are sampled
533     * and all the index values are close-by, and get closer together as more are sampled. Unlike the Halton sequence,
534     * this has very different results with different seeds (Halton only allows bases to be changed), and doesn't
535     * involve any division, modulus, conditionals, or loops.
536     * @param seed an int seed that should be an odd number
537     * @param width the width of the area this can cover
538     * @param height the height of the area this can cover
539     * @param xOffset the lowest x-coordinate this can produce, and also added to width to get the upper bound on x
540     * @param yOffset the lowest y-coordinate this can produce, and also added to height to get the upper bound on y
541     * @param index the index in the sequence, almost always a positive int that increases by 1 with each call
542     * @return a Coord between (xOffset, yOffset) inclusive and (width+xOffset, height+yOffset) exclusive
543     */
544    public static Coord haltoid(int seed, int width, int height, int xOffset, int yOffset, int index)
545    {
546        int morton = GreasedRegion.disperseBits(Integer.reverse((seed * 0x2C9277B5 | 1) * (index + 1)));
547        return Coord.get((int)(width * ((morton & 0xffff) * 0x1p-16)) + xOffset, (int)(((morton >>> 16) * 0x1p-16) * height) + yOffset);
548    }
549    /**
550     * Martin Roberts' "unreasonably effective" quasi-random int sequence based on the golden ratio.
551     * See <a href="http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/">his blog</a> for
552     * more detailed info, but this can be summarized as being extremely good at separating outputs at the expense of
553     * seeming less random. Produces an int between offset (inclusive) and offset + span (exclusive), with the int at
554     * each {@code index} likely to be different for at least {@code span / 4} indices (very low spans may offer less of
555     * a guarantee).
556     * <br>
557     * Note, use {@link #roberts(int, int, int, int, int)} for 2D points and this method for 1D values; the same
558     * properties won't be preserved if you use a 1D Roberts sequence in 2D.
559     * @param span the size of the range this can return
560     * @param offset the minimum value this can return
561     * @param index the index of the int in the 1D Roberts sequence; should be greater than 0, but not required to be
562     * @return an int between offset inclusive and offset+span exclusive
563     */
564    public static int roberts(int span, int offset, int index)
565    {
566        return (int)((index * 0x9E3779B9L & 0xFFFFFFFFL) * span >>> 32) + offset;
567    }
568    
569    /**
570     * Martin Roberts' "unreasonably effective" quasi-random point sequence based on a 2D analogue to the golden ratio.
571     * See <a href="http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/">his blog</a> for
572     * more detailed info, but this can be summarized as being extremely good at separating points at the expense of
573     * seeming less random. Produces a Coord with x between xOffset (inclusive) and xOffset + width (exclusive), and y
574     * between yOffset (inclusive) and yOffset + height (exclusive), with the Coord at each {@code index} likely to be
575     * different for at least {@code width * height / 4} indices (very low sizes may offer less of a guarantee).
576     * @param width the x-size of the space this can place a Coord
577     * @param height the y-size of the space this can place a Coord
578     * @param xOffset the minimum x-position of a Coord
579     * @param yOffset the minimum y-position of a Coord
580     * @param index the index of the Coord in the 2D Roberts sequence; should be greater than 0, but not required to be
581     * @return a Coord with x,y between xOffset,yOffset inclusive and xOffset+width,yOffset+height exclusive
582     */
583    public static Coord roberts(int width, int height, int xOffset, int yOffset, int index)
584    {
585        return Coord.get(
586        (int)((index * 0xC13FA9A9L & 0xFFFFFFFFL) * width  >>> 32) + xOffset,
587        (int)((index * 0x91E10DA5L & 0xFFFFFFFFL) * height >>> 32) + yOffset);
588    }
589}