001/* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) 002 003To the extent possible under law, the author has dedicated all copyright 004and related and neighboring rights to this software to the public domain 005worldwide. This software is distributed without any warranty. 006 007See <http://creativecommons.org/publicdomain/zero/1.0/>. */ 008package squidpony.squidmath; 009 010import squidpony.StringKit; 011 012import java.io.Serializable; 013 014/** 015 * A port of Blackman and Vigna's xoroshiro128+ generator; should be very fast and produce medium-quality output. 016 * Testing shows it is within 5% the speed of LightRNG, sometimes faster and sometimes slower, and has a larger period. 017 * It's called XoRo because it involves Xor as well as Rotate operations on the 128-bit pseudo-random state. Note that 018 * xoroshiro128+ fails some statistical quality tests systematically, and fails others often; if this could be a concern 019 * for you, {@link DiverRNG}, which is the default for {@link RNG}, will be faster and won't fail tests, and 020 * though its period is shorter, it would still take years to exhaust on one core generating only random numbers. 021 * <br> 022 * {@link LightRNG} is also very fast, but relative to XoRoRNG it has a significantly shorter period (the amount of 023 * random numbers it will go through before repeating), at {@code pow(2, 64)} as opposed to XoRoRNG's 024 * {@code pow(2, 128) - 1}, but LightRNG also allows the current RNG state to be retrieved and altered with 025 * {@code getState()} and {@code setState()}. For most cases, you should decide between DiverRNG, LightRNG, XoRoRNG, 026 * and other RandomnessSource implementations based on your needs for period length and state manipulation (DiverRNG 027 * is also used internally by almost all StatefulRNG objects). You might want significantly less predictable random 028 * results, which {@link IsaacRNG} can provide, along with a large period. You may want a very long period of random 029 * numbers, which would suggest {@link LongPeriodRNG} as a good choice or {@link MersenneTwister} as a potential 030 * alternative. You may want better performance on 32-bit machines or on GWT, where {@link Starfish32RNG} is currently 031 * the best choice most of the time, and {@link Lathe32RNG} can be faster but has slightly worse quality (both of these 032 * generators use a 32-bit variant on the xoroshiro algorithm but change the output scrambler). These all can generate 033 * pseudo-random numbers in a handful of nanoseconds (with the key exception of 64-bit generators being used on GWT, 034 * where they may take more than 100 nanoseconds per number), so unless you need a LOT of random numbers in a hurry, 035 * they'll probably all be fine on performance. You may want to decide on the special features of a generator, indicated 036 * by implementing {@link StatefulRandomness} if their state can be read and written to, and/or 037 * {@link SkippingRandomness} if sections in the generator's sequence can be skipped in long forward or backward leaps. 038 * <br> 039 * <a href="http://xoroshiro.di.unimi.it/xoroshiro128plus.c">Original version here.</a> 040 * <br> 041 * Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) 042 * 043 * @author Sebastiano Vigna 044 * @author David Blackman 045 * @author Tommy Ettinger (if there's a flaw, use SquidLib's issues and don't bother Vigna or Blackman, it's probably a mistake in SquidLib's implementation) 046 */ 047public final class XoRoRNG implements RandomnessSource, Serializable { 048 049 private static final long DOUBLE_MASK = (1L << 53) - 1; 050 private static final double NORM_53 = 1. / (1L << 53); 051 private static final long FLOAT_MASK = (1L << 24) - 1; 052 private static final double NORM_24 = 1. / (1L << 24); 053 054 private static final long serialVersionUID = 1018744536171610262L; 055 056 private long state0, state1; 057 058 /** 059 * Creates a new generator seeded using four calls to Math.random(). 060 */ 061 public XoRoRNG() { 062 this((long) ((Math.random() - 0.5) * 0x10000000000000L) 063 ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L), 064 (long) ((Math.random() - 0.5) * 0x10000000000000L) 065 ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L)); 066 } 067 /** 068 * Constructs this XoRoRNG by dispersing the bits of seed using {@link #setSeed(long)} across the two parts of state 069 * this has. 070 * @param seed a long that won't be used exactly, but will affect both components of state 071 */ 072 public XoRoRNG(final long seed) { 073 setSeed(seed); 074 } 075 /** 076 * Constructs this XoRoRNG by calling {@link #setSeed(long, long)} on the arguments as given; see that method for 077 * the specific details (stateA and stateB are kept as-is unless they are both 0). 078 * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0 079 * @param stateB the number to use as the second part of the state 080 */ 081 public XoRoRNG(final long stateA, final long stateB) { 082 setSeed(stateA, stateB); 083 } 084 085 @Override 086 public final int next(int bits) { 087 final long s0 = state0; 088 long s1 = state1; 089 final int result = (int)(s0 + s1) >>> (32 - bits); 090 s1 ^= s0; 091 state0 = (s0 << 55 | s0 >>> 9) ^ s1 ^ (s1 << 14); // a, b 092 state1 = (s1 << 36 | s1 >>> 28); // c 093 return result; 094 } 095 096 @Override 097 public final long nextLong() { 098 final long s0 = state0; 099 long s1 = state1; 100 final long result = s0 + s1; 101 102 s1 ^= s0; 103 state0 = (s0 << 55 | s0 >>> 9) ^ s1 ^ (s1 << 14); // a, b 104 state1 = (s1 << 36 | s1 >>> 28); // c 105 /* 106 state0 = Long.rotateLeft(s0, 55) ^ s1 ^ (s1 << 14); // a, b 107 state1 = Long.rotateLeft(s1, 36); // c 108 */ 109 return result; 110 } 111 112 /** 113 * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the 114 * copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to 115 * copy the state so it isn't shared, usually, and produce a new value with the same exact state. 116 * 117 * @return a copy of this RandomnessSource 118 */ 119 @Override 120 public XoRoRNG copy() { 121 XoRoRNG next = new XoRoRNG(state0); 122 next.state0 = state0; 123 next.state1 = state1; 124 return next; 125 } 126 127 128 /** 129 * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer. 130 * @return any int, all 32 bits are random 131 */ 132 public int nextInt() { 133 return (int)nextLong(); 134 } 135 136 /** 137 * Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive 138 * result. 139 * @param bound the outer exclusive bound; may be positive or negative 140 * @return a random int between 0 (inclusive) and bound (exclusive) 141 */ 142 public int nextInt(final int bound) { 143 return (int) ((bound * (nextLong() >>> 33)) >> 31); 144 } 145 /** 146 * Inclusive lower, exclusive upper. 147 * @param inner the inner bound, inclusive, can be positive or negative 148 * @param outer the outer bound, exclusive, should be positive, should usually be greater than inner 149 * @return a random int that may be equal to inner and will otherwise be between inner and outer 150 */ 151 public int nextInt(final int inner, final int outer) { 152 return inner + nextInt(outer - inner); 153 } 154 155 /** 156 * Exclusive on the outer bound; the inner bound is 0. The bound may be negative, which will produce a non-positive 157 * result. 158 * @param bound the outer exclusive bound; may be positive or negative 159 * @return a random long between 0 (inclusive) and bound (exclusive) 160 */ 161 public long nextLong(long bound) { 162 long rand = nextLong(); 163 final long randLow = rand & 0xFFFFFFFFL; 164 final long boundLow = bound & 0xFFFFFFFFL; 165 rand >>>= 32; 166 bound >>= 32; 167 final long t = rand * boundLow + (randLow * boundLow >>> 32); 168 return rand * bound + (t >> 32) + (randLow * bound + (t & 0xFFFFFFFFL) >> 32); 169 } 170 /** 171 * Inclusive inner, exclusive outer; both inner and outer can be positive or negative. 172 * @param inner the inner bound, inclusive, can be positive or negative 173 * @param outer the outer bound, exclusive, can be positive or negative and may be greater than or less than inner 174 * @return a random long that may be equal to inner and will otherwise be between inner and outer 175 */ 176 public long nextLong(final long inner, final long outer) { 177 return inner + nextLong(outer - inner); 178 } 179 180 public double nextDouble() { 181 return (nextLong() & DOUBLE_MASK) * NORM_53; 182 } 183 184 public float nextFloat() { 185 return (float) ((nextLong() & FLOAT_MASK) * NORM_24); 186 } 187 188 public boolean nextBoolean() { 189 return nextLong() < 0L; 190 } 191 192 public void nextBytes(final byte[] bytes) { 193 int i = bytes.length, n; 194 while (i != 0) { 195 n = Math.min(i, 8); 196 for (long bits = nextLong(); n-- != 0; bits >>>= 8) { 197 bytes[--i] = (byte) bits; 198 } 199 } 200 } 201 202 /** 203 * Sets the seed of this generator using one long, running that through LightRNG's algorithm twice to get the state. 204 * @param seed the number to use as the seed 205 */ 206 public void setSeed(final long seed) { 207 208 long state = seed + 0x9E3779B97F4A7C15L, 209 z = state; 210 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 211 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 212 state0 = z ^ (z >>> 31); 213 state += 0x9E3779B97F4A7C15L; 214 z = state; 215 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 216 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 217 state1 = z ^ (z >>> 31); 218 } 219 220 /** 221 * Sets the seed of this generator using two longs, using them without changes unless both are 0 (then it makes the 222 * state variable corresponding to stateA 1 instead). 223 * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0 224 * @param stateB the number to use as the second part of the state 225 */ 226 public void setSeed(final long stateA, final long stateB) { 227 228 state0 = stateA; 229 state1 = stateB; 230 if((stateA | stateB) == 0L) 231 state0 = 1L; 232 } 233 234 /** 235 * Gets the first component of this generator's two-part state, as a long. This can be 0 on its own, but will never 236 * be 0 at the same time as the other component of state, {@link #getStateB()}. You can set the state with two exact 237 * values using {@link #setSeed(long, long)}, but the alternative overload {@link #setSeed(long)} won't use the 238 * state without changing it (it needs to cover 128 bits with a 64-bit value). 239 * @return the first component of this generator's state 240 */ 241 public long getStateA() 242 { 243 return state0; 244 } 245 /** 246 * Gets the second component of this generator's two-part state, as a long. This can be 0 on its own, but will never 247 * be 0 at the same time as the other component of state, {@link #getStateA()}. You can set the state with two exact 248 * values using {@link #setSeed(long, long)}, but the alternative overload {@link #setSeed(long)} won't use the 249 * state without changing it (it needs to cover 128 bits with a 64-bit value). 250 * @return the second component of this generator's state 251 */ 252 public long getStateB() 253 { 254 return state1; 255 } 256 257 @Override 258 public String toString() { 259 return "XoRoRNG with stateA 0x" + StringKit.hex(state0) + "L and stateB 0x" + StringKit.hex(state1) + 'L'; 260 } 261 262 @Override 263 public boolean equals(Object o) { 264 if (this == o) return true; 265 if (o == null || getClass() != o.getClass()) return false; 266 267 XoRoRNG xoRoRNG = (XoRoRNG) o; 268 269 if (state0 != xoRoRNG.state0) return false; 270 return state1 == xoRoRNG.state1; 271 } 272 273 @Override 274 public int hashCode() { 275 return (int) (31L * (state0 ^ (state0 >>> 32)) + (state1 ^ (state1 >>> 32))); 276 } 277}