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 port of Blackman and Vigna's xoroshiro128+ generator; should be very fast and produce medium-quality output.
016 * Testing shows it is within 5% the speed of LightRNG, sometimes faster and sometimes slower, and has a larger period.
017 * It's called XoRo because it involves Xor as well as Rotate operations on the 128-bit pseudo-random state. Note that
018 * xoroshiro128+ fails some statistical quality tests systematically, and fails others often; if this could be a concern
019 * for you, {@link DiverRNG}, which is the default for {@link RNG}, will be faster and won't fail tests, and
020 * though its period is shorter, it would still take years to exhaust on one core generating only random numbers.
021 * <br>
022 * {@link LightRNG} is also very fast, but relative to XoRoRNG it has a significantly shorter period (the amount of
023 * random numbers it will go through before repeating), at {@code pow(2, 64)} as opposed to XoRoRNG's
024 * {@code pow(2, 128) - 1}, but LightRNG also allows the current RNG state to be retrieved and altered with
025 * {@code getState()} and {@code setState()}. For most cases, you should decide between DiverRNG, LightRNG, XoRoRNG,
026 * and other RandomnessSource implementations based on your needs for period length and state manipulation (DiverRNG
027 * is also used internally by almost all StatefulRNG objects). You might want significantly less predictable random
028 * results, which {@link IsaacRNG} can provide, along with a large period. You may want a very long period of random
029 * numbers, which  would suggest {@link LongPeriodRNG} as a good choice or {@link MersenneTwister} as a potential
030 * alternative. You may want better performance on 32-bit machines or on GWT, where {@link Starfish32RNG} is currently
031 * the best choice most of the time, and {@link Lathe32RNG} can be faster but has slightly worse quality (both of these
032 * generators use a 32-bit variant on the xoroshiro algorithm but change the output scrambler). These all can generate
033 * pseudo-random numbers in a handful of nanoseconds (with the key exception of 64-bit generators being used on GWT,
034 * where they may take more than 100 nanoseconds per number), so unless you need a LOT of random numbers in a hurry,
035 * they'll probably all be fine on performance. You may want to decide on the special features of a generator, indicated
036 * by implementing {@link StatefulRandomness} if their state can be read and written to, and/or
037 * {@link SkippingRandomness} if sections in the generator's sequence can be skipped in long forward or backward leaps.
038 * <br>
039 * <a href="http://xoroshiro.di.unimi.it/xoroshiro128plus.c">Original version here.</a>
040 * <br>
041 * Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
042 *
043 * @author Sebastiano Vigna
044 * @author David Blackman
045 * @author Tommy Ettinger (if there's a flaw, use SquidLib's issues and don't bother Vigna or Blackman, it's probably a mistake in SquidLib's implementation)
046 */
047public final class XoRoRNG implements RandomnessSource, Serializable {
048
049        private static final long DOUBLE_MASK = (1L << 53) - 1;
050    private static final double NORM_53 = 1. / (1L << 53);
051    private static final long FLOAT_MASK = (1L << 24) - 1;
052    private static final double NORM_24 = 1. / (1L << 24);
053
054        private static final long serialVersionUID = 1018744536171610262L;
055
056    private long state0, state1;
057
058    /**
059     * Creates a new generator seeded using four calls to Math.random().
060     */
061    public XoRoRNG() {
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     * Constructs this XoRoRNG by dispersing the bits of seed using {@link #setSeed(long)} across the two parts of state
069     * this has.
070     * @param seed a long that won't be used exactly, but will affect both components of state
071     */
072    public XoRoRNG(final long seed) {
073        setSeed(seed);
074    }
075    /**
076     * Constructs this XoRoRNG by calling {@link #setSeed(long, long)} on the arguments as given; see that method for 
077     * the specific details (stateA and stateB are kept as-is unless they are both 0).
078     * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0
079     * @param stateB the number to use as the second part of the state
080     */
081    public XoRoRNG(final long stateA, final long stateB) {
082        setSeed(stateA, stateB);
083    }
084
085    @Override
086    public final int next(int bits) {
087        final long s0 = state0;
088        long s1 = state1;
089        final int result = (int)(s0 + s1) >>> (32 - bits);
090        s1 ^= s0;
091        state0 = (s0 << 55 | s0 >>> 9) ^ s1 ^ (s1 << 14); // a, b
092        state1 = (s1 << 36 | s1 >>> 28); // c
093        return result;
094    }
095
096    @Override
097    public final long nextLong() {
098        final long s0 = state0;
099        long s1 = state1;
100        final long result = s0 + s1;
101
102        s1 ^= s0;
103        state0 = (s0 << 55 | s0 >>> 9) ^ s1 ^ (s1 << 14); // a, b
104        state1 = (s1 << 36 | s1 >>> 28); // c
105        /*
106        state0 = Long.rotateLeft(s0, 55) ^ s1 ^ (s1 << 14); // a, b
107        state1 = Long.rotateLeft(s1, 36); // c
108        */
109        return result;
110    }
111
112    /**
113     * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
114     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to
115     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
116     *
117     * @return a copy of this RandomnessSource
118     */
119    @Override
120    public XoRoRNG copy() {
121        XoRoRNG next = new XoRoRNG(state0);
122        next.state0 = state0;
123        next.state1 = state1;
124        return next;
125    }
126
127
128    /**
129     * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
130     * @return any int, all 32 bits are random
131     */
132    public int nextInt() {
133        return (int)nextLong();
134    }
135
136    /**
137     * Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive
138     * result.
139     * @param bound the outer exclusive bound; may be positive or negative
140     * @return a random int between 0 (inclusive) and bound (exclusive)
141     */
142    public int nextInt(final int bound) {
143        return (int) ((bound * (nextLong() >>> 33)) >> 31);
144    }
145    /**
146     * Inclusive lower, exclusive upper.
147     * @param inner the inner bound, inclusive, can be positive or negative
148     * @param outer the outer bound, exclusive, should be positive, should usually be greater than inner
149     * @return a random int that may be equal to inner and will otherwise be between inner and outer
150     */
151    public int nextInt(final int inner, final int outer) {
152        return inner + nextInt(outer - inner);
153    }
154
155    /**
156     * Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive
157     * result.
158     * @param bound the outer exclusive bound; may be positive or negative
159     * @return a random long between 0 (inclusive) and bound (exclusive)
160     */
161    public long nextLong(long bound) {
162        long rand = nextLong();
163        final long randLow = rand & 0xFFFFFFFFL;
164        final long boundLow = bound & 0xFFFFFFFFL;
165        rand >>>= 32;
166        bound >>= 32;
167        final long t = rand * boundLow + (randLow * boundLow >>> 32);
168        return rand * bound + (t >> 32) + (randLow * bound + (t & 0xFFFFFFFFL) >> 32);
169    }
170    /**
171     * Inclusive inner, exclusive outer; both inner and outer can be positive or negative.
172     * @param inner the inner bound, inclusive, can be positive or negative
173     * @param outer the outer bound, exclusive, can be positive or negative and may be greater than or less than inner
174     * @return a random long that may be equal to inner and will otherwise be between inner and outer
175     */
176    public long nextLong(final long inner, final long outer) {
177        return inner + nextLong(outer - inner);
178    }
179
180    public double nextDouble() {
181        return (nextLong() & DOUBLE_MASK) * NORM_53;
182    }
183
184    public float nextFloat() {
185        return (float) ((nextLong() & FLOAT_MASK) * NORM_24);
186    }
187
188    public boolean nextBoolean() {
189        return nextLong() < 0L;
190    }
191
192    public void nextBytes(final byte[] bytes) {
193        int i = bytes.length, n;
194        while (i != 0) {
195            n = Math.min(i, 8);
196            for (long bits = nextLong(); n-- != 0; bits >>>= 8) {
197                bytes[--i] = (byte) bits;
198            }
199        }
200    }
201
202    /**
203     * Sets the seed of this generator using one long, running that through LightRNG's algorithm twice to get the state.
204     * @param seed the number to use as the seed
205     */
206    public void setSeed(final long seed) {
207
208        long state = seed + 0x9E3779B97F4A7C15L,
209                z = state;
210        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
211        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
212        state0 = z ^ (z >>> 31);
213        state += 0x9E3779B97F4A7C15L;
214        z = state;
215        z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
216        z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
217        state1 = z ^ (z >>> 31);
218    }
219
220    /**
221     * Sets the seed of this generator using two longs, using them without changes unless both are 0 (then it makes the
222     * state variable corresponding to stateA 1 instead).
223     * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0
224     * @param stateB the number to use as the second part of the state
225     */
226    public void setSeed(final long stateA, final long stateB) {
227
228        state0 = stateA;
229        state1 = stateB;
230        if((stateA | stateB) == 0L)
231            state0 = 1L;
232    }
233
234    /**
235     * Gets the first component of this generator's two-part state, as a long. This can be 0 on its own, but will never
236     * be 0 at the same time as the other component of state, {@link #getStateB()}. You can set the state with two exact
237     * values using {@link #setSeed(long, long)}, but the alternative overload {@link #setSeed(long)} won't use the
238     * state without changing it (it needs to cover 128 bits with a 64-bit value).
239     * @return the first component of this generator's state
240     */
241    public long getStateA()
242    {
243        return state0;
244    }
245    /**
246     * Gets the second component of this generator's two-part state, as a long. This can be 0 on its own, but will never
247     * be 0 at the same time as the other component of state, {@link #getStateA()}. You can set the state with two exact
248     * values using {@link #setSeed(long, long)}, but the alternative overload {@link #setSeed(long)} won't use the
249     * state without changing it (it needs to cover 128 bits with a 64-bit value).
250     * @return the second component of this generator's state
251     */
252    public long getStateB()
253    {
254        return state1;
255    }
256
257    @Override
258    public String toString() {
259        return "XoRoRNG with stateA 0x" + StringKit.hex(state0) + "L and stateB 0x" + StringKit.hex(state1) + 'L';
260    }
261
262    @Override
263    public boolean equals(Object o) {
264        if (this == o) return true;
265        if (o == null || getClass() != o.getClass()) return false;
266
267        XoRoRNG xoRoRNG = (XoRoRNG) o;
268
269        if (state0 != xoRoRNG.state0) return false;
270        return state1 == xoRoRNG.state1;
271    }
272
273    @Override
274    public int hashCode() {
275        return (int) (31L * (state0 ^ (state0 >>> 32)) + (state1 ^ (state1 >>> 32)));
276    }
277}