001package squidpony.squidmath; 002 003import squidpony.StringKit; 004 005import java.io.Serializable; 006 007/** 008 * An IRNG implementation that allows the extra functionality of a StatefulRandomness and a SkippingRandomness, as well 009 * as allowing reverse-lookup of the state that produced a long using the static {@link #inverseNextLong(long)} method, 010 * and distance checks between two generated numbers with the static {@link #distance(long, long)} method. A task this 011 * might be useful for could be simple obfuscation that is hard to undo unless you know the starting state, like this: 012 * <ol> 013 * <li>take a sequence of numbers or characters and a MoonwalkRNG with a given starting state,</li> 014 * <li>modify each item in the sequence with a random but reversible change such as a bitwise XOR 015 * with a number produced by the MoonwalkRNG (such as by {@link #nextInt()}),</li> 016 * <li>on a later run, take the modified sequence and a MoonwalkRNG with the same starting state (but no direct 017 * access to the starting sequence), and skip ahead by the length of the sequence with {@link #skip(long)},</li> 018 * <li>starting at the end of the sequence, apply the reverse change to the items with numbers generated 019 * <b>backwards</b> by MoonwalkRNG with {@link #previousInt()} (such as a XOR if the number was originally modified 020 * with a XOR or an addition if it was originally modified with a subtraction),</li> 021 * <li>when the full sequence has been reversed, you now have the original sequence again.</li> 022 * </ol> 023 * This is also possible with determine() methods in various RandomnessSource implementations, but those require some 024 * extra work to allow them to use sequential inputs instead of inputs that have a large difference between generations. 025 * <br> 026 * Internally, this is like {@link StatefulRNG} if it always used {@link LightRNG} and allowed access to LightRNG's 027 * skip() method as well as the reverse lookup and distance methods that aren't in LightRNG but are allowed by it. 028 * <br> 029 * The name comes from the ability of this generator to easily go in reverse, like the moonwalk dance move, including 030 * {@link #previousLong()} and {@link #skip(long)} for advancing backwards, but also {@link #inverseNextLong(long)} to 031 * go from output back to state. 032 * <br> 033 * Created by Tommy Ettinger on 4/14/2018. 034 */ 035public class MoonwalkRNG extends AbstractRNG implements IStatefulRNG, SkippingRandomness, Serializable { 036 private static final long serialVersionUID = 1L; 037 038 private long state; 039 /** 040 * Default constructor; uses a random seed. 041 */ 042 public MoonwalkRNG() { 043 this((long) ((Math.random() - 0.5) * 0x10000000000000L) 044 ^ (long) (((Math.random() - 0.5) * 2.0) * 0x8000000000000000L)); 045 } 046 047 /** 048 * Constructs a MoonwalkRNG with the given seed as-is; any seed can be given. 049 * @param seed any long 050 */ 051 public MoonwalkRNG(long seed) { 052 state = seed; 053 } 054 055 /** 056 * String-seeded constructor; uses a platform-independent hash of the String (it does not use String.hashCode) as a 057 * seed for this RNG. 058 * @param seedString any CharSequence, such as a String or StringBuilder; if null this will use the seed 0 059 */ 060 public MoonwalkRNG(CharSequence seedString) { 061 this(CrossHash.hash64(seedString)); 062 } 063 064 /** 065 * Get up to 32 bits (inclusive) of random output; the int this produces 066 * will not require more than {@code bits} bits to represent. 067 * 068 * @param bits an int between 1 and 32, both inclusive 069 * @return a random number that fits in the specified number of bits 070 */ 071 @Override 072 public int next(int bits) { 073 long z = state += 0x9E3779B97F4A7C15L; 074 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 075 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 076 return (int)(z ^ (z >>> 31)) >>> (32 - bits); 077 } 078 079 /** 080 * Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive). 081 * 082 * @return a 32-bit random int. 083 */ 084 @Override 085 public int nextInt() { 086 long z = state += 0x9E3779B97F4A7C15L; 087 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 088 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 089 return (int)(z ^ (z >>> 31)); 090 } 091 092 /** 093 * Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive). 094 * 095 * @return a 64-bit random long. 096 */ 097 @Override 098 public long nextLong() { 099 long z = state += 0x9E3779B97F4A7C15L; 100 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 101 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 102 return z ^ (z >>> 31); 103 } 104 /** 105 * Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive), but advances the state 106 * "backwards," such that calling {@link #nextInt()} alternating with this method will return the same pair of 107 * numbers for as long as you keep alternating those two calls. This can be useful with {@link #skip(long)} when it 108 * advances ahead by a large amount and you want to step backward to reverse another set of forward-advancing number 109 * generations that had been done by other code. 110 * 111 * @return a 32-bit random int. 112 */ 113 public int previousInt() { 114 long z = state -= 0x9E3779B97F4A7C15L; 115 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 116 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 117 return (int)(z ^ (z >>> 31)); 118 } 119 120 /** 121 * Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive), but advances the state 122 * "backwards," such that calling {@link #nextLong()} alternating with this method will return the same pair of 123 * numbers for as long as you keep alternating those two calls. This can be useful with {@link #skip(long)} when it 124 * advances ahead by a large amount and you want to step backward to reverse another set of forward-advancing number 125 * generations that had been done by other code. 126 * 127 * @return a 64-bit random long. 128 */ 129 public long previousLong() { 130 long z = state -= 0x9E3779B97F4A7C15L; 131 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 132 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 133 return (z ^ (z >>> 31)); 134 } 135 136 137 /** 138 * Get a random bit of state, interpreted as true or false with approximately equal likelihood. 139 * <br> 140 * This implementation uses a sign check and is able to avoid some calculations needed to get a full int or long. 141 * 142 * @return a random boolean. 143 */ 144 @Override 145 public boolean nextBoolean() { 146 long z = state += 0x9E3779B97F4A7C15L; 147 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 148 return ((z ^ (z >>> 27)) * 0x94D049BB133111EBL) < 0; 149 } 150 151 /** 152 * Gets a random double between 0.0 inclusive and 1.0 exclusive. 153 * This returns a maximum of 0.9999999999999999 because that is the largest double value that is less than 1.0 . 154 * 155 * @return a double between 0.0 (inclusive) and 0.9999999999999999 (inclusive) 156 */ 157 @Override 158 public double nextDouble() { 159 long z = state += 0x9E3779B97F4A7C15L; 160 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 161 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 162 return ((z ^ (z >>> 31)) & 0x1fffffffffffffL) * 0x1p-53; 163 } 164 165 /** 166 * Gets a random float between 0.0f inclusive and 1.0f exclusive. 167 * This returns a maximum of 0.99999994 because that is the largest float value that is less than 1.0f . 168 * 169 * @return a float between 0f (inclusive) and 0.99999994f (inclusive) 170 */ 171 @Override 172 public float nextFloat() { 173 long z = state += 0x9E3779B97F4A7C15L; 174 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 175 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 176 return ((z ^ (z >>> 31)) & 0xffffffL) * 0x1p-24f; 177 } 178 179 /** 180 * Creates a copy of this MoonwalkRNG; it will generate the same random numbers, given the same calls in order, as 181 * this MoonwalkRNG at the point copy() is called. The copy will not share references with this MoonwalkRNG. 182 * @return a copy of this IRNG 183 */ 184 @Override 185 public MoonwalkRNG copy() { 186 return new MoonwalkRNG(state); 187 } 188 189 /** 190 * Gets a view of this IRNG in a way that implements {@link Serializable}, which may simply be this IRNG if it 191 * implements Serializable as well as IRNG. 192 * <br> 193 * For implementors: It is suggested to return an {@link RNG} initialized by calling 194 * {@link RNG#RNG(long)} with {@link #nextLong()} if you are unable to save the current state of this IRNG and the 195 * caller still needs something saved. This won't preserve the current state or the choice of IRNG implementation, 196 * however, so it is simply a last resort in case you don't want to throw an exception. 197 * 198 * @return a {@link Serializable} view of this IRNG or a similar one; may be {@code this} 199 */ 200 @Override 201 public Serializable toSerializable() { 202 return this; 203 } 204 205 /** 206 * Advances or rolls back the SkippingRandomness' state without actually generating each number. Skips forward 207 * or backward a number of steps specified by advance, where a step is equal to one call to {@link #nextLong()}, 208 * and returns the random number produced at that step. Negative numbers can be used to step backward, or 0 can be 209 * given to get the most-recently-generated long from {@link #nextLong()}. 210 * 211 * @param advance Number of future generations to skip over; can be negative to backtrack, 0 gets the most-recently-generated number 212 * @return the random long generated after skipping forward or backwards by {@code advance} numbers 213 */ 214 @Override 215 public long skip(long advance) { 216 long z = (state += 0x9E3779B97F4A7C15L * advance); 217 z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; 218 z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; 219 return z ^ (z >>> 31); 220 } 221 222 /** 223 * Get the current internal state of the StatefulRandomness as a long. 224 * 225 * @return the current internal state of this object as a long 226 */ 227 @Override 228 public long getState() { 229 return state; 230 } 231 232 /** 233 * Set the current internal state of this StatefulRandomness with a long; all longs are allowed. 234 * 235 * @param state a 64-bit long; this can be any long, even 0 236 */ 237 @Override 238 public void setState(long state) { 239 this.state = state; 240 } 241 242 @Override 243 public String toString() { 244 return "MoonwalkRNG with state 0x" + StringKit.hex(state) + 'L'; 245 } 246 247 @Override 248 public boolean equals(Object o) { 249 if (this == o) return true; 250 if (o == null || getClass() != o.getClass()) return false; 251 252 MoonwalkRNG moonwalkRNG = (MoonwalkRNG) o; 253 254 return state == moonwalkRNG.state; 255 } 256 257 @Override 258 public int hashCode() { 259 return (int) (state ^ (state >>> 32)); 260 } 261 262 263 /** 264 * Given the output of a call to {@link #nextLong()} as {@code out}, this finds the state of the MoonwalkRNG that 265 * produce that output. If you set the state of a MoonwalkRNG with {@link #setState(long)} to the result of this 266 * method and then call {@link #nextLong()} on it, you should get back {@code out}. 267 * <br> 268 * This isn't as fast as {@link #nextLong()}, but both run in constant time. Some random number generators take more 269 * than constant time to reverse, so one was chosen for this class that would still be efficient ({@link LightRNG}). 270 * <br> 271 * This will not necessarily work if out was produced by a generator other than a MoonwalkRNG, or if it was produced 272 * with the bounded {@link #nextLong(long)} method by any generator. 273 * @param out a long as produced by {@link #nextLong()}, without changes 274 * @return the state of the RNG that will produce the given long 275 */ 276 public static long inverseNextLong(long out) 277 { 278 out ^= out >>> 31; 279 out ^= out >>> 62; 280 out *= 0x319642B2D24D8EC3L; 281 out ^= out >>> 27; 282 out ^= out >>> 54; 283 out *= 0x96DE1B173F119089L; 284 out ^= out >>> 30; 285 return (out ^ out >>> 60) - 0x9E3779B97F4A7C15L; 286 //0x96DE1B173F119089L 0x319642B2D24D8EC3L 0xF1DE83E19937733DL 287 } 288 289 /** 290 * Returns the number of steps (where a step is equal to one call to most random number methods in this class) 291 * needed to go from receiving out1 from a MoonwalkRNG's {@link #nextLong()} method to receiving out2 from another 292 * call. This number can be used with {@link #skip(long)} to move a MoonwalkRNG forward or backward by the desired 293 * distance. 294 * @param out1 a long as produced by {@link #nextLong()}, without changes 295 * @param out2 a long as produced by {@link #nextLong()}, without changes 296 * @return the number of calls to {@link #nextLong()} that would be required to go from producing out1 to producing 297 * out2; can be positive or negative, and can be passed to {@link #skip(long)} 298 */ 299 public static long distance(final long out1, final long out2) 300 { 301 return (inverseNextLong(out2) - inverseNextLong(out1)) * 0xF1DE83E19937733DL; 302 } 303}