001package squidpony.squidmath;
002
003import squidpony.StringKit;
004
005import java.io.Serializable;
006
007/**
008 * A very fast generator on 64-bit systems that allows choosing any of 2 to the 63 odd-number streams. Each stream
009 * changes the set of possible outputs this can produce (amending the main flaw of ThrustAltRNG). This does well in
010 * PractRand quality tests, passing 32TB with one minor anomaly (it shares a lot of structure with ThrustAltRNG,
011 * which does very well in PractRand's testing as well as TestU01's BigCrush). It also outperforms just about everything
012 * in BumbleBench benchmarks, making it arguably the fastest random number generator algorithm here that
013 * can produce all long values (it just needs multiple generator objects to do so, all seeded differently).
014 * <br>
015 * Because this can produce multiple occurrences of any number in its sequence (except 0, which it should always produce
016 * once over its period of 2 to the 64), it can be considered as passing the "birthday problem" test; after running
017 * <a href="http://www.pcg-random.org/posts/birthday-test.html">this test provided by Melissa E. O'Neill</a> on Tangle,
018 * it correctly has 9 repeats compared to an expected 10, using the Skipping adapter to check one out of every 65536
019 * outputs for duplicates. A generator that failed that test would have 0 repeats or more than 20, so Tangle passes.
020 * ThrustAltRNG probably also passes (or its structure allows it to potentially do so), but LightRNG, LinnormRNG,
021 * MizuchiRNG, and even ThrustRNG will fail it by never repeating an output. Truncating the output bits of any of these
022 * generators will allow them to pass this test, at the cost of reducing the size of the output to an int instead of a
023 * long (less than ideal). Notably, an individual Tangle generator tends to be able to produce about 2/3 of all possible
024 * long outputs, with roughly 1/3 of all outputs not possible to produce and another 1/3 produced exactly once. These
025 * are approximations and will vary between instances. The test that gave the "roughly 2/3 possible" result gave similar
026 * results with 8-bit stateA and stateB and with 16-bit stateA and stateB, though it could change with the 64-bit states
027 * Tangle actually uses.
028 * <br>
029 * The name "Tangle" comes from how the two states of this generator are "tied up in each other," with synchronized
030 * periods of 2 to the 64 (stateA) and 2 to the 63 (stateB) that repeat as a whole every 2 to the 64 outputs. Contrary
031 * to the name, Tangle isn't slowed down at all by this, but the period length of the generator is less than the maximum
032 * possible (which OrbitRNG has, though that one is slowed down).
033 * <br>
034 * See also {@link OrbitRNG}, which gives up more speed but moves through all 2 to the 64 long values as streams over
035 * its full period, which is 2 to the 128 (with one stream) instead of the 2 to the 64 (with 2 to the 63 streams) here.
036 * There's also {@link SilkRNG}, which is like OrbitRNG but uses 32-bit math and is GWT-optimized.
037 * <br>
038 * This added a small extra step to the generation on March 4, 2020; the extra step reduces correlation between streams
039 * by further randomizing the output. Without this step (an additional right-xorshift by 6), nearby stateA or stateB
040 * values would often produce visibly similar sequences; with the step they are much less similar and more random. The
041 * additional step slows down TangleRNG by a very small amount. This edit also added {@link #getStream()}, which may
042 * have a use somewhere (maybe diagnosing possible problems?).
043 * <br>
044 * Created by Tommy Ettinger on 7/9/2018.
045 */
046public final class TangleRNG implements RandomnessSource, SkippingRandomness, Serializable {
047    private static final long serialVersionUID = 5L;
048    /**
049     * Can be any long value.
050     */
051    private long stateA;
052
053    /**
054     * Must be odd.
055     */
056    private long stateB;
057
058    /**
059     * Creates a new generator seeded using Math.random.
060     */
061    public TangleRNG() {
062        this((long) ((Math.random() - 0.5) * 0x10000000000000L)
063                ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L),
064                (long) ((Math.random() - 0.5) * 0x10000000000000L)
065                ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L));
066    }
067
068    public TangleRNG(long seed) {
069        stateA = (seed = ((seed = (((seed * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ seed >>> 27) * 0xAEF17502108EF2D9L) ^ seed >>> 25;
070        stateB = ((seed = ((seed = (((seed * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ seed >>> 27) * 0xAEF17502108EF2D9L) ^ seed >>> 25) | 1L;
071    }
072
073    public TangleRNG(final long seedA, final long seedB) {
074        stateA = seedA;
075        stateB = seedB | 1L;
076    }
077
078    /**
079     * Get the "A" part of the internal state as a long.
080     *
081     * @return the current internal "A" state of this object.
082     */
083    public long getStateA() {
084        return stateA;
085    }
086
087    /**
088     * Set the "A" part of the internal state with a long.
089     *
090     * @param stateA a 64-bit long
091     */
092    public void setStateA(long stateA) {
093        this.stateA = stateA;
094    }
095
096    /**
097     * Get the "B" part of the internal state as a long.
098     *
099     * @return the current internal "B" state of this object.
100     */
101    public long getStateB() {
102        return stateB;
103    }
104
105    /**
106     * Set the "B" part of the internal state with a long; the least significant bit is ignored (will always be odd).
107     *
108     * @param stateB a 64-bit long
109     */
110    public void setStateB(long stateB) {
111        this.stateB = stateB | 1L;
112    }
113
114    /**
115     * Using this method, any algorithm that might use the built-in Java Random
116     * can interface with this randomness source.
117     *
118     * @param bits the number of bits to be returned
119     * @return the integer containing the appropriate number of bits
120     */
121    @Override
122    public final int next(final int bits) {
123        final long s = (stateA += 0xC6BC279692B5C323L);
124        final long z = (s ^ s >>> 31) * (stateB += 0x9E3779B97F4A7C16L);
125        return (int)(z ^ z >>> 26 ^ z >>> 6) >>> (32 - bits);
126    }
127    /**
128     * Using this method, any algorithm that needs to efficiently generate more
129     * than 32 bits of random data can interface with this randomness source.
130     * <p>
131     * Get a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive).
132     *
133     * @return a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive)
134     */
135    @Override
136    public final long nextLong() {
137        final long s = (stateA += 0xC6BC279692B5C323L);
138        final long z = (s ^ s >>> 31) * (stateB += 0x9E3779B97F4A7C16L);
139        return z ^ z >>> 26 ^ z >>> 6;
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 need 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 TangleRNG copy() {
151        return new TangleRNG(stateA, stateB);
152    }
153    @Override
154    public String toString() {
155        return "TangleRNG with stateA 0x" + StringKit.hex(stateA) + "L and stateB 0x" + StringKit.hex(stateB) + 'L';
156    }
157
158    @Override
159    public boolean equals(Object o) {
160        if (this == o) return true;
161        if (o == null || getClass() != o.getClass()) return false;
162
163        TangleRNG tangleRNG = (TangleRNG) o;
164
165        return stateA == tangleRNG.stateA && stateB == tangleRNG.stateB;
166    }
167
168    @Override
169    public int hashCode() {
170        return (int) (31L * (stateA ^ (stateA >>> 32)) + (stateB ^ stateB >>> 32));
171    }
172
173    /**
174     * Advances or rolls back the SkippingRandomness' state without actually generating each number. Skips forward
175     * or backward a number of steps specified by advance, where a step is equal to one call to {@link #nextLong()},
176     * and returns the random number produced at that step. Negative numbers can be used to step backward, or 0 can be
177     * given to get the most-recently-generated long from {@link #nextLong()}.
178     *
179     * @param advance Number of future generations to skip over; can be negative to backtrack, 0 gets the most-recently-generated number
180     * @return the random long generated after skipping forward or backwards by {@code advance} numbers
181     */
182    @Override
183    public long skip(long advance) {
184        final long s = (stateA += 0xC6BC279692B5C323L * advance);
185        final long z = (s ^ s >>> 31) * (stateB += 0x9E3779B97F4A7C16L * advance);
186        return z ^ z >>> 26 ^ z >>> 6;
187    }
188    /**
189     * Gets a long that identifies which stream of numbers this generator is producing; this stream identifier is always
190     * an odd long and won't change by generating numbers. It is determined at construction and will usually (not
191     * always) change if {@link #setStateA(long)} or {@link #setStateB(long)} are called. Each stream is a
192     * probably-unique sequence of 2 to the 64 longs, where approximately 1/3 of all possible longs will not ever occur
193     * (while others occur twice or more), but this set of results is different for every stream. There are 2 to the 63
194     * possible streams, one for every odd long.
195     * @return an odd long that identifies which stream this TangleRNG is generating from
196     */
197    public long getStream()
198    {
199        return stateB - (stateA * 0x1743CE5C6E1B848BL) * 0x9E3779B97F4A7C16L;
200    }
201
202}