001package squidpony.squidmath; 002 003import java.io.Serializable; 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.Collection; 007import java.util.Collections; 008import java.util.Iterator; 009import java.util.List; 010 011/** 012 * A helper class for implementing {@link IRNG} without so much busy-work. 013 * You need to provide implementations for the abstract methods {@link #nextInt()}, {@link #next(int)}, 014 * {@link #nextLong()}, {@link #nextBoolean()}, {@link #nextDouble()}, {@link #nextFloat()}, {@link #copy()}, and 015 * {@link #toSerializable()}, many of which may be built off of each other and some of which have sample code in their 016 * documentation strings in this class. 017 * <br> 018 * Big thanks to smelc for the concept in his hgameshrogue library. 019 * @author Tommy Ettinger 020 * @author smelC 021 */ 022public abstract class AbstractRNG implements IRNG { 023 /** 024 * Get up to 32 bits (inclusive) of random output; the int this produces 025 * will not require more than {@code bits} bits to represent. 026 * 027 * @param bits an int between 1 and 32, both inclusive 028 * @return a random number that fits in the specified number of bits 029 */ 030 @Override 031 public abstract int next(int bits); 032 /** 033 * Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive). 034 * 035 * @return a 32-bit random int. 036 */ 037 @Override 038 public abstract int nextInt(); 039 040 /** 041 * Returns a random non-negative integer below the given bound, or 0 if the bound is 0 or 042 * negative. 043 * 044 * @param bound the upper bound (exclusive) 045 * @return the found number 046 */ 047 @Override 048 public int nextInt(int bound) { 049 return (int) ((bound * ((long)next(31))) >>> 31) & ~(bound >> 31); 050 } 051 052 /** 053 * Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive). 054 * 055 * @return a 64-bit random long. 056 */ 057 @Override 058 public abstract long nextLong(); 059 060 /** 061 * Exclusive on bound (which must be positive), with an inner bound of 0. 062 * If bound is negative or 0 this always returns 0. 063 * <br> 064 * Credit for this method goes to <a href="https://oroboro.com/large-random-in-range/">Rafael Baptista's blog</a> 065 * for the original idea, and the JDK10 Math class' usage of Karatsuba multiplication for the current algorithm. 066 * This method is drastically faster than the previous implementation when the bound varies often (roughly 4x 067 * faster, possibly more). It also always gets exactly one random long, so by default it advances the state as much 068 * as {@link #nextLong()}; subclasses can generate two ints instead of one long if they prefer. 069 * 070 * @param bound the outer exclusive bound; should be positive, otherwise this always returns 0L 071 * @return a random long between 0 (inclusive) and bound (exclusive) 072 */ 073 @Override 074 public long nextLong(long bound) { 075 long rand = nextLong(); 076 if (bound <= 0) return 0; 077 final long randLow = rand & 0xFFFFFFFFL; 078 final long boundLow = bound & 0xFFFFFFFFL; 079 rand >>>= 32; 080 bound >>>= 32; 081 final long a = rand * bound; 082 final long b = randLow * boundLow; 083 return (((b >>> 32) + (rand + randLow) * (bound + boundLow) - a - b) >>> 32) + a; 084 } 085 086 /** 087 * Get a random bit of state, interpreted as true or false with approximately equal likelihood. 088 * <br> 089 * Note: This is abstract because some implementations may be best served by using {@link #next(int)} to get 1 bit, 090 * returning {@code next(1) == 1}, but others will get much better results with a sign check by calling their choice 091 * of {@link #nextInt()} or {@link #nextLong()} and returning {@code nextInt() < 0} or {@code nextLong < 0L}. For 092 * example, an implementation that uses a linear congruential generator without truncating some lower bits will have 093 * very-low-period results for the bottom bit (alternating true and false), but perfectly fine results from a sign 094 * check. There are tested issues on the bottom (at least 2) bits of {@link XoRoRNG}, but again not on a sign check. 095 * @return a random boolean. 096 */ 097 @Override 098 public abstract boolean nextBoolean(); 099 /** 100 * Gets a random double between 0.0 inclusive and 1.0 exclusive. 101 * This returns a maximum of 0.9999999999999999 because that is the largest double value that is less than 1.0 . 102 * <br> 103 * This is abstract because some generators may natively work with double or float values, but others may need to 104 * convert a long to a double as with {@code (nextLong() & 0x1fffffffffffffL) * 0x1p-53}, which is recommended if 105 * longs are fast to produce. 106 * @return a double between 0.0 (inclusive) and 0.9999999999999999 (inclusive) 107 */ 108 @Override 109 public abstract double nextDouble(); 110 /** 111 * This returns a random double between 0.0 (inclusive) and outer (exclusive). The value for outer can be positive 112 * or negative. Because of how math on doubles works, there are at most 2 to the 53 values this can return for any 113 * given outer bound, and very large values for outer will not necessarily produce all numbers you might expect. 114 * 115 * @param outer the outer exclusive bound as a double; can be negative or positive 116 * @return a double between 0.0 (inclusive) and outer (exclusive) 117 */ 118 @Override 119 public double nextDouble(double outer) { 120 return nextDouble() * outer; 121 } 122 123 /** 124 * Gets a random float between 0.0f inclusive and 1.0f exclusive. 125 * This returns a maximum of 0.99999994 because that is the largest float value that is less than 1.0f . 126 * <br> 127 * This is abstract because some generators may natively work with double or float values, but others may need to 128 * convert an int or long to a float as with {@code (nextInt() & 0xffffff) * 0x1p-24f}, 129 * {@code (nextLong() & 0xffffffL) * 0x1p-24f}, or {@code next(24) * 0x1p-24f}, any of which can work when the 130 * method they call is high-quality and fast. You probably would want to use nextInt() or next() if your 131 * implementation is natively 32-bit and is slower at producing longs, for example. 132 * @return a float between 0f (inclusive) and 0.99999994f (inclusive) 133 */ 134 @Override 135 public abstract float nextFloat(); 136 /** 137 * This returns a random float between 0.0f (inclusive) and outer (exclusive). The value for outer can be positive 138 * or negative. Because of how math on floats works, there are at most 2 to the 24 values this can return for any 139 * given outer bound, and very large values for outer will not necessarily produce all numbers you might expect. 140 * 141 * @param outer the outer exclusive bound as a float; can be negative or positive 142 * @return a float between 0f (inclusive) and outer (exclusive) 143 */ 144 @Override 145 public float nextFloat(float outer) { 146 return nextFloat() * outer; 147 } 148 /** 149 * Exclusive on bound (which may be positive or negative), with an inner bound of 0. 150 * If bound is negative this returns a negative long; if bound is positive this returns a positive long. The bound 151 * can even be 0, which will cause this to return 0L every time. This uses a biased technique to get numbers from 152 * large ranges, but the amount of bias is incredibly small (expected to be under 1/1000 if enough random ranged 153 * numbers are requested, which is about the same as an unbiased method that was also considered). It may have 154 * noticeable bias if the generator's period is exhausted by only calls to this method. Unlike all unbiased methods, 155 * this advances the state by an equivalent to exactly one call to {@link #nextLong()}, where rejection sampling 156 * would sometimes advance by one call, but other times by arbitrarily many more. 157 * <br> 158 * Credit for this method goes to <a href="https://oroboro.com/large-random-in-range/">Rafael Baptista's blog</a> 159 * for the original idea, and the JDK10 Math class' usage of Hacker's Delight code for the current algorithm. 160 * This method is drastically faster than the previous implementation when the bound varies often (roughly 4x 161 * faster, possibly more). It also always gets exactly one random long, so by default it advances the state as much 162 * as {@link #nextLong()}; subclasses that are better at generating ints can override this and generate two ints 163 * instead of one long that needs separating internally. 164 * 165 * @param bound the outer exclusive bound; can be positive or negative 166 * @return a random long between 0 (inclusive) and bound (exclusive) 167 */ 168 @Override 169 public long nextSignedLong(long bound) { 170 long rand = nextLong(); 171 final long randLow = rand & 0xFFFFFFFFL; 172 final long boundLow = bound & 0xFFFFFFFFL; 173 rand >>>= 32; 174 bound >>= 32; 175 final long t = rand * boundLow + (randLow * boundLow >>> 32); 176 return rand * bound + (t >> 32) + (randLow * bound + (t & 0xFFFFFFFFL) >> 32); 177 } 178 179 /** 180 * Returns a random non-negative integer between 0 (inclusive) and the given bound (exclusive), 181 * or 0 if the bound is 0. The bound can be negative, which will produce 0 or a negative result. 182 * <br> 183 * Credit goes to Daniel Lemire, http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ 184 * 185 * @param bound the outer bound (exclusive), can be negative or positive 186 * @return the found number 187 */ 188 @Override 189 public int nextSignedInt(final int bound) { 190 return (int) ((bound * (nextInt() & 0xFFFFFFFFL)) >> 32); 191 } 192 193 /** 194 * Returns a value between min (inclusive) and max (exclusive) as ints. 195 * <br> 196 * The inclusive and exclusive behavior is to match the behavior of the similar 197 * method that deals with floating point values. 198 * <br> 199 * If {@code min} and {@code max} happen to be the same, {@code min} is returned 200 * (breaking the exclusive behavior, but it's convenient to do so). 201 * 202 * @param min the minimum bound on the return value (inclusive) 203 * @param max the maximum bound on the return value (exclusive) 204 * @return the found value 205 */ 206 @Override 207 public int between(int min, int max) { 208 return nextInt(max - min) + min; 209 } 210 211 /** 212 * Returns a value between min (inclusive) and max (exclusive) as longs. 213 * <br> 214 * The inclusive and exclusive behavior is to match the behavior of the similar 215 * method that deals with floating point values. 216 * <br> 217 * If {@code min} and {@code max} happen to be the same, {@code min} is returned 218 * (breaking the exclusive behavior, but it's convenient to do so). 219 * 220 * @param min the minimum bound on the return value (inclusive) 221 * @param max the maximum bound on the return value (exclusive) 222 * @return the found value 223 */ 224 @Override 225 public long between(long min, long max) { 226 return nextLong(max - min) + min; 227 } 228 229 /** 230 * Returns a value from a uniform distribution from min (inclusive) to max 231 * (exclusive). 232 * 233 * @param min the minimum bound on the return value (inclusive) 234 * @param max the maximum bound on the return value (exclusive) 235 * @return the found value 236 */ 237 @Override 238 public double between(double min, double max) { 239 return nextDouble(max - min) + min; 240 } 241 242 /** 243 * Returns a random element from the provided array and maintains object 244 * type. 245 * 246 * @param array the array to get an element from 247 * @return the randomly selected element 248 */ 249 @Override 250 public <T> T getRandomElement(T[] array) { 251 if (array.length < 1) { 252 return null; 253 } 254 return array[nextInt(array.length)]; 255 } 256 257 /** 258 * Returns a random element from the provided list. If the list is empty 259 * then null is returned. This will perform well on Lists that allow random access, 260 * but will not perform as well on {@link java.util.LinkedList} or similar classes 261 * that need to iterate one-by-one in their {@link List#get(int)} method. 262 * 263 * @param list the list to get an element from 264 * @return the randomly selected element 265 */ 266 @Override 267 public <T> T getRandomElement(List<T> list) { 268 if (list.isEmpty()) { 269 return null; 270 } 271 return list.get(nextInt(list.size())); 272 } 273 274 /** 275 * Returns a random element from the provided Collection, which should have predictable iteration order if you want 276 * predictable behavior for identical RNG seeds, though it will get a random element just fine for any Collection 277 * (just not predictably in all cases). If you give this a Set, it should be a LinkedHashSet or some form of sorted 278 * Set like TreeSet if you want predictable results. Any List or Queue should be fine. Map does not implement 279 * Collection, thank you very much Java library designers, so you can't actually pass a Map to this, though you can 280 * pass the keys or values. If coll is empty, returns null. 281 * <br> 282 * Requires iterating through a random amount of coll's elements, so performance depends on the size of coll but is 283 * likely to be decent, as long as iteration isn't unusually slow. This replaces {@code getRandomElement(Queue)}, 284 * since Queue implements Collection and the older Queue-using implementation was probably less efficient. 285 * <br> 286 * You should generally prefer {@link #getRandomElement(List)} whenever possible, or in some cases you can use 287 * methods that get a random value on the Collection (or Map, in the case of OrderedMap) itself. 288 * 289 * @param coll the Collection to get an element from; remember, Map does not implement Collection 290 * @return the randomly selected element 291 */ 292 @Override 293 public <T> T getRandomElement(Collection<T> coll) { 294 int n; 295 if ((n = coll.size()) <= 0) { 296 return null; 297 } 298 n = nextInt(n); 299 T t = null; 300 Iterator<T> it = coll.iterator(); 301 while (n-- >= 0 && it.hasNext()) 302 t = it.next(); 303 return t; 304 } 305 306 /** 307 * Mutates the array arr by switching the contents at pos1 and pos2. 308 * @param arr an array of T; must not be null 309 * @param pos1 an index into arr; must be at least 0 and no greater than arr.length 310 * @param pos2 an index into arr; must be at least 0 and no greater than arr.length 311 */ 312 protected static <T> void swap(T[] arr, int pos1, int pos2) { 313 final T tmp = arr[pos1]; 314 arr[pos1] = arr[pos2]; 315 arr[pos2] = tmp; 316 } 317 318 /** 319 * Shuffle an array using the Fisher-Yates algorithm and returns a shuffled copy, freshly-allocated, without 320 * modifying elements. 321 * <br> 322 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 323 * 324 * @param elements an array of T; will not be modified 325 * @return a shuffled copy of elements 326 */ 327 @Override 328 public <T> T[] shuffle(T[] elements) { 329 final int size = elements.length; 330 final T[] array = Arrays.copyOf(elements, size); 331 for (int i = size; i > 1; i--) { 332 swap(array, i - 1, nextInt(i)); 333 } 334 return array; 335 } 336 337 /** 338 * Shuffles an array in-place using the Fisher-Yates algorithm. 339 * If you don't want the array modified, use {@link #shuffle(Object[], Object[])}. 340 * <br> 341 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 342 * 343 * @param elements an array of T; <b>will</b> be modified 344 * @return elements after shuffling it in-place 345 */ 346 @Override 347 public <T> T[] shuffleInPlace(T[] elements) { 348 final int size = elements.length; 349 for (int i = size; i > 1; i--) { 350 swap(elements, i - 1, nextInt(i)); 351 } 352 return elements; 353 } 354 355 /** 356 * Shuffle an array using the Fisher-Yates algorithm. If possible, create a new array or reuse an existing array 357 * with the same length as elements and pass it in as dest; the dest array will contain the shuffled contents of 358 * elements and will also be returned as-is. If dest does not have the same length as elements, this will throw an 359 * IllegalArgumentException 360 * <br> 361 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 362 * 363 * @param elements an array of T; will not be modified 364 * @param <T> can be any non-primitive type. 365 * @param dest Where to put the shuffle. If it does not have the same length as {@code elements}, this will 366 * throw an IllegalArgumentException. 367 * @return {@code dest} after modifications 368 */ 369 @Override 370 public <T> T[] shuffle(T[] elements, T[] dest) { 371 if (dest.length != elements.length) 372 throw new IllegalArgumentException("Not allowed! In AbstractRNG.shuffle(), elements and dest must not have the same length."); 373 System.arraycopy(elements, 0, dest, 0, elements.length); 374 shuffleInPlace(dest); 375 return dest; 376 } 377 378 /** 379 * Shuffles a {@link Collection} of T using the Fisher-Yates algorithm and returns an ArrayList of T. 380 * <br> 381 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 382 * 383 * @param elements a Collection of T; will not be modified 384 * @return a shuffled ArrayList containing the whole of elements in pseudo-random order. 385 */ 386 @Override 387 public <T> ArrayList<T> shuffle(Collection<T> elements) { 388 return shuffle(elements, null); 389 } 390 391 /** 392 * Shuffles a {@link Collection} of T using the Fisher-Yates algorithm and puts it in a buffer. 393 * The result is allocated if {@code buf} is null or if {@code buf} isn't empty, 394 * otherwise {@code elements} is poured into {@code buf}. 395 * <br> 396 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 397 * 398 * @param elements a Collection of T; will not be modified 399 * @param buf a buffer as an ArrayList that will be filled with the shuffled contents of elements; 400 * if null or non-empty, a new ArrayList will be allocated and returned 401 * @return a shuffled ArrayList containing the whole of elements in pseudo-random order, which may be {@code buf} 402 */ 403 @Override 404 public <T> ArrayList<T> shuffle(Collection<T> elements, ArrayList<T> buf) { 405 final ArrayList<T> al; 406 if (buf == null || !buf.isEmpty()) 407 al = new ArrayList<>(elements); 408 else { 409 al = buf; 410 al.addAll(elements); 411 } 412 final int n = al.size(); 413 for (int i = n; i > 1; i--) { 414 Collections.swap(al, nextInt(i), i - 1); 415 } 416 return al; 417 } 418 419 /** 420 * Shuffles a Collection of T items in-place using the Fisher-Yates algorithm. 421 * This only shuffles List data structures. 422 * If you don't want the array modified, use {@link #shuffle(Collection)}, which returns a List as well. 423 * <br> 424 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 425 * 426 * @param elements a Collection of T; <b>will</b> be modified 427 * @return elements after shuffling it in-place 428 */ 429 @Override 430 public <T> List<T> shuffleInPlace(List<T> elements) { 431 final int n = elements.size(); 432 for (int i = n; i > 1; i--) { 433 Collections.swap(elements, nextInt(i), i - 1); 434 } 435 return elements; 436 } 437 438 /** 439 * Generates a random permutation of the range from 0 (inclusive) to length (exclusive). 440 * Useful for passing to OrderedMap or OrderedSet's reorder() methods. 441 * 442 * @param length the size of the ordering to produce 443 * @return a random ordering containing all ints from 0 to length (exclusive) 444 */ 445 @Override 446 public int[] randomOrdering(int length) { 447 if (length <= 0) 448 return new int[0]; 449 return randomOrdering(length, new int[length]); 450 } 451 452 /** 453 * Generates a random permutation of the range from 0 (inclusive) to length (exclusive) and stores it in 454 * the dest parameter, avoiding allocations. 455 * Useful for passing to OrderedMap or OrderedSet's reorder() methods. 456 * 457 * @param length the size of the ordering to produce; the smaller of {@code dest.length} and length will be used 458 * @param dest the destination array; will be modified 459 * @return dest, filled with a random ordering containing all ints from 0 to length (exclusive) 460 */ 461 @Override 462 public int[] randomOrdering(int length, int[] dest) { 463 if (dest == null) return null; 464 465 final int n = Math.min(length, dest.length); 466 for (int i = 0; i < n; i++) { 467 dest[i] = i; 468 } 469 for (int i = n - 1; i > 0; i--) { 470 final int r = nextInt(i+1), 471 t = dest[r]; 472 dest[r] = dest[i]; 473 dest[i] = t; 474 } 475 return dest; 476 } 477 /** 478 * Gets a random portion of data (an array), assigns that portion to output (an array) so that it fills as much as 479 * it can, and then returns output. Will only use a given position in the given data at most once; uses a Feistel 480 * Network to accomplish this without allocations. Internally, makes 2 calls to {@link #nextInt()}, regardless of 481 * the data being randomized. 482 * <br> 483 * Uses approximately the same code as {@link LowStorageShuffler}, but without any object or array allocations. 484 * 485 * @param data an array of T; will not be modified. 486 * @param output an array of T that will be overwritten; should always be instantiated with the portion length 487 * @param <T> can be any non-primitive type. 488 * @return output, after {@code Math.min(output.length, data.length)} unique items have been put into it from data 489 */ 490 @Override 491 public <T> T[] randomPortion(T[] data, T[] output) { 492 final int length = data.length, n = Math.min(length, output.length); 493 // calculate next power of 4. Needed since the balanced Feistel network needs 494 // an even number of bits to work with 495 int pow4 = HashCommon.nextPowerOfTwo(length); 496 pow4 = ((pow4 | pow4 << 1) & 0x55555554) - 1; 497 // calculate our left and right masks to split our indices for the Feistel network 498 final int halfBits = Integer.bitCount(pow4) >>> 1; 499 final int rightMask = pow4 >>> halfBits; 500 final int leftMask = pow4 ^ rightMask; 501 final int key0 = nextInt(), key1 = nextInt(); 502 int index = 0; 503 for (int i = 0; i < n; i++) { 504 int shuffleIndex; 505 // index is the index to start searching for the next number at 506 while (index <= pow4) 507 { 508 // break our index into the left and right half 509 int left = (index & leftMask) >>> halfBits; 510 int right = (index & rightMask); 511 // do 2 Feistel rounds 512 int newRight = left ^ (LowStorageShuffler.round(right, key0) & rightMask); 513 left = right; 514 right = newRight; 515 newRight = left ^ (LowStorageShuffler.round(right, key1) & rightMask); 516 shuffleIndex = right << halfBits | newRight; 517 index++; 518 519 // if we found a valid index, return it! 520 if (shuffleIndex < length) { 521 output[i] = data[shuffleIndex]; 522 break; 523 } 524 } 525 } 526 return output; 527 } 528 529 /** 530 * Creates a copy of this IRNG; it will generate the same random numbers, given the same calls in order, as this 531 * IRNG at the point copy() is called. The copy will not share references with this IRNG. If this IRNG does not 532 * permit copying itself, it is suggested to either throw an {@link UnsupportedOperationException} or return a new 533 * IRNG of the same type but with a random seed, with the latter meant as a partial defense against cheating. 534 * <br> 535 * This is abstract because every implementation is likely to have different specifics for this. 536 * @return a copy of this IRNG 537 */ 538 @Override 539 public abstract IRNG copy(); 540 541 /** 542 * Gets a view of this IRNG in a way that implements {@link Serializable}, which may simply be this IRNG if it 543 * implements Serializable as well as IRNG. 544 * <br> 545 * For implementors: It is suggested to return an {@link RNG} initialized by calling 546 * {@link RNG#RNG(long)} with {@link #nextLong()} if you are unable to save the current state of this IRNG and the 547 * caller still needs something saved. This won't preserve the current state or the choice of IRNG implementation, 548 * however, so it is simply a last resort in case you don't want to throw an exception. 549 * 550 * @return a {@link Serializable} view of this IRNG or a similar one; may be {@code this} 551 */ 552 @Override 553 public abstract Serializable toSerializable(); 554}