001package squidpony.squidmath;
002
003import squidpony.StringKit;
004
005import java.io.Serializable;
006
007/**
008 * A modification of Blackman and Vigna's xoroshiro128+ generator using two 32-bit ints of state instead of two 64-bit
009 * longs and also incorporating a large-increment counter (Weyl sequence) that is added to the rotated xoroshiro output;
010 * this is tied with {@link Lathe32RNG} for the fastest generator on GWT I have found that also passes the full 32TB
011 * battery of PractRand's statistical tests. Starfish32RNG has 2D equidistribution while this only has 1D; this means
012 * Starfish32RNG (and GWTRNG) can produce all pairs of ints or all longs (except for one) with equal likelihood, while
013 * Oriole32RNG (and Lathe32RNG) produce some pairs more often than others. In statistical testing, xoroshiro always
014 * fails some binary matrix rank tests, but smaller-state versions fail other tests as well. The changes Oriole makes
015 * apply only to the output of xoroshiro, not its well-tested state transition for the "xoroshiro state" part of this
016 * generator, and these changes eliminate all statistical failures on 32TB of tested data, avoiding the failures the
017 * small-state variant of xoroshiro suffers on BinaryRank, BCFN, DC6, and FPF. It avoids multiplication, like xoroshiro
018 * and much of the xorshift family of generators, and any arithmetic it performs is safe for GWT. Oriole takes advantage
019 * of xoroshiro's flaws being mostly confined to its output's lower bits by rotating the output of xoroshiro (the weaker
020 * 32-bit-state version) and adding a "Weyl sequence," essentially a large-increment counter that overflows and wraps
021 * frequently, to the output. Although the upper bits of xoroshiro are not free of artifacts either, they are harder to
022 * find issues with (see
023 * <a href="http://www.pcg-random.org/posts/xoroshiro-fails-truncated.html">this article by PCG-Random's author</a> for
024 * more detail). It is unclear if the changes made here would improve the larger-state version, but they probably would
025 * help to some extent with at least the binary rank failures. The period is also improved by incorporating the Weyl
026 * sequence, up to 0xFFFFFFFFFFFFFFFF00000000 .
027 * <br>
028 * The name comes from the insectivorous orange songbird called an oriole, which as I have found from the one that
029 * visits my backyard, reacts quickly and is always looking for bugs to remove. It also sounds like "xoro."
030 * <br>
031 * <a href="http://xoroshiro.di.unimi.it/xoroshiro128plus.c">Original version here for xorshiro128+</a>; this version
032 * uses <a href="https://groups.google.com/d/msg/prng/Ll-KDIbpO8k/bfHK4FlUCwAJ">different constants</a> by the same
033 * author, Sebastiano Vigna.
034 * <br>
035 * Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
036 * Ported and modified in 2018 by Tommy Ettinger
037 * @author Sebastiano Vigna
038 * @author David Blackman
039 * @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)
040 * @see Lathe32RNG A related generator that implements StatefulRandomness and has very similar speed
041 */
042public final class Oriole32RNG implements RandomnessSource, Serializable {
043
044    private static final long serialVersionUID = 2L;
045
046    private int stateA, stateB, stateC;
047
048    /**
049     * Creates a new generator seeded using three calls to Math.random().
050     */
051    public Oriole32RNG() {
052        setState((int)((Math.random() * 2.0 - 1.0) * 0x80000000), (int)((Math.random() * 2.0 - 1.0) * 0x80000000),
053                (int)((Math.random() * 2.0 - 1.0) * 0x80000000));
054    }
055    /**
056     * Constructs this Oriole32RNG by dispersing the bits of seed using {@link #setSeed(int)} across the two parts of state
057     * this has.
058     * @param seed a long that won't be used exactly, but will affect both components of state
059     */
060    public Oriole32RNG(final int seed) {
061        setSeed(seed);
062    }
063    /**
064     * Constructs this Oriole32RNG by calling {@link #setState(int, int, int)} on stateA and stateB as given but
065     * producing stateC via {@code stateA ^ stateB}; see that method for the specific details (stateA and stateB are
066     * kept as-is unless they are both 0).
067     * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0
068     * @param stateB the number to use as the second part of the state
069     */
070    public Oriole32RNG(final int stateA, final int stateB) {
071        setState(stateA, stateB, stateA ^ stateB);
072    }
073
074    /**
075     * Constructs this Oriole32RNG by calling {@link #setState(int, int, int)} on the arguments as given; see that
076     * method for the specific details (stateA and stateB are kept as-is unless they are both 0).
077     * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0
078     * @param stateB the number to use as the second part of the state
079     * @param stateC the number to use as the counter part of the state (third part)
080     */
081    public Oriole32RNG(final int stateA, final int stateB, final int stateC) {
082        setState(stateA, stateB, stateC);
083    }
084
085    @Override
086    public final int next(int bits) {
087        final int s0 = stateA;
088        int s1 = stateB;
089        final int result = s0 + s1;
090        s1 ^= s0;
091        stateA = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b
092        stateB = (s1 << 28 | s1 >>> 4); // c
093        return (result << 29 | result >>> 3) + (stateC += 0x632BE5AB) >>> (32 - bits);
094    }
095
096    /**
097     * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
098     * @return any int, all 32 bits are random
099     */
100    public final int nextInt() {
101        final int s0 = stateA;
102        int s1 = stateB;
103        final int result = s0 + s1;
104        s1 ^= s0;
105        stateA = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b
106        stateB = (s1 << 28 | s1 >>> 4); // c
107        return (result << 29 | result >>> 3) + (stateC += 0x632BE5AB);
108    }
109
110    @Override
111    public final long nextLong() {
112        final int s0 = stateA;
113        int s1 = stateB;
114        final int high = s0 + s1;
115        s1 ^= s0;
116        final int s00 = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b
117        s1 = (s1 << 28 | s1 >>> 4); // c
118        final int low = s00 + s1;
119        s1 ^= s00;
120        stateA = (s00 << 13 | s00 >>> 19) ^ s1 ^ (s1 << 5); // a, b
121        stateB = (s1 << 28 | s1 >>> 4); // c
122        return ((high << 29 | high >>> 3) + (stateC + 0x632BE5ABL)) << 32 | ((low << 29 | low >>> 3) + (stateC += 0xC657CB56) & 0xFFFFFFFFL);
123    }
124
125    /**
126     * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
127     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to
128     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
129     *
130     * @return a copy of this RandomnessSource
131     */
132    @Override
133    public Oriole32RNG copy() {
134        return new Oriole32RNG(stateA, stateB, stateC);
135    }
136
137    /**
138     * Sets the state of this generator using one int, running it through Zog32RNG's algorithm three times to get 
139     * three ints.
140     * @param seed the int to use to assign this generator's state
141     */
142    public void setSeed(final int seed) {
143        int z = seed + 0xC74EAD55, a = seed ^ z;
144        a ^= a >>> 14;
145        z = (z ^ z >>> 10) * 0xA5CB3;
146        a ^= a >>> 15;
147        stateA = (z ^ z >>> 20) + (a ^= a << 13);
148        z = seed + 0x8E9D5AAA;
149        a ^= a >>> 14;
150        z = (z ^ z >>> 10) * 0xA5CB3;
151        a ^= a >>> 15;
152        stateB = (z ^ z >>> 20) + (a ^ a << 13);
153        if((stateA | stateB) == 0)
154            stateA = 1;
155        z = seed - 0xC74EAD55;
156        a ^= a >>> 14;
157        z = (z ^ z >>> 10) * 0xA5CB3;
158        a ^= a >>> 15;
159        stateC = (z ^ z >>> 20) + (a ^ a << 13);
160    }
161
162    public int getStateA()
163    {
164        return stateA;
165    }
166    public void setStateA(int stateA)
167    {
168        this.stateA = (stateA | stateB) == 0 ? 1 : stateA;
169    }
170    public int getStateB()
171    {
172        return stateB;
173    }
174    public void setStateB(int stateB)
175    {
176        this.stateB = stateB;
177        if((stateB | stateA) == 0) stateA = 1;
178    }
179    public int getStateC()
180    {
181        return stateC;
182    }
183    public void setStateC(int stateC)
184    {
185        this.stateC = stateC;
186    }
187
188    /**
189     * Sets the current internal state of this Oriole32RNG with three ints, where stateA and stateB can each be any int
190     * unless they are both 0, and stateC can be any int without restrictions.
191     * @param stateA any int except 0 (0 will be treated as 1 instead)
192     * @param stateB any int
193     */
194    public void setState(int stateA, int stateB, int stateC)
195    {
196        this.stateA = (stateA | stateB) == 0 ? 1 : stateA;
197        this.stateB = stateB;
198        this.stateC = stateC;
199    }
200    @Override
201    public String toString() {
202        return "Oriole32RNG with stateA 0x" + StringKit.hex(stateA) + ", stateB 0x" + StringKit.hex(stateB) + ", and stateC 0x" + StringKit.hex(stateC);
203    }
204
205    @Override
206    public boolean equals(Object o) {
207        if (this == o) return true;
208        if (o == null || getClass() != o.getClass()) return false;
209
210        Oriole32RNG oriole32RNG = (Oriole32RNG) o;
211
212        return stateA == oriole32RNG.stateA && stateB == oriole32RNG.stateB && stateC == oriole32RNG.stateC;
213    }
214
215    @Override
216    public int hashCode() {
217        return 31 * stateA + stateB;
218    }
219}
220