001package squidpony.squidmath; 002 003import java.io.Serializable; 004import java.util.Arrays; 005import java.util.Collections; 006import java.util.List; 007import java.util.Random; 008 009/** 010 * A high-quality and very fast RNG that has no apparent visual artifacts here; uses Mark Overton's CMR subcycle 011 * generator type, with a multiplication on the output. This is meant to be an answer to when people ask for a 012 * bare-minimum generator that's still "good enough" for games. It still passes at least 8TB of PractRand testing and 013 * passes TestU01 with both the bits in normal forward order and in reversed bit order, which is remarkable for a 014 * generator this small and simple. It has an unknown period that is fairly high; unless the seed used puts the 015 * generator in a worse cycle (some of which have a much lower period, like the seed 0), the period probably won't be 016 * exhausted without hours (possibly days) of pure random number generation. It cannot produce all possible longs in its 017 * longest cycle, and it can't produce even a fraction of all possible longs in its smallest cycle. 018 * <br> 019 * This implements RandomnessSource, but if you just want to copy this class with no dependencies, then the class 020 * declaration can easily be changed to {@code public class BasicRandom64 extends Random implements Serializable} 021 * without any other changes. Note, it does extend java.util.Random for additional ease of integration, but doesn't use 022 * the slow {@code synchronized} keyword that Random's implementations do. 023 * <br> 024 * <a href="http://www.drdobbs.com/tools/fast-high-quality-parallel-random-number/231000484">This Dr. Dobb's article has 025 * more on this type of generator</a>. A multiplication applied to the output of a CMR seems to be enough to pass 026 * stringent testing, which is amazing. 027 * @author Mark Overton 028 * @author Tommy Ettinger 029 */ 030public class BasicRandom64 extends Random implements RandomnessSource, Serializable { 031 private static final long serialVersionUID = 3L; 032 033 public long state; 034 035 /** 036 * Calls {@link #seed(int)} with a random int value (obtained using {@link Math#random()}). 037 */ 038 public BasicRandom64() 039 { 040 seed((int)((Math.random() * 2.0 - 1.0) * 0x80000000)); 041 } 042 043 /** 044 * The recommended constructor, this guarantees the generator will have a period of at least 2 to the 20 (roughly 045 * one million, but most if not all initial states will have much longer periods). All ints are permissible values 046 * for the {@code seed} parameter. 047 * @param seed any int; will be used to get the actual state used in the generator (which is a long internally) 048 */ 049 public BasicRandom64(final int seed) 050 { 051 seed(seed); 052 } 053 054 /** 055 * Like {@link #BasicRandom64(int)}, this doesn't use the seed as-is, and instead uses it to get a valid state 056 * (which is a long internally). If you want to duplicate the state of another BasicRandom64, get the existing state 057 * either with the field {@link #state} or with {@link #getState()} (you could store the state and load it later 058 * at this stage), then make some new BasicRandom64 (such as with {@code new BasicRandom64(0);}) and call 059 * {@link #setState(long)} with the previous state. You can also use {@link #copy()}. 060 * @param seed any long; will be mixed around and given to {@link #seed(int)} as an int, not used as-is 061 */ 062 public BasicRandom64(final long seed) 063 { 064 seed((int)(seed ^ seed >>> 11 ^ seed >>> 21 ^ seed >>> 32)); 065 } 066 067 /** 068 * Seeds the state using all bits of the given int {@code s}. Between 33554432 and 4294967296 seeds are possible, 069 * with the actual count probably much closer to 4294967296. This treats the top 25 bits of {@code s} (moved to the 070 * bottom, plus 1, to avoid a seed of 0) as the starting point and then generates the next state at most 127 times, 071 * with each generated state taking less time than {@link #nextLong()}. Some of the starting states are entirely 072 * possible to be within 127 steps of another starting state, so not all seeds are necessarily unique. This is not 073 * guaranteed to put the generator on an optimal subcycle, but it is guaranteed that any subcycle will have a period 074 * of at least 1048575. 075 * @param s all bits are used, none verbatim (0 is tolerated) 076 */ 077 public final void seed(final int s) { 078 long v = (s >>> 7) + 1L; // at least 2 to the 25 sequential seeds have periods of at least 1048575. 079 for (int i = (s & 0x7F); i > 0; i--) { 080 v = (v << 29 | v >>> 35) * 0xAC564B05L; 081 } 082 state = v; 083 } 084 085 public long getState() { 086 return state; 087 } 088 089 public void setState(final long seed) 090 { 091 if(seed == 0L) state = 1L; 092 else state = seed; 093 } 094 095 public final long nextLong() { 096 return (state = (state << 29 | state >>> 35) * 0xAC564B05L) * 0x818102004182A025L; 097 } 098 099 /** 100 * Gets an int with at most the specified amount of bits; don't confuse this with {@link #nextInt(int)}, which gets 101 * a number between 0 and its int argument, where this draws from a different (larger) range of random results. For 102 * example, {@code next(2)} can return any 2-bit int, 103 * which is limited to 0, 1, 2, or 3. Note that if you request 0 bits, this can give you any int (32 bits). 104 * @param bits the number of bits to get, from 1 to 32 105 * @return an int with at most the specified bits 106 */ 107 public final int next(final int bits) { 108 return (int)((state = (state << 29 | state >>> 35) * 0xAC564B05L) * 0x818102004182A025L) >>> (32 - bits); 109 } 110 public final int nextInt() { 111 return (int)((state = (state << 29 | state >>> 35) * 0xAC564B05L) * 0x818102004182A025L); 112 } 113 114 /** 115 * Returns a random non-negative integer between 0 (inclusive) and the given bound (exclusive), 116 * or 0 if the bound is 0. The bound can be negative, which will produce 0 or a negative result. 117 * <br> 118 * Credit goes to Daniel Lemire, http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ 119 * 120 * @param bound the outer bound (exclusive), can be negative or positive 121 * @return the found number 122 */ 123 public int nextInt(final int bound) { 124 return (int) ((bound * (nextLong() & 0xFFFFFFFFL)) >> 32); 125 } 126 /** 127 * Exclusive on bound (which must be positive), with an inner bound of 0. 128 * If bound is negative or 0 this always returns 0. 129 * <br> 130 * Credit for this method goes to <a href="https://oroboro.com/large-random-in-range/">Rafael Baptista's blog</a> 131 * for the original idea, and the JDK10 Math class' usage of Karatsuba multiplication for the current algorithm. 132 * This method is drastically faster than the previous implementation when the bound varies often (roughly 4x 133 * faster, possibly more). It also always gets exactly one random long, so by default it advances the state as much 134 * as {@link #nextLong()}. 135 * 136 * @param bound the outer exclusive bound; should be positive, otherwise this always returns 0L 137 * @return a random long between 0 (inclusive) and bound (exclusive) 138 */ 139 public long nextLong(long bound) { 140 long rand = nextLong(); 141 if (bound <= 0) return 0; 142 final long randLow = rand & 0xFFFFFFFFL; 143 final long boundLow = bound & 0xFFFFFFFFL; 144 rand >>>= 32; 145 bound >>>= 32; 146 final long a = rand * bound; 147 final long b = randLow * boundLow; 148 return (((b >>> 32) + (rand + randLow) * (bound + boundLow) - a - b) >>> 32) + a; 149 } 150 151 /** 152 * Sets the seed using a long, passing its argument to {@link #setState(long)}. That method just sets the public 153 * field {@link #state} to its argument currently, but it may do more to ensure cycle length in the future. 154 * @param seed the initial seed 155 */ 156 @Override 157 public void setSeed(long seed) { 158 setState(seed); 159 } 160 /** 161 * Mutates the array arr by switching the contents at pos1 and pos2. 162 * @param arr an array of T; must not be null 163 * @param pos1 an index into arr; must be at least 0 and no greater than arr.length 164 * @param pos2 an index into arr; must be at least 0 and no greater than arr.length 165 */ 166 protected static <T> void swap(T[] arr, int pos1, int pos2) { 167 final T tmp = arr[pos1]; 168 arr[pos1] = arr[pos2]; 169 arr[pos2] = tmp; 170 } 171 172 /** 173 * Shuffle an array using the Fisher-Yates algorithm and returns a shuffled copy, freshly-allocated, without 174 * modifying elements. 175 * <br> 176 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 177 * 178 * @param elements an array of T; will not be modified 179 * @return a shuffled copy of elements 180 */ 181 public <T> T[] shuffle(T[] elements) { 182 final int size = elements.length; 183 final T[] array = Arrays.copyOf(elements, size); 184 for (int i = size; i > 1; i--) { 185 swap(array, i - 1, nextInt(i)); 186 } 187 return array; 188 } 189 190 /** 191 * Shuffles an array in-place using the Fisher-Yates algorithm, affecting indices from 0 (inclusive) to length 192 * (exclusive). May be useful with libGDX Array instances, which can be shuffled with 193 * {@code random.shuffleInPlace(arr.items, arr.size)}. If you don't want the array modified, use 194 * {@link #shuffle(Object[])}. 195 * <br> 196 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 197 * 198 * @param elements an array of T; <b>will</b> be modified 199 * @return elements after shuffling it in-place 200 */ 201 public <T> T[] shuffleInPlace(T[] elements, int length) { 202 final int size = Math.min(elements.length, length); 203 for (int i = size; i > 1; i--) { 204 swap(elements, i - 1, nextInt(i)); 205 } 206 return elements; 207 } 208 209 /** 210 * Shuffles an array in-place using the Fisher-Yates algorithm. 211 * If you don't want the array modified, use {@link #shuffle(Object[])}. 212 * <br> 213 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 214 * 215 * @param elements an array of T; <b>will</b> be modified 216 * @return elements after shuffling it in-place 217 */ 218 public <T> T[] shuffleInPlace(T[] elements) { 219 final int size = elements.length; 220 for (int i = size; i > 1; i--) { 221 swap(elements, i - 1, nextInt(i)); 222 } 223 return elements; 224 } 225 /** 226 * Shuffles a Collection of T items in-place using the Fisher-Yates algorithm. 227 * This only shuffles List data structures. 228 * <br> 229 * <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Wikipedia has more on this algorithm</a>. 230 * 231 * @param elements a List of T; <b>will</b> be modified 232 * @param <T> can be any non-primitive type. 233 * @return elements after shuffling it in-place 234 */ 235 public <T> List<T> shuffleInPlace(List<T> elements) { 236 final int n = elements.size(); 237 for (int i = n; i > 1; i--) { 238 Collections.swap(elements, nextInt(i), i - 1); 239 } 240 return elements; 241 } 242 243 244 public BasicRandom64 copy() { 245 BasicRandom64 sr = new BasicRandom64(); 246 sr.state = state; 247 return sr; 248 } 249}