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}