001package squidpony.squidmath; 002 003import squidpony.StringKit; 004 005import java.io.Serializable; 006 007/** 008 * An IRNG implementation that is meant to provide random numbers very quickly when targeting GWT but also to produce 009 * the same numbers when used on desktop, Android, or other platforms, and that can have its state read as a 010 * StatefulRandomness. This uses the same algorithm as {@link Starfish32RNG}, which means it has two 32-bit ints for 011 * state and a period of 0xFFFFFFFFFFFFFFFF (2 to the 64 minus 1), while passing 32TB of PractRand tests without any 012 * failures or anomalies (so its quality is very good). This previously used {@link Lathe32RNG}'s algorithm, which is a 013 * tiny bit faster on desktop and a fair amount faster on GWT, but can't produce all long values and produces some more 014 * often than others. Unlike {@link RNG}, there is no RandomnessSource that can be swapped out, but also somewhat less 015 * indirection on common calls like {@link #nextInt()} and {@link #nextFloat()}. Although this implements 016 * {@link StatefulRandomness}, it is not recommended to use this as the RandomnessSource for a StatefulRNG; you should 017 * use {@link Starfish32RNG} if you want the larger API provided by StatefulRNG and/or RNG while keeping similar, though 018 * probably slightly weaker, GWT performance relative to this class. Any performance measurements on GWT depend heavily 019 * on the browser; in some versions of Chrome and Chromium, this performs almost exactly as well as Lathe32RNG, but in 020 * newer versions it lags behind by a small factor. It tends to be very fast in the current Firefox (September 2018). 021 * <br> 022 * Be advised: if you subtract {@code 0x9E3779BD} from every output, that modified output will fail some tests reliably. 023 * Similar numbers may also cause this result, though it isn't clear if this is ever relevant in actual usage. Part of 024 * the reason Lathe32RNG was switched out was because its behavior on {@link #between(int, int)} was poor, but it 025 * doesn't seem to be for this version. 026 * <br> 027 * <a href="http://xoshiro.di.unimi.it/xoroshiro64starstar.c">Original version here for xoroshiro64**</a>. 028 * <br> 029 * Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) 030 * Ported and modified in 2018 and 2019 by Tommy Ettinger 031 * @author Sebastiano Vigna 032 * @author David Blackman 033 * @author Tommy Ettinger (if there's a flaw, use SquidLib's issues and don't bother Vigna or Blackman, the algorithm here has been adjusted from their work) 034 */ 035public final class GWTRNG extends AbstractRNG implements IStatefulRNG, Serializable { 036 private static final long serialVersionUID = 3L; 037 038 public int stateA, stateB; 039 040 /** 041 * Creates a new generator seeded using two calls to Math.random(). 042 */ 043 public GWTRNG() 044 { 045 setState((int)((Math.random() * 2.0 - 1.0) * 0x80000000), (int)((Math.random() * 2.0 - 1.0) * 0x80000000)); 046 } 047 /** 048 * Constructs this GWTRNG by dispersing the bits of seed using {@link #setSeed(int)} across the two parts of state 049 * this has. 050 * @param seed an int that won't be used exactly, but will affect both components of state 051 */ 052 public GWTRNG(final int seed) { 053 setSeed(seed); 054 } 055 /** 056 * Constructs this GWTRNG by splitting the given seed across the two parts of state this has with 057 * {@link #setState(long)}. 058 * @param seed a long that will be split across both components of state 059 */ 060 public GWTRNG(final long seed) { 061 setState(seed); 062 } 063 /** 064 * Constructs this GWTRNG by calling {@link #setState(int, int)} on stateA and stateB as given; see that method 065 * for the specific details (stateA and stateB are kept as-is unless they are both 0). 066 * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0 067 * @param stateB the number to use as the second part of the state 068 */ 069 public GWTRNG(final int stateA, final int stateB) { 070 setState(stateA, stateB); 071 } 072 073 /** 074 * Hashes {@code seed} using both {@link CrossHash#hash(CharSequence)} and {@link String#hashCode()} and uses those 075 * two results as the two states with {@link #setState(int, int)}. If seed is null, this won't call 076 * String.hashCode() on it and will instead use 1 as that state (to avoid the forbidden double-zero case). 077 * @param seed any String; may be null 078 */ 079 public GWTRNG(final String seed) { 080 setState(CrossHash.hash(seed), seed == null ? 1 : seed.hashCode()); 081 } 082 083 /** 084 * Get up to 32 bits (inclusive) of random output; the int this produces 085 * will not require more than {@code bits} bits to represent. 086 * 087 * @param bits an int between 1 and 32, both inclusive 088 * @return a random number that fits in the specified number of bits 089 */ 090 @Override 091 public final int next(int bits) { 092 final int s0 = stateA; 093 final int s1 = stateB ^ s0; 094 final int result = s0 * 31; 095 stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 096 stateB = (s1 << 13 | s1 >>> 19); 097 return (result << 28 | result >>> 4) + 0x9E3779BD >>> (32 - bits); 098 } 099 100 /** 101 * Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive). 102 * 103 * @return a 32-bit random int. 104 */ 105 @Override 106 public final int nextInt() { 107 final int s0 = stateA; 108 final int s1 = stateB ^ s0; 109 final int result = s0 * 31; 110 stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 111 stateB = (s1 << 13 | s1 >>> 19); 112 return (result << 28 | result >>> 4) + 0x9E3779BD; 113 } 114 /** 115 * Returns a random non-negative integer below the given bound, or 0 if the bound is 0 or 116 * negative. 117 * 118 * @param bound the upper bound (exclusive) 119 * @return the found number 120 */ 121 @Override 122 public final int nextInt(final int bound) { 123 final int s0 = stateA; 124 final int s1 = stateB ^ s0; 125 final int result = s0 * 31; 126 stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 127 stateB = (s1 << 13 | s1 >>> 19); 128 return (int) ((bound * ((result << 28 | result >>> 4) + 0x9E3779BD & 0xFFFFFFFFL)) >>> 32) & ~(bound >> 31); 129 } 130 131 /** 132 * Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive). 133 * 134 * @return a 64-bit random long. 135 */ 136 @Override 137 public final long nextLong() { 138 int s0 = stateA; 139 int s1 = stateB ^ s0; 140 final int high = s0 * 31; 141 s0 = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 142 s1 = (s1 << 13 | s1 >>> 19) ^ s0; 143 final int low = s0 * 31; 144 stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 145 stateB = (s1 << 13 | s1 >>> 19); 146 return ((high << 28 | high >>> 4) + 0x9E3779BDL) << 32 147 | ((low << 28 | low >>> 4) + 0x9E3779BD & 0xFFFFFFFFL); 148 } 149 150 /** 151 * Get a random bit of state, interpreted as true or false with approximately equal likelihood. 152 * This implementation uses a sign check as a safeguard, since its algorithm is based on (but is not equivalent to) 153 * xoroshiro, which recommends a sign check instead of using the least significant bit. 154 * 155 * @return a random boolean. 156 */ 157 @Override 158 public final boolean nextBoolean() { 159 final int s0 = stateA; 160 final int s1 = stateB ^ s0; 161 stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 162 stateB = (s1 << 13 | s1 >>> 19); 163 return (s0 * 31 & 8) == 8; // same effect as a sign check if this was rotated as normal 164 } 165 166 /** 167 * Gets a random double between 0.0 inclusive and 1.0 exclusive. 168 * This returns a maximum of 0.9999999999999999 because that is the largest double value that is less than 1.0 . 169 * 170 * @return a double between 0.0 (inclusive) and 0.9999999999999999 (inclusive) 171 */ 172 @Override 173 public final double nextDouble() { 174 int s0 = stateA; 175 int s1 = stateB ^ s0; 176 final int high = s0 * 31; 177 s0 = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 178 s1 = (s1 << 13 | s1 >>> 19) ^ s0; 179 final int low = s0 * 31; 180 stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 181 stateB = (s1 << 13 | s1 >>> 19); 182 return ((((high << 28 | high >>> 4) + 0x9E3779BDL) << 32 183 | ((low << 28 | low >>> 4) + 0x9E3779BD & 0xFFFFFFFFL)) 184 & 0x1FFFFFFFFFFFFFL) * 0x1p-53; 185 } 186 187 /** 188 * Gets a random float between 0.0f inclusive and 1.0f exclusive. 189 * This returns a maximum of 0.99999994 because that is the largest float value that is less than 1.0f . 190 * 191 * @return a float between 0f (inclusive) and 0.99999994f (inclusive) 192 */ 193 @Override 194 public final float nextFloat() { 195 final int s0 = stateA; 196 final int s1 = stateB ^ s0; 197 final int result = s0 * 31; 198 stateA = (s0 << 26 | s0 >>> 6) ^ s1 ^ (s1 << 9); 199 stateB = (s1 << 13 | s1 >>> 19); 200 return ((result << 28 | result >>> 4) + 0x9E3779BD & 0xffffff) * 0x1p-24f; 201 } 202 203 /** 204 * Creates a copy of this GWTRNG; it will generate the same random numbers, given the same calls in order, as this 205 * GWTRNG at the point copy() is called. The copy will not share references with this GWTRNG. 206 * 207 * @return a copy of this GWTRNG 208 */ 209 @Override 210 public GWTRNG copy() { 211 return new GWTRNG(stateA, stateB); 212 } 213 214 /** 215 * Gets a view of this IRNG in a way that implements {@link Serializable}, which is simply this IRNG. 216 * @return a {@link Serializable} view of this IRNG or a similar one; always {@code this} 217 */ 218 @Override 219 public Serializable toSerializable() { 220 return this; 221 } 222 /** 223 * Sets the state of this generator using one int, running it through Zog32RNG's algorithm two times to get 224 * two ints. If the states would both be 0, state A is assigned 1 instead. 225 * @param seed the int to use to produce this generator's state 226 */ 227 public void setSeed(final int seed) { 228 int z = seed + 0xC74EAD55, a = seed ^ z; 229 a ^= a >>> 14; 230 z = (z ^ z >>> 10) * 0xA5CB3; 231 a ^= a >>> 15; 232 stateA = (z ^ z >>> 20) + (a ^= a << 13); 233 z = seed + 0x8E9D5AAA; 234 a ^= a >>> 14; 235 z = (z ^ z >>> 10) * 0xA5CB3; 236 a ^= a >>> 15; 237 stateB = (z ^ z >>> 20) + (a ^ a << 13); 238 if((stateA | stateB) == 0) 239 stateA = 1; 240 } 241 242 public int getStateA() 243 { 244 return stateA; 245 } 246 /** 247 * Sets the first part of the state to the given int. As a special case, if the parameter is 0 and stateB is 248 * already 0, this will set stateA to 1 instead, since both states cannot be 0 at the same time. Usually, you 249 * should use {@link #setState(int, int)} to set both states at once, but the result will be the same if you call 250 * setStateA() and then setStateB() or if you call setStateB() and then setStateA(). 251 * @param stateA any int 252 */ 253 254 public void setStateA(int stateA) 255 { 256 this.stateA = (stateA | stateB) == 0 ? 1 : stateA; 257 } 258 public int getStateB() 259 { 260 return stateB; 261 } 262 263 /** 264 * Sets the second part of the state to the given int. As a special case, if the parameter is 0 and stateA is 265 * already 0, this will set stateA to 1 and stateB to 0, since both cannot be 0 at the same time. Usually, you 266 * should use {@link #setState(int, int)} to set both states at once, but the result will be the same if you call 267 * setStateA() and then setStateB() or if you call setStateB() and then setStateA(). 268 * @param stateB any int 269 */ 270 public void setStateB(int stateB) 271 { 272 this.stateB = stateB; 273 if((stateB | stateA) == 0) stateA = 1; 274 } 275 276 /** 277 * Sets the current internal state of this GWTRNG with three ints, where stateA and stateB can each be any int 278 * unless they are both 0 (which will be treated as if stateA is 1 and stateB is 0). 279 * @param stateA any int (if stateA and stateB are both 0, this will be treated as 1) 280 * @param stateB any int 281 */ 282 public void setState(int stateA, int stateB) 283 { 284 this.stateA = stateA == 0 && stateB == 0 ? 1 : stateA; 285 this.stateB = stateB; 286 } 287 288 /** 289 * Get the current internal state of the StatefulRandomness as a long. 290 * 291 * @return the current internal state of this object. 292 */ 293 @Override 294 public long getState() { 295 return stateA & 0xFFFFFFFFL | ((long)stateB) << 32; 296 } 297 298 /** 299 * Set the current internal state of this StatefulRandomness with a long. 300 * 301 * @param state a 64-bit long. You should avoid passing 0; this implementation will treat it as 1. 302 */ 303 @Override 304 public void setState(long state) { 305 stateA = state == 0 ? 1 : (int)(state & 0xFFFFFFFFL); 306 stateB = (int)(state >>> 32); 307 } 308 309 @Override 310 public boolean equals(Object o) { 311 if (this == o) return true; 312 if (o == null || getClass() != o.getClass()) return false; 313 314 GWTRNG gwtrng = (GWTRNG) o; 315 316 if (stateA != gwtrng.stateA) return false; 317 return stateB == gwtrng.stateB; 318 } 319 320 @Override 321 public int hashCode() { 322 return 31 * stateA + stateB; 323 } 324 325 @Override 326 public String toString() { 327 return "GWTRNG with stateA 0x" + StringKit.hex(stateA) + " and stateB 0x" + StringKit.hex(stateB); 328 } 329 330 /** 331 * A deterministic random int generator that, given one int {@code state} as input, irreversibly returns an 332 * almost-always-different int as a result. Unlike the rest of GWTRNG, this will not produce all possible ints given 333 * all ints as inputs, and probably a third of all possible ints cannot be returned. You should call this with 334 * {@code GWTRNG.determineInt(state = state + 1 | 0)} (you can subtract 1 to go backwards instead of forwards), 335 * which will allow overflow in the incremented state to be handled the same on GWT as on desktop. 336 * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineInt(state = state + 1 | 0)} to handle overflow 337 * @return a not-necessarily-unique int that is usually very different from {@code state} 338 */ 339 public static int determineInt(int state) { 340 return (state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19; 341 } 342 343 /** 344 * A deterministic random int generator that, given one int {@code state} and an outer int {@code bound} as input, 345 * returns an int between 0 (inclusive) and {@code bound} (exclusive) as a result, which should have no noticeable 346 * correlation between {@code state} and the result. You should call this with 347 * {@code GWTRNG.determineBound(state = state + 1 | 0, bound)} (you can subtract 1 to go backwards instead of 348 * forwards), which will allow overflow in the incremented state to be handled the same on GWT as on desktop. 349 * Like most bounded int generation in SquidLib, this uses some long math, but most of the function uses ints. 350 * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineBounded(state = state + 1 | 0, bound)} to handle overflow 351 * @param bound the outer exclusive bound, as an int; may be positive or negative 352 * @return an int between 0 (inclusive) and {@code bound} (exclusive) 353 */ 354 public static int determineBounded(int state, final int bound) 355 { 356 return (int) ((((state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) & 0xFFFFFFFFL) * bound >> 32); 357 } 358 /** 359 * A deterministic random long generator that, given one int {@code state} as input, returns an 360 * almost-always-different long as a result. This can only return a tiny fraction of all possible longs, since there 361 * are at most 2 to the 32 possible ints and this doesn't even return different values for each of those. You should 362 * call this with {@code GWTRNG.determine(state = state + 1 | 0)} (you can subtract 1 to go backwards instead of 363 * forwards), which will allow overflow in the incremented state to be handled the same on GWT as on desktop. 364 * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determine(state = state + 1 | 0)} to handle overflow 365 * @return a not-necessarily-unique long that is usually very different from {@code state} 366 */ 367 public static long determine(int state) 368 { 369 int r = (state ^ 0xD1B54A35) * 0x102473; 370 return ((long) ((r = (r ^ r >>> 11 ^ r >>> 21) * (r | 0xFFE00001)) ^ r >>> 13 ^ r >>> 19) << 32) 371 | (((state = ((state = (r ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) & 0xFFFFFFFFL); 372 } 373 /** 374 * A deterministic random float generator that, given one int {@code state} as input, returns an 375 * almost-always-different float between 0.0f and 1.0f as a result. Unlike the rest of GWTRNG, this might not 376 * produce all possible floats given all ints as inputs, and some fraction of possible floats cannot be returned. 377 * You should call this with {@code GWTRNG.determineFloat(state = state + 1 | 0)} (you can subtract 1 to go 378 * backwards instead of forwards), which will allow overflow in the incremented state to be handled the same on GWT 379 * as on desktop. 380 * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineFloat(state = state + 1 | 0)} to handle overflow 381 * @return a not-necessarily-unique float from 0.0f to 1.0f that is usually very different from {@code state} 382 */ 383 public static float determineFloat(int state) { 384 return (((state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) & 0xFFFFFF) * 0x1p-24f; 385 } 386 /** 387 * A deterministic random double generator that, given one int {@code state} as input, returns an 388 * almost-always-different double between 0.0 and 1.0 as a result. This cannot produce more than a tiny fraction of 389 * all possible doubles because the input is 32 bits and at least 53 bits are needed to represent most doubles from 390 * 0.0 to 1.0. You should call this with {@code GWTRNG.determineDouble(state = state + 1 | 0)} (you can subtract 1 391 * to go backwards instead of forwards), which will allow overflow in the incremented state to be handled the same 392 * on GWT as on desktop. 393 * @param state an int that should go up or down by 1 each call, as with {@code GWTRNG.determineDouble(state = state + 1 | 0)} to handle overflow 394 * @return a not-necessarily-unique double from 0.0 to 1.0 that is usually very different from {@code state} 395 */ 396 public static double determineDouble(int state) 397 { 398 return ((state = ((state = (state ^ 0xD1B54A35) * 0x102473) ^ state >>> 11 ^ state >>> 21) * (state | 0xFFE00001)) ^ state >>> 13 ^ state >>> 19) * 0x1p-32 + 0.5; 399 } 400}