001package squidpony.squidmath;
002
003import squidpony.StringKit;
004
005import java.io.Serializable;
006
007/**
008 * A larger-period generator with 128 bits of state, good speed, and high quality in PractRand testing; it is at least
009 * 1-dimensionally equidistributed. It appears to be slightly faster than a Xorshift128+ generator, like RandomXS128 in
010 * libGDX, with practically the same period (this has a period of 2 to the 128), but it isn't as fast as as
011 * {@link OrbitRNG} or {@link GearRNG} (Goat seems to have higher statistical quality than either of those late in
012 * testing, though). It passes 64TB of PractRand testing with no anomalies, and might be able to endure tests past even
013 * that (the default setting stops at 32TB); I had set up PractRand to test up to 128TB but it ran out of memory after
014 * 5 days of nonstop testing on all 6 cores. If 16GB of RAM isn't enough to find even an anomaly in GoatRNG, then it is
015 * probably quite good.
016 * <br>
017 * Unlike most RNGs from outside Goat, Gear, and Orbit's family, this relies on a conditional and comparison to achieve
018 * both its period and randomness goals. All of these generators use two additive sequences for their states, and stall
019 * one of the state updates when the other state matches a criterion. For Orbit, it stalls only when stateA is 0
020 * (roughly 1 in 18 quintillion generated numbers); for Gear, stateA must be less than 1863783533 away from the minimum
021 * long value (roughly 1 in 10 billion generated numbers), and here, stateA must be less than 5096992405936522019L to
022 * stall (roughly 3 in 4 generated numbers).
023 * <br>
024 * Unlike GearRNG, this allows all long values for both states; unlike OrbitRNG, there shouldn't be significant
025 * correlation between an even value for stateB and the value 1 greater than that (such as 4 and 5, or 100 and 101). 
026 * <br>
027 * The name comes from how goats are reliably hard to predict, like an RNG should be.
028 * It is called GhoulRNG in some tests run on it; an earlier version of GoatRNG also exists
029 * that does well in testing for the first 32TB and then suddenly has serious issues.
030 * <br>
031 * Created by Tommy Ettinger on 5/8/2020.
032 */
033public final class GoatRNG implements RandomnessSource, Serializable {
034    private static final long serialVersionUID = 1L;
035    /**
036     * Can be any long value.
037     */
038    public long stateA;
039    /**
040     * Can be any long value.
041     */
042    public long stateB;
043
044    /**
045     * Creates a new generator seeded using Math.random.
046     */
047    public GoatRNG() {
048        this((long) ((Math.random() - 0.5) * 0x10000000000000L)
049                ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L),
050                (long) ((Math.random() - 0.5) * 0x10000000000000L)
051                ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L));
052    }
053
054    public GoatRNG(long seed) {
055        stateA = (seed = (seed = ((seed = (((seed * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ seed >>> 27) * 0xAEF17502108EF2D9L) ^ seed >>> 25);
056        stateB =         (seed = ((seed = (((seed * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ seed >>> 27) * 0xAEF17502108EF2D9L) ^ seed >>> 25;
057    }
058
059    public GoatRNG(final long seedA, final long seedB) {
060        stateA = seedA;
061        stateB = seedB;
062    }
063
064    /**
065     * Get the "A" part of the internal state as a long.
066     *
067     * @return the current internal state of this object.
068     */
069    public long getStateA() {
070        return stateA;
071    }
072
073    /**
074     * Set the "A" part of the internal state with a long.
075     *
076     * @param stateA any 64-bit long
077     */
078    public void setStateA(long stateA) {
079        this.stateA = stateA;
080    }
081
082    /**
083     * Get the "B" part of the internal state as a long.
084     *
085     * @return the current internal "B" state of this object.
086     */
087    public long getStateB() {
088        return stateB;
089    }
090
091    /**
092     * Set the "B" part of the internal state with a long.
093     *
094     * @param stateB any 64-bit long
095     */
096    public void setStateB(long stateB) {
097        this.stateB = stateB;
098    }
099
100
101    /**
102     * Using this method, any algorithm that might use the built-in Java Random
103     * can interface with this randomness source.
104     *
105     * @param bits the number of bits to be returned
106     * @return the integer containing the appropriate number of bits
107     */
108    @Override
109    public final int next(final int bits) {
110        long s = (stateA += 0xD1342543DE82EF95L);
111        s ^= s >>> 31 ^ s >>> 23;
112        if(s < 0x46BC279692B5C323L) {
113            final long t = stateB;
114            s *= ((t ^ t << 9) | 1L);
115            return (int)(s ^ s >>> 25) >>> (32 - bits);
116        }
117        else {
118            final long t = (stateB += 0xB1E131D6149D9795L);
119            s *= ((t ^ t << 9) | 1L);
120            return (int)(s ^ s >>> 25) >>> (32 - bits);
121        }
122    }
123    /**
124     * Using this method, any algorithm that needs to efficiently generate more
125     * than 32 bits of random data can interface with this randomness source.
126     * <p>
127     * Get a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive).
128     *
129     * @return a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive)
130     */
131    @Override
132    public final long nextLong() {
133        long s = (stateA += 0xD1342543DE82EF95L);
134        s ^= s >>> 31 ^ s >>> 23;
135        if(s < 0x46BC279692B5C323L) {
136            final long t = stateB;
137            s *= ((t ^ t << 9) | 1L);
138            return s ^ s >>> 25;
139        }
140        else {
141            final long t = (stateB += 0xB1E131D6149D9795L);
142            s *= ((t ^ t << 9) | 1L);
143            return s ^ s >>> 25;
144        }
145    }
146
147    /**
148     * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
149     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just need to
150     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
151     *
152     * @return a copy of this RandomnessSource
153     */
154    @Override
155    public GoatRNG copy() {
156        return new GoatRNG(stateA, stateB);
157    }
158    @Override
159    public String toString() {
160        return "GoatRNG with stateA 0x" + StringKit.hex(stateA) + "L and stateB 0x" + StringKit.hex(stateB) + 'L';
161    }
162
163    @Override
164    public boolean equals(Object o) {
165        if (this == o) return true;
166        if (o == null || getClass() != o.getClass()) return false;
167
168        GoatRNG goatRNG = (GoatRNG) o;
169
170        return stateA == goatRNG.stateA && stateB == goatRNG.stateB;
171    }
172
173    @Override
174    public int hashCode() {
175        return (int) (31L * (stateA ^ (stateA >>> 32)) + (stateB ^ stateB >>> 32));
176    }
177    
178}