001package squidpony.squidmath;
002
003import squidpony.StringKit;
004
005import java.io.Serializable;
006
007/**
008 * An IRNG implementation that is meant to provide random numbers very quickly when targeting GWT but also to produce
009 * the same numbers when used on desktop, Android, or other platforms, and that can have its state read as a
010 * StatefulRandomness. This uses the same algorithm as {@link Starfish32RNG}, which means it has two 32-bit ints for
011 * state and a period of 0xFFFFFFFFFFFFFFFF (2 to the 64 minus 1), while passing 32TB of PractRand tests without any
012 * failures or anomalies (so its quality is very good). This previously used {@link Lathe32RNG}'s algorithm, which is a
013 * tiny bit faster on desktop and a fair amount faster on GWT, but can't produce all long values and produces some more
014 * often than others. Unlike {@link RNG}, there is no RandomnessSource that can be swapped out, but also somewhat less 
015 * indirection on common calls like {@link #nextInt()} and {@link #nextFloat()}. Although this implements
016 * {@link StatefulRandomness}, it is not recommended to use this as the RandomnessSource for a StatefulRNG; you should
017 * use {@link Starfish32RNG} if you want the larger API provided by StatefulRNG and/or RNG while keeping similar, though
018 * probably slightly weaker, GWT performance relative to this class. Any performance measurements on GWT depend heavily
019 * on the browser; in some versions of Chrome and Chromium, this performs almost exactly as well as Lathe32RNG, but in
020 * newer versions it lags behind by a small factor. It tends to be very fast in the current Firefox (September 2018).
021 * <br>
022 * Be advised: if you subtract {@code 0x9E3779BD} from every output, that modified output will fail some tests reliably.
023 * Similar numbers may also cause this result, though it isn't clear if this is ever relevant in actual usage. Part of
024 * the reason Lathe32RNG was switched out was because its behavior on {@link #between(int, int)} was poor, but it
025 * doesn't seem to be for this version.
026 * <br>
027 * <a href="http://xoshiro.di.unimi.it/xoroshiro64starstar.c">Original version here for xoroshiro64**</a>.
028 * <br>
029 * Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
030 * Ported and modified in 2018 and 2019 by Tommy Ettinger
031 * @author Sebastiano Vigna
032 * @author David Blackman
033 * @author Tommy Ettinger (if there's a flaw, use SquidLib's issues and don't bother Vigna or Blackman, the algorithm here has been adjusted from their work)
034 */
035public final class GWTRNG extends AbstractRNG implements IStatefulRNG, Serializable {
036    private static final long serialVersionUID = 3L;
037
038    public int stateA, stateB;
039
040    /**
041     * Creates a new generator seeded using two calls to Math.random().
042     */
043    public GWTRNG()
044    {
045        setState((int)((Math.random() * 2.0 - 1.0) * 0x80000000), (int)((Math.random() * 2.0 - 1.0) * 0x80000000));
046    }
047    /**
048     * Constructs this GWTRNG by dispersing the bits of seed using {@link #setSeed(int)} across the two parts of state
049     * this has.
050     * @param seed an int that won't be used exactly, but will affect both components of state
051     */
052    public GWTRNG(final int seed) {
053        setSeed(seed);
054    }
055    /**
056     * Constructs this GWTRNG by splitting the given seed across the two parts of state this has with
057     * {@link #setState(long)}.
058     * @param seed a long that will be split across both components of state
059     */
060    public GWTRNG(final long seed) {
061        setState(seed);
062    }
063    /**
064     * Constructs this GWTRNG by calling {@link #setState(int, int)} on stateA and stateB as given; see that method
065     * for the specific details (stateA and stateB are kept as-is unless they are both 0).
066     * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0
067     * @param stateB the number to use as the second part of the state
068     */
069    public GWTRNG(final int stateA, final int stateB) {
070        setState(stateA, stateB);
071    }
072
073    /**
074     * Hashes {@code seed} using both {@link CrossHash#hash(CharSequence)} and {@link String#hashCode()} and uses those
075     * two results as the two states with {@link #setState(int, int)}. If seed is null, this won't call
076     * String.hashCode() on it and will instead use 1 as that state (to avoid the forbidden double-zero case).
077     * @param seed any String; may be null
078     */
079    public GWTRNG(final String seed) {
080        setState(CrossHash.hash(seed), seed == null ? 1 : seed.hashCode());
081    }
082
083    /**
084     * Get up to 32 bits (inclusive) of random output; the int this produces
085     * will not require more than {@code bits} bits to represent.
086     *
087     * @param bits an int between 1 and 32, both inclusive
088     * @return a random number that fits in the specified number of bits
089     */
090    @Override
091    public final int next(int bits) {
092        final int s0 = stateA;
093        final int s1 = stateB ^ s0;
094        final int result = s0 * 31;
095        stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
096        stateB = (s1 << 13 | s1 >>> 19);
097        return (result << 28 | result >>> 4) + 0x9E3779BD >>> (32 - bits);
098    }
099
100    /**
101     * Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive).
102     *
103     * @return a 32-bit random int.
104     */
105    @Override
106    public final int nextInt() {
107        final int s0 = stateA;
108        final int s1 = stateB ^ s0;
109        final int result = s0 * 31;
110        stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
111        stateB = (s1 << 13 | s1 >>> 19);
112        return (result << 28 | result >>> 4) + 0x9E3779BD;
113    }
114    /**
115     * Returns a random non-negative integer below the given bound, or 0 if the bound is 0 or
116     * negative.
117     *
118     * @param bound the upper bound (exclusive)
119     * @return the found number
120     */
121    @Override
122    public final int nextInt(final int bound) {
123        final int s0 = stateA;
124        final int s1 = stateB ^ s0;
125        final int result = s0 * 31;
126        stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
127        stateB = (s1 << 13 | s1 >>> 19);
128        return (int) ((bound * ((result << 28 | result >>> 4) + 0x9E3779BD & 0xFFFFFFFFL)) >>> 32) & ~(bound >> 31);
129    }
130
131    /**
132     * Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive).
133     *
134     * @return a 64-bit random long.
135     */
136    @Override
137    public final long nextLong() {
138        int s0 = stateA;
139        int s1 = stateB ^ s0;
140        final int high = s0 * 31;
141        s0 = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
142        s1 = (s1 << 13 | s1 >>> 19) ^ s0;
143        final int low = s0 * 31;
144        stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
145        stateB = (s1 << 13 | s1 >>> 19);
146        return ((high << 28 | high >>> 4) + 0x9E3779BDL) << 32
147                | ((low << 28 | low >>> 4) + 0x9E3779BD & 0xFFFFFFFFL);
148    }
149
150    /**
151     * Get a random bit of state, interpreted as true or false with approximately equal likelihood.
152     * This implementation uses a sign check as a safeguard, since its algorithm is based on (but is not equivalent to)
153     * xoroshiro, which recommends a sign check instead of using the least significant bit.
154     *
155     * @return a random boolean.
156     */
157    @Override
158    public final boolean nextBoolean() {
159        final int s0 = stateA;
160        final int s1 = stateB ^ s0;
161        stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
162        stateB = (s1 << 13 | s1 >>> 19);
163        return (s0 * 31 & 8) == 8; // same effect as a sign check if this was rotated as normal
164    }
165
166    /**
167     * Gets a random double between 0.0 inclusive and 1.0 exclusive.
168     * This returns a maximum of 0.9999999999999999 because that is the largest double value that is less than 1.0 .
169     *
170     * @return a double between 0.0 (inclusive) and 0.9999999999999999 (inclusive)
171     */
172    @Override
173    public final double nextDouble() {
174        int s0 = stateA;
175        int s1 = stateB ^ s0;
176        final int high = s0 * 31;
177        s0 = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
178        s1 = (s1 << 13 | s1 >>> 19) ^ s0;
179        final int low = s0 * 31;
180        stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
181        stateB = (s1 << 13 | s1 >>> 19);
182        return  ((((high << 28 | high >>> 4) + 0x9E3779BDL) << 32
183                | ((low << 28 | low >>> 4) + 0x9E3779BD & 0xFFFFFFFFL))
184                & 0x1FFFFFFFFFFFFFL) * 0x1p-53;
185    }
186
187    /**
188     * Gets a random float between 0.0f inclusive and 1.0f exclusive.
189     * This returns a maximum of 0.99999994 because that is the largest float value that is less than 1.0f .
190     *
191     * @return a float between 0f (inclusive) and 0.99999994f (inclusive)
192     */
193    @Override
194    public final float nextFloat() {
195        final int s0 = stateA;
196        final int s1 = stateB ^ s0;
197        final int result = s0 * 31;
198        stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9);
199        stateB = (s1 << 13 | s1 >>> 19);
200        return ((result << 28 | result >>> 4) + 0x9E3779BD & 0xffffff) * 0x1p-24f;
201    }
202
203    /**
204     * Creates a copy of this GWTRNG; it will generate the same random numbers, given the same calls in order, as this
205     * GWTRNG at the point copy() is called. The copy will not share references with this GWTRNG.
206     * 
207     * @return a copy of this GWTRNG
208     */
209    @Override
210    public GWTRNG copy() {
211        return new GWTRNG(stateA, stateB);
212    }
213
214    /**
215     * Gets a view of this IRNG in a way that implements {@link Serializable}, which is simply this IRNG.
216     * @return a {@link Serializable} view of this IRNG or a similar one; always {@code this}
217     */
218    @Override
219    public Serializable toSerializable() {
220        return this;
221    }
222    /**
223     * Sets the state of this generator using one int, running it through Zog32RNG's algorithm two times to get 
224     * two ints. If the states would both be 0, state A is assigned 1 instead.
225     * @param seed the int to use to produce this generator's state
226     */
227    public void setSeed(final int seed) {
228        int z = seed + 0xC74EAD55, a = seed ^ z;
229        a ^= a >>> 14;
230        z = (z ^ z >>> 10) * 0xA5CB3;
231        a ^= a >>> 15;
232        stateA = (z ^ z >>> 20) + (a ^= a << 13);
233        z = seed + 0x8E9D5AAA;
234        a ^= a >>> 14;
235        z = (z ^ z >>> 10) * 0xA5CB3;
236        a ^= a >>> 15;
237        stateB = (z ^ z >>> 20) + (a ^ a << 13);
238        if((stateA | stateB) == 0)
239            stateA = 1;
240    }
241
242    public int getStateA()
243    {
244        return stateA;
245    }
246    /**
247     * Sets the first part of the state to the given int. As a special case, if the parameter is 0 and stateB is
248     * already 0, this will set stateA to 1 instead, since both states cannot be 0 at the same time. Usually, you
249     * should use {@link #setState(int, int)} to set both states at once, but the result will be the same if you call
250     * setStateA() and then setStateB() or if you call setStateB() and then setStateA().
251     * @param stateA any int
252     */
253
254    public void setStateA(int stateA)
255    {
256        this.stateA = (stateA | stateB) == 0 ? 1 : stateA;
257    }
258    public int getStateB()
259    {
260        return stateB;
261    }
262
263    /**
264     * Sets the second part of the state to the given int. As a special case, if the parameter is 0 and stateA is
265     * already 0, this will set stateA to 1 and stateB to 0, since both cannot be 0 at the same time. Usually, you
266     * should use {@link #setState(int, int)} to set both states at once, but the result will be the same if you call
267     * setStateA() and then setStateB() or if you call setStateB() and then setStateA().
268     * @param stateB any int
269     */
270    public void setStateB(int stateB)
271    {
272        this.stateB = stateB;
273        if((stateB | stateA) == 0) stateA = 1;
274    }
275
276    /**
277     * Sets the current internal state of this GWTRNG with three ints, where stateA and stateB can each be any int
278     * unless they are both 0 (which will be treated as if stateA is 1 and stateB is 0).
279     * @param stateA any int (if stateA and stateB are both 0, this will be treated as 1)
280     * @param stateB any int
281     */
282    public void setState(int stateA, int stateB)
283    {
284        this.stateA = stateA == 0 && stateB == 0 ? 1 : stateA;
285        this.stateB = stateB;
286    }
287
288    /**
289     * Get the current internal state of the StatefulRandomness as a long.
290     *
291     * @return the current internal state of this object.
292     */
293    @Override
294    public long getState() {
295        return stateA & 0xFFFFFFFFL | ((long)stateB) << 32;
296    }
297
298    /**
299     * Set the current internal state of this StatefulRandomness with a long.
300     *
301     * @param state a 64-bit long. You should avoid passing 0; this implementation will treat it as 1.
302     */
303    @Override
304    public void setState(long state) {
305        stateA = state == 0 ? 1 : (int)(state & 0xFFFFFFFFL);
306        stateB = (int)(state >>> 32);
307    }
308
309    @Override
310    public boolean equals(Object o) {
311        if (this == o) return true;
312        if (o == null || getClass() != o.getClass()) return false;
313
314        GWTRNG gwtrng = (GWTRNG) o;
315
316        if (stateA != gwtrng.stateA) return false;
317        return stateB == gwtrng.stateB;
318    }
319
320    @Override
321    public int hashCode() {
322        return 31 * stateA + stateB;
323    }
324    
325    @Override
326    public String toString() {
327        return "GWTRNG with stateA 0x" + StringKit.hex(stateA) + " and stateB 0x" + StringKit.hex(stateB);
328    }
329
330    /**
331     * A deterministic random int generator that, given one int {@code state} as input, irreversibly returns an 
332     * almost-always-different int as a result. Unlike the rest of GWTRNG, this will not produce all possible ints given
333     * all ints as inputs, and probably a third of all possible ints cannot be returned. You should call this with
334     * {@code GWTRNG.determineInt(state = state + 1 | 0)} (you can subtract 1 to go backwards instead of forwards),
335     * which will allow overflow in the incremented state to be handled the same on GWT as on desktop.
336     * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineInt(state = state + 1 | 0)} to handle overflow 
337     * @return a not-necessarily-unique int that is usually very different from {@code state}
338     */
339    public static int determineInt(int state) {
340        return (state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19;
341    }
342    
343    /**
344     * A deterministic random int generator that, given one int {@code state} and an outer int {@code bound} as input,
345     * returns an int between 0 (inclusive) and {@code bound} (exclusive) as a result, which should have no noticeable
346     * correlation between {@code state} and the result. You should call this with
347     * {@code GWTRNG.determineBound(state = state + 1 | 0, bound)} (you can subtract 1 to go backwards instead of
348     * forwards), which will allow overflow in the incremented state to be handled the same on GWT as on desktop.
349     * Like most bounded int generation in SquidLib, this uses some long math, but most of the function uses ints.
350     * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineBounded(state = state + 1 | 0, bound)} to handle overflow
351     * @param bound the outer exclusive bound, as an int; may be positive or negative
352     * @return an int between 0 (inclusive) and {@code bound} (exclusive)
353     */
354    public static int determineBounded(int state, final int bound)
355    {
356        return (int) ((((state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) & 0xFFFFFFFFL) * bound >> 32);
357    }
358    /**
359     * A deterministic random long generator that, given one int {@code state} as input, returns an 
360     * almost-always-different long as a result. This can only return a tiny fraction of all possible longs, since there
361     * are at most 2 to the 32 possible ints and this doesn't even return different values for each of those. You should
362     * call this with {@code GWTRNG.determine(state = state + 1 | 0)} (you can subtract 1 to go backwards instead of
363     * forwards), which will allow overflow in the incremented state to be handled the same on GWT as on desktop.
364     * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determine(state = state + 1 | 0)} to handle overflow 
365     * @return a not-necessarily-unique long that is usually very different from {@code state}
366     */
367    public static long determine(int state)
368    {
369        int r = (state ^ 0xD1B54A35) * 0x102473;
370        return ((long) ((r = (r ^ r >>> 11 ^ r >>> 21) * (r | 0xFFE00001)) ^ r >>> 13 ^ r >>> 19) << 32) 
371                | (((state = ((state = (r ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) & 0xFFFFFFFFL);
372    }
373    /**
374     * A deterministic random float generator that, given one int {@code state} as input, returns an 
375     * almost-always-different float between 0.0f and 1.0f as a result. Unlike the rest of GWTRNG, this might not
376     * produce all possible floats given all ints as inputs, and some fraction of possible floats cannot be returned.
377     * You should call this with {@code GWTRNG.determineFloat(state = state + 1 | 0)} (you can subtract 1 to go
378     * backwards instead of forwards), which will allow overflow in the incremented state to be handled the same on GWT
379     * as on desktop.
380     * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineFloat(state = state + 1 | 0)} to handle overflow 
381     * @return a not-necessarily-unique float from 0.0f to 1.0f that is usually very different from {@code state}
382     */
383    public static float determineFloat(int state) {
384        return (((state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) & 0xFFFFFF) * 0x1p-24f;
385    }
386    /**
387     * A deterministic random double generator that, given one int {@code state} as input, returns an 
388     * almost-always-different double between 0.0 and 1.0 as a result. This cannot produce more than a tiny fraction of
389     * all possible doubles because the input is 32 bits and at least 53 bits are needed to represent most doubles from
390     * 0.0 to 1.0. You should call this with {@code GWTRNG.determineDouble(state = state + 1 | 0)} (you can subtract 1
391     * to go backwards instead of forwards), which will allow overflow in the incremented state to be handled the same
392     * on GWT as on desktop.
393     * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineDouble(state = state + 1 | 0)} to handle overflow 
394     * @return a not-necessarily-unique double from 0.0 to 1.0 that is usually very different from {@code state}
395     */
396    public static double determineDouble(int state)
397    {
398        return ((state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) * 0x1p-32 + 0.5;
399    }
400}