001/*
002 * Ported to Java from the PCG library. Its copyright header follows:
003 *
004 * PCG Random Number Generation for C++
005 *
006 * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *     http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 *
020 * For additional information about the PCG random number generation scheme,
021 * including its license and other licensing options, visit
022 *
023 *     http://www.pcg-random.org
024 */
025package squidpony.squidmath;
026
027import squidpony.StringKit;
028
029import java.io.Serializable;
030
031/**
032 * This is a RandomnessSource in the PCG-Random family. It performs pseudo-
033 * random modifications to the output based on the techniques from the
034 * Permuted Congruential Generators created by M.E. O'Neill.
035 * Specifically, this variant is:
036 * RXS M XS -- random xorshift, mcg multiply, fixed xorshift
037 *
038 * The most statistically powerful generator, but all those steps
039 * make it slower than some of the others.
040 * <br>
041 * Even though benchmarks on similar programs in C would lead you to
042 * believe this should be somewhat faster than LightRNG, benchmarking
043 * with JMH seems to show LightRNG being roughly 16% faster than
044 * PermutedRNG, and both drastically faster than java.util.Random .
045 * This generator was implemented incorrectly for a large part of its history,
046 * but it seems correct now, though it may be a little slower.
047 * @author Melissa E. O'Neill (Go HMC!)
048 * @author Tommy Ettinger
049 * @see PintRNG PintRNG is similar to this algorithm but uses only 32-bit math, where possible.
050 */
051public final class PermutedRNG implements RandomnessSource, StatefulRandomness, SkippingRandomness, Serializable
052{
053        /** 2 raised to the 53, - 1. */
054    private static final long DOUBLE_MASK = ( 1L << 53 ) - 1;
055    /** 2 raised to the -53. */
056    private static final double NORM_53 = 1. / ( 1L << 53 );
057    /** 2 raised to the 24, -1. */
058    private static final long FLOAT_MASK = ( 1L << 24 ) - 1;
059    /** 2 raised to the -24. */
060    private static final double NORM_24 = 1. / ( 1L << 24 );
061    /**
062     * The state can be seeded with any value.
063     */
064    public long state;
065
066        private static final long serialVersionUID = 3748443966125527657L;
067
068    /**
069     * Creates a new generator seeded using Math.random.
070     */
071    public PermutedRNG() {
072        this((long) ((Math.random() - 0.5) * 0x10000000000000L)
073                ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L));
074    }
075
076    /**
077     * Constructs a new PermutedRNG with the given seed as its state, exactly.
078     * @param seed a long that will be used as-is for the state of a new PermutedRNG
079     */
080    public PermutedRNG(final long seed) {
081        state = seed;
082    }
083
084    /**
085     * Gets a random int with at most the specified number of bits.
086     * Equivalent in its effect on the state to calling {@link #nextLong()} exactly one time.
087     * @param bits the number of bits to be returned, between 1 and 32
088     * @return a pseudo-random int with at most the specified bits
089     */
090    @Override
091    public final int next( final int bits ) {
092        long p = (state = state * 0x5851F42D4C957F2DL + 0x14057B7EF767814FL);
093        p = (p ^ p >>> (5 + (p >>> 59))) * 0xAEF17502108EF2D9L;
094        return (int)(p ^ p >>> 43) >>> (32 - bits);
095    }
096
097    /**
098     * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
099     * Equivalent in its effect on the state to calling {@link #nextLong()} exactly one time.
100     * @return any int, all 32 bits are random
101     */
102    public int nextInt() {
103        long p = (state = state * 0x5851F42D4C957F2DL + 0x14057B7EF767814FL);
104        p = (p ^ p >>> (5 + (p >>> 59))) * 0xAEF17502108EF2D9L;
105        return (int)(p ^ p >>> 43);
106    }
107    /**
108     * Can return any long, positive or negative, of any size permissible in a 64-bit signed integer.
109     *
110     * @return any long, all 64 bits are random
111     */
112    @Override
113    public final long nextLong()
114    {
115        // increment  = 1442695040888963407L;
116        // multiplier = 6364136223846793005L;
117
118        long p = (state = state * 0x5851F42D4C957F2DL + 0x14057B7EF767814FL);
119        p = (p ^ p >>> (5 + (p >>> 59))) * 0xAEF17502108EF2D9L;
120        return (p ^ p >>> 43);
121    }
122
123    /**
124     * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
125     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to
126     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
127     *
128     * @return a copy of this RandomnessSource
129     */
130    @Override
131    public PermutedRNG copy() {
132        return new PermutedRNG(state);
133    }
134
135    /**
136     * Exclusive on the outer bound; the inner bound is 0.
137     * Calls {@link #nextLong()} exactly once.
138     * @param bound the upper bound; can be positive or negative
139     * @return a random int less than n and at least equal to 0
140     */
141    public int nextInt( final int bound ) {
142        return (int)((bound * (nextLong() & 0x7FFFFFFFL)) >> 31);
143    }
144
145    /**
146     * Inclusive lower, exclusive upper. The upper bound is really the outer bound, and the lower bound the inner bound,
147     * because upper is permitted to be less than lower, though upper is still exclusive there.
148     * Calls {@link #nextLong()} exactly once.
149     * @param lower the lower bound, inclusive, can be positive or negative
150     * @param upper the upper bound, exclusive, can be positive or negative
151     * @return a random int at least equal to lower and less than upper (if upper is less than lower, then the result
152     *         will be less than or equal to lower and greater than upper)
153     */
154    public int nextInt( final int lower, final int upper ) {
155        return lower + nextInt(upper - lower);
156    }
157
158    /**
159     * Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive
160     * result. Calls {@link #nextLong()} exactly once.
161     * @param bound the outer exclusive bound; may be positive or negative
162     * @return a random long between 0 (inclusive) and bound (exclusive)
163     */
164    public long nextLong(long bound) {
165        long rand = nextLong();
166        final long randLow = rand & 0xFFFFFFFFL;
167        final long boundLow = bound & 0xFFFFFFFFL;
168        rand >>>= 32;
169        bound >>= 32;
170        final long t = rand * boundLow + (randLow * boundLow >>> 32);
171        return rand * bound + (t >> 32) + (randLow * bound + (t & 0xFFFFFFFFL) >> 32);
172    }
173    /**
174     * Inclusive inner, exclusive outer; both inner and outer can be positive or negative. Calls {@link #nextLong()}
175     * exactly once.
176     * @param inner the inner bound, inclusive, can be positive or negative
177     * @param outer the outer bound, exclusive, can be positive or negative and may be greater than or less than inner
178     * @return a random long that may be equal to inner and will otherwise be between inner and outer
179     */
180    public long nextLong(final long inner, final long outer) {
181        return inner + nextLong(outer - inner);
182    }
183    /**
184     * Gets a uniform random double in the range {@code [0.0,1.0)}.
185     * Calls {@link #nextLong()} exactly once.
186     * @return a random double at least equal to 0.0 and less than 1.0
187     */
188    public double nextDouble() {
189        return ( nextLong() & DOUBLE_MASK ) * NORM_53;
190    }
191
192    /**
193     * Gets a uniform random double in the range [0.0,outer) given a positive parameter outer. If outer
194     * is negative, it will be the (exclusive) lower bound and 0.0 will be the (inclusive) upper bound.
195     * Calls {@link #nextLong()} exactly once.
196     *  @param outer the exclusive outer bound, can be negative
197     * @return a random double between 0.0 (inclusive) and outer (exclusive)
198     */
199    public double nextDouble(final double outer) {
200        return nextDouble() * outer;
201    }
202
203    /**
204     * Gets a uniform random float in the range {@code [0.0,1.0)}
205     * Calls {@link #nextLong()} exactly once.
206     *
207     * @return a random float at least equal to 0.0f and less than 1.0f
208     */
209    public float nextFloat() {
210        return (float)( ( nextLong() & FLOAT_MASK ) * NORM_24 );
211    }
212
213    /**
214     * Gets a random value, true or false.
215     * Calls {@link #nextLong()} exactly once.
216     * @return a random true or false value.
217     */
218    public boolean nextBoolean() {
219        return nextLong() < 0L;
220    }
221
222    /**
223     * Given a byte array as a parameter, this will fill the array with random bytes (modifying it
224     * in-place). Calls {@link #nextLong()} {@code Math.ceil(bytes.length / 8.0)} times.
225     * @param bytes a byte array that will have its contents overwritten with random bytes.
226     */
227    public void nextBytes( final byte[] bytes ) {
228        int i = bytes.length, n;
229        while( i != 0 ) {
230            n = Math.min(i, 8 );
231            for ( long bits = nextLong(); n-- != 0; bits >>>= 8 ) bytes[ --i ] = (byte)bits;
232        }
233    }
234
235
236    /**
237     * Sets the seed of this generator (which is also the current state).
238     * @param seed the seed to use for this PermutedRNG, as if it was constructed with this seed.
239     */
240    public void setSeed( final long seed ) {
241        state = seed;
242    }
243    /**
244     * Sets the seed (also the current state) of this generator.
245     * @param seed the seed to use for this PermutedRNG, as if it was constructed with this seed.
246     */
247    @Override
248        public void setState( final long seed ) {
249        state = seed;
250    }
251    /**
252     * Gets the current state of this generator.
253     * @return the current seed of this PermutedRNG, changed once per call to {@link #nextLong()}
254     */
255    @Override
256        public long getState( ) {
257        return state;
258    }
259
260    /**
261     * Advances or rolls back the PermutedRNG's state without actually generating each number. Skips forward
262     * or backward a number of steps specified by advance, where a step is equal to one call to {@link #nextLong()},
263     * and returns the random number produced at that step (you can get the state with {@link #getState()}).
264     * Skipping ahead or behind takes more than constant time, unlike with {@link LightRNG}, but less time
265     * than calling {@link #nextLong()} {@code advance} times. Skipping backwards by one step is the worst case for this
266     * technique.
267     * @param advance Number of future generations to skip past. Can be negative to backtrack.
268     * @return the number that would be generated after generating advance random numbers.
269     */
270    @Override
271    public long skip(long advance)
272    {
273        // The method used here is based on Brown, "Random Number Generation
274        // with Arbitrary Stride,", Transactions of the American Nuclear
275        // Society (Nov. 1994).  The algorithm is very similar to fast
276        // exponentiation.
277        //
278        // Even though advance is a signed long, it is treated as unsigned, effectively, for the purposes
279        // of how many iterations it goes through (at most 63 for forwards, 64 for "backwards").
280        long acc_mult = 1, acc_plus = 0, cur_mult = 0x5851F42D4C957F2DL, cur_plus = 0x14057B7EF767814FL;
281
282        while (advance > 0L) {
283            if ((advance & 1L) != 0L) {
284                acc_mult *= cur_mult;
285                acc_plus = acc_plus*cur_mult + cur_plus;
286            }
287            cur_plus *= (cur_mult+1L);
288            cur_mult *= cur_mult;
289            advance >>>= 1;
290        }
291        long p = (state = acc_mult * state + acc_plus);
292        p = (p ^ p >>> (5 + (p >>> 59))) * 0xAEF17502108EF2D9L;
293        return (p ^ p >>> 43);
294    }
295
296    @Override
297    public String toString() {
298        return "PermutedRNG with state 0x" + StringKit.hex(state) + 'L';
299    }
300
301    /**
302     * Given suitably-different inputs as {@code state}, this will permute that state to get a seemingly-unrelated
303     * number. Unlike {@link LightRNG#determine(long)}, this will not work with inputs that are sequential, and it is
304     * recommended that subsequent calls change state with a linear congruential generator like
305     * {@code PermutedRNG.determine(state = state * 0x5851F42D4C957F2DL + 0x14057B7EF767814FL)}. It will be correct for
306     * any inputs, but if {@code state} is 0, then this will return 0.
307     * @param state a long that should be changed with {@code state = state * 0x5851F42D4C957F2DL + 0x14057B7EF767814FL}
308     * @return a pseudo-random long determined from state
309     */
310    public static long determine(long state)
311    {
312        state = (state ^ state >>> (5 + (state >>> 59))) * 0xAEF17502108EF2D9L;
313        return (state >>> 43) ^ state;
314    }
315
316    /**
317     * Given suitably-different inputs as {@code state}, this will permute that state to get a seemingly-unrelated
318     * number as an int between 0 and bound. Unlike {@link LightRNG#determine(long)}, this will not work with inputs
319     * that are sequential, and it is recommended that subsequent calls change state with a linear congruential
320     * generator like {@code PermutedRNG.determine(state = state * 0x5851F42D4C957F2DL + 0x14057B7EF767814FL)}. It will
321     * be correct for any inputs, but if {@code state} is 0, then this will return 0.
322     * @param state a long that should be changed with {@code state = state * 0x5851F42D4C957F2DL + 0x14057B7EF767814FL}
323     * @param bound the exclusive outer bound on the numbers this can produce, as an int
324     * @return a pseudo-random int between 0 (inclusive) and bound (exclusive) determined from state
325     */
326    public static int determineBounded(long state, final int bound)
327    {
328        state ^= state >>> (5 + (state >>> 59));
329        return (int)((bound * ((((state *= 0xAEF17502108EF2D9L) >>> 43) ^ state) & 0x7FFFFFFFL)) >> 31);
330    }
331}