001/*  Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
002
003To the extent possible under law, the author has dedicated all copyright
004and related and neighboring rights to this software to the public domain
005worldwide. This software is distributed without any warranty.
006
007See <http://creativecommons.org/publicdomain/zero/1.0/>. */
008package squidpony.squidmath;
009
010import squidpony.StringKit;
011
012import java.io.Serializable;
013
014/**
015 * A modification of Blackman and Vigna's xoroshiro128+ generator using two 32-bit ints of state instead of two 64-bit
016 * longs, as well as modifying the output with two additional operations on the existing state; this is both the fastest
017 * generator on GWT I have found without statistical failures, and a StatefulRandomness. This algorithm is sometimes
018 * called xoroshiro64++ and is mentioned in <a href="http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf">this paper
019 * by Blackman and Vigna</a> (in section 10.7; the 'r' constant is 10, which seems to usually do well on those same
020 * authors' HWD test). Lathe32RNG passes the full 32TB battery of PractRand's statistical tests, and does so with 3
021 * "unusual" anomalies, no more-serious anomalies, and no failures. It isn't especially likely that this can pass much
022 * more than 32TB of testing (judging by related attempts, 128TB would be a likely failure point), but because
023 * multi-threaded code is either impossible or impractical on GWT, actually using that many numbers would take a very
024 * long time (generating them would take about 3 nanoseconds per int, but it would take more than 2 to the 43 ints to
025 * start to approach detectable failures, and detecting the failures in anything but the worst case would take more than
026 * a day). In statistical testing, xoroshiro with the '+' scrambler always fails some binary matrix rank tests, but
027 * smaller-state versions fail other tests as well. The changes Lathe makes apply only to the output of xoroshiro64+ (in
028 * Vigna's and Blackman's terms, they are a scrambler), not its well-tested state transition, and these changes
029 * eliminate all statistical failures on 32TB of tested data, avoiding the failures the small-state variant of xoroshiro
030 * suffers on BinaryRank, BCFN, DC6, and FPF. It avoids multiplication (except in {@link #setSeed(int)}, which needs to
031 * use a different algorithm to spread a seed out across twice as much state), like xoroshiro and much of the xorshift
032 * family of generators, and any arithmetic it performs is safe for GWT. Lathe makes an extremely small set of changes
033 * to xoroshiro64+, running xoroshiro64+ as normal (holding on to the result as well as the initial stateA, called s[0]
034 * in the original xoroshiro code) and then bitwise-rotating the result and adding the (now previous) stateA. Although
035 * no bits of xoroshiro are truly free of artifacts, some are harder to find issues with
036 * (see <a href="http://www.pcg-random.org/posts/xoroshiro-fails-truncated.html">this article by PCG-Random's author</a>
037 * for more detail). It is unclear if the changes made here would improve the larger-state version, but they probably
038 * would help to some extent with at least the binary rank failures. The period is identical to xoroshiro with two
039 * 32-bit states, at 0xFFFFFFFFFFFFFFFF or 2 to the 64 minus 1. This generator is slightly slower than xoroshiro without
040 * the small extra steps applied to the output, but about as fast as {@link Oriole32RNG} (this has a smaller period and
041 * smaller state but implements StatefulRandomness). Some simple tests on bytes instead of ints showed that the
042 * technique used here produces all possible bytes with equal frequency when run on bytes as state, with the exception
043 * of producing 0 one less time (because both states cannot be 0 at the same time). This gives some confidence for the
044 * algorithm used here, but the algorithm is still only one-dimensionally equidistributed (the same as xoroshiro128+),
045 * meaning it produces some pairs of ints more frequently than others. You may want to prefer {@link Starfish32RNG},
046 * which is the current default in {@link GWTRNG}, because it can produce all pairs of ints and all longs (except one),
047 * and has noticeably better quality even on some short generated sequences.
048 * <br>
049 * The name comes from a tool that rotates very quickly to remove undesirable parts of an object, akin to how this
050 * generator adds an extra bitwise rotation to xoroshiro64+ to remove several types of
051 * undesirable statistical failures from its test results.
052 * <br>
053 * <a href="http://xoroshiro.di.unimi.it/xoroshiro128plus.c">Original version here for xorshiro128+</a>; this version
054 * uses <a href="https://groups.google.com/d/msg/prng/Ll-KDIbpO8k/bfHK4FlUCwAJ">different constants</a> by the same
055 * author, Sebastiano Vigna. It does not use <a href="http://xoshiro.di.unimi.it/xoroshiro64star.c">the constants used
056 * in other xoroshiro64 scrambled generators</a>, instead using similar-quality ones from the earlier constants link.
057 * <br>
058 * Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
059 * Ported and modified in 2018 by Tommy Ettinger
060 * @author Sebastiano Vigna
061 * @author David Blackman
062 * @author Tommy Ettinger (if there's a flaw, use SquidLib's or Sarong's issues and don't bother Vigna or Blackman, it's probably a mistake in SquidLib's implementation)
063 */
064public final class Lathe32RNG implements StatefulRandomness, Serializable {
065
066    private static final long serialVersionUID = 2L;
067
068    private int stateA, stateB;
069
070    /**
071     * Creates a new generator seeded using two calls to Math.random().
072     */
073    public Lathe32RNG() {
074        setState((int)((Math.random() * 2.0 - 1.0) * 0x80000000), (int)((Math.random() * 2.0 - 1.0) * 0x80000000));
075    }
076    /**
077     * Constructs this Lathe32RNG by dispersing the bits of seed using {@link #setSeed(int)} across the two parts of state
078     * this has.
079     * @param seed an int that won't be used exactly, but will affect both components of state
080     */
081    public Lathe32RNG(final int seed) {
082        setSeed(seed);
083    }
084    /**
085     * Constructs this Lathe32RNG by splitting the given seed across the two parts of state this has with
086     * {@link #setState(long)}.
087     * @param seed a long that will be split across both components of state
088     */
089    public Lathe32RNG(final long seed) {
090        setState(seed);
091    }
092    /**
093     * Constructs this Lathe32RNG by calling {@link #setState(int, int)} on stateA and stateB as given; see that method
094     * for the specific details (stateA and stateB are kept as-is unless they are both 0).
095     * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0
096     * @param stateB the number to use as the second part of the state
097     */
098    public Lathe32RNG(final int stateA, final int stateB) {
099        setState(stateA, stateB);
100    }
101    
102    @Override
103    public final int next(int bits) {
104        final int s0 = stateA;
105        int s1 = stateB;
106        final int result = s0 + s1;
107        s1 ^= s0;
108        stateA = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b
109        stateB = (s1 << 28 | s1 >>> 4); // c
110        return (result << 10 | result >>> 22) + s0 >>> (32 - bits);
111    }
112
113    /**
114     * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
115     * @return any int, all 32 bits are random
116     */
117    public final int nextInt() {
118        final int s0 = stateA;
119        int s1 = stateB;
120        final int result = s0 + s1;
121        s1 ^= s0;
122        stateA = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b
123        stateB = (s1 << 28 | s1 >>> 4); // c
124        return (result << 10 | result >>> 22) + s0;
125    }
126
127    @Override
128    public final long nextLong() {
129        final int s0 = stateA;
130        int s1 = stateB;
131        final int high = s0 + s1;
132        s1 ^= s0;
133        final int s00 = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b
134        s1 = (s1 << 28 | s1 >>> 4); // c
135        final int low = s00 + s1;
136        s1 ^= s00;
137        stateA = (s00 << 13 | s00 >>> 19) ^ s1 ^ (s1 << 5); // a, b
138        stateB = (s1 << 28 | s1 >>> 4); // c
139        return ((high << 10 | high >>> 22) + s0 | 0L) << 32 | ((low << 10 | low >>> 22) + s00 & 0xFFFFFFFFL);
140    }
141
142    /**
143     * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
144     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to
145     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
146     *
147     * @return a copy of this RandomnessSource
148     */
149    @Override
150    public Lathe32RNG copy() {
151        return new Lathe32RNG(stateA, stateB);
152    }
153
154    /**
155     * Sets the state of this generator using one int, running it through Zog32RNG's algorithm two times to get 
156     * two ints. If the states would both be 0, state A is assigned 1 instead.
157     * @param seed the int to use to produce this generator's state
158     */
159    public void setSeed(final int seed) {
160        int z = seed + 0xC74EAD55, a = seed ^ z;
161        a ^= a >>> 14;
162        z = (z ^ z >>> 10) * 0xA5CB3;
163        a ^= a >>> 15;
164        stateA = (z ^ z >>> 20) + (a ^= a << 13);
165        z = seed + 0x8E9D5AAA;
166        a ^= a >>> 14;
167        z = (z ^ z >>> 10) * 0xA5CB3;
168        a ^= a >>> 15;
169        stateB = (z ^ z >>> 20) + (a ^ a << 13);
170        if((stateA | stateB) == 0)
171            stateA = 1;
172    }
173
174    public int getStateA()
175    {
176        return stateA;
177    }
178    /**
179     * Sets the first part of the state to the given int. As a special case, if the parameter is 0 and stateB is
180     * already 0, this will set stateA to 1 instead, since both states cannot be 0 at the same time. Usually, you
181     * should use {@link #setState(int, int)} to set both states at once, but the result will be the same if you call
182     * setStateA() and then setStateB() or if you call setStateB() and then setStateA().
183     * @param stateA any int
184     */
185
186    public void setStateA(int stateA)
187    {
188        this.stateA = (stateA | stateB) == 0 ? 1 : stateA;
189    }
190    public int getStateB()
191    {
192        return stateB;
193    }
194
195    /**
196     * Sets the second part of the state to the given int. As a special case, if the parameter is 0 and stateA is
197     * already 0, this will set stateA to 1 and stateB to 0, since both cannot be 0 at the same time. Usually, you
198     * should use {@link #setState(int, int)} to set both states at once, but the result will be the same if you call
199     * setStateA() and then setStateB() or if you call setStateB() and then setStateA().
200     * @param stateB any int
201     */
202    public void setStateB(int stateB)
203    {
204        this.stateB = stateB;
205        if((stateB | stateA) == 0) stateA = 1;
206    }
207
208    /**
209     * Sets the current internal state of this Lathe32RNG with three ints, where stateA and stateB can each be any int
210     * unless they are both 0 (which will be treated as if stateA is 1 and stateB is 0).
211     * @param stateA any int (if stateA and stateB are both 0, this will be treated as 1)
212     * @param stateB any int
213     */
214    public void setState(int stateA, int stateB)
215    {
216        this.stateA = (stateA | stateB) == 0 ? 1 : stateA;
217        this.stateB = stateB;
218    }
219
220    /**
221     * Get the current internal state of the StatefulRandomness as a long.
222     *
223     * @return the current internal state of this object.
224     */
225    @Override
226    public long getState() {
227        return stateA & 0xFFFFFFFFL | ((long)stateB) << 32;
228    }
229
230    /**
231     * Set the current internal state of this StatefulRandomness with a long.
232     *
233     * @param state a 64-bit long. You should avoid passing 0; this implementation will treat it as 1.
234     */
235    @Override
236    public void setState(long state) {
237        stateA = state == 0 ? 1 : (int)(state & 0xFFFFFFFFL);
238        stateB = (int)(state >>> 32);
239    }
240
241    @Override
242    public String toString() {
243        return "Lathe32RNG with stateA 0x" + StringKit.hex(stateA) + " and stateB 0x" + StringKit.hex(stateB);
244    }
245
246    @Override
247    public boolean equals(Object o) {
248        if (this == o) return true;
249        if (o == null || getClass() != o.getClass()) return false;
250
251        Lathe32RNG lathe32RNG = (Lathe32RNG) o;
252
253        return stateA == lathe32RNG.stateA && stateB == lathe32RNG.stateB;
254    }
255
256    @Override
257    public int hashCode() {
258        return 31 * stateA + stateB;
259    }
260}