001package squidpony.squidmath; 002 003import squidpony.StringKit; 004 005import java.io.Serializable; 006 007/** 008 * A very fast generator on 64-bit systems that allows choosing any of 2 to the 63 odd-number streams. Each stream 009 * changes the set of possible outputs this can produce (amending the main flaw of ThrustAltRNG). This does well in 010 * PractRand quality tests, passing 32TB with one minor anomaly (it shares a lot of structure with ThrustAltRNG, 011 * which does very well in PractRand's testing as well as TestU01's BigCrush). It also outperforms just about everything 012 * in BumbleBench benchmarks, making it arguably the fastest random number generator algorithm here that 013 * can produce all long values (it just needs multiple generator objects to do so, all seeded differently). 014 * <br> 015 * Because this can produce multiple occurrences of any number in its sequence (except 0, which it should always produce 016 * once over its period of 2 to the 64), it can be considered as passing the "birthday problem" test; after running 017 * <a href="http://www.pcg-random.org/posts/birthday-test.html">this test provided by Melissa E. O'Neill</a> on Tangle, 018 * it correctly has 9 repeats compared to an expected 10, using the Skipping adapter to check one out of every 65536 019 * outputs for duplicates. A generator that failed that test would have 0 repeats or more than 20, so Tangle passes. 020 * ThrustAltRNG probably also passes (or its structure allows it to potentially do so), but LightRNG, LinnormRNG, 021 * MizuchiRNG, and even ThrustRNG will fail it by never repeating an output. Truncating the output bits of any of these 022 * generators will allow them to pass this test, at the cost of reducing the size of the output to an int instead of a 023 * long (less than ideal). Notably, an individual Tangle generator tends to be able to produce about 2/3 of all possible 024 * long outputs, with roughly 1/3 of all outputs not possible to produce and another 1/3 produced exactly once. These 025 * are approximations and will vary between instances. The test that gave the "roughly 2/3 possible" result gave similar 026 * results with 8-bit stateA and stateB and with 16-bit stateA and stateB, though it could change with the 64-bit states 027 * Tangle actually uses. 028 * <br> 029 * The name "Tangle" comes from how the two states of this generator are "tied up in each other," with synchronized 030 * periods of 2 to the 64 (stateA) and 2 to the 63 (stateB) that repeat as a whole every 2 to the 64 outputs. Contrary 031 * to the name, Tangle isn't slowed down at all by this, but the period length of the generator is less than the maximum 032 * possible (which OrbitRNG has, though that one is slowed down). 033 * <br> 034 * See also {@link OrbitRNG}, which gives up more speed but moves through all 2 to the 64 long values as streams over 035 * its full period, which is 2 to the 128 (with one stream) instead of the 2 to the 64 (with 2 to the 63 streams) here. 036 * There's also {@link SilkRNG}, which is like OrbitRNG but uses 32-bit math and is GWT-optimized. 037 * <br> 038 * This added a small extra step to the generation on March 4, 2020; the extra step reduces correlation between streams 039 * by further randomizing the output. Without this step (an additional right-xorshift by 6), nearby stateA or stateB 040 * values would often produce visibly similar sequences; with the step they are much less similar and more random. The 041 * additional step slows down TangleRNG by a very small amount. This edit also added {@link #getStream()}, which may 042 * have a use somewhere (maybe diagnosing possible problems?). 043 * <br> 044 * Created by Tommy Ettinger on 7/9/2018. 045 */ 046public final class TangleRNG implements RandomnessSource, SkippingRandomness, Serializable { 047 private static final long serialVersionUID = 5L; 048 /** 049 * Can be any long value. 050 */ 051 private long stateA; 052 053 /** 054 * Must be odd. 055 */ 056 private long stateB; 057 058 /** 059 * Creates a new generator seeded using Math.random. 060 */ 061 public TangleRNG() { 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 public TangleRNG(long seed) { 069 stateA = (seed = ((seed = (((seed * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ seed >>> 27) * 0xAEF17502108EF2D9L) ^ seed >>> 25; 070 stateB = ((seed = ((seed = (((seed * 0x632BE59BD9B4E019L) ^ 0x9E3779B97F4A7C15L) * 0xC6BC279692B5CC83L)) ^ seed >>> 27) * 0xAEF17502108EF2D9L) ^ seed >>> 25) | 1L; 071 } 072 073 public TangleRNG(final long seedA, final long seedB) { 074 stateA = seedA; 075 stateB = seedB | 1L; 076 } 077 078 /** 079 * Get the "A" part of the internal state as a long. 080 * 081 * @return the current internal "A" state of this object. 082 */ 083 public long getStateA() { 084 return stateA; 085 } 086 087 /** 088 * Set the "A" part of the internal state with a long. 089 * 090 * @param stateA a 64-bit long 091 */ 092 public void setStateA(long stateA) { 093 this.stateA = stateA; 094 } 095 096 /** 097 * Get the "B" part of the internal state as a long. 098 * 099 * @return the current internal "B" state of this object. 100 */ 101 public long getStateB() { 102 return stateB; 103 } 104 105 /** 106 * Set the "B" part of the internal state with a long; the least significant bit is ignored (will always be odd). 107 * 108 * @param stateB a 64-bit long 109 */ 110 public void setStateB(long stateB) { 111 this.stateB = stateB | 1L; 112 } 113 114 /** 115 * Using this method, any algorithm that might use the built-in Java Random 116 * can interface with this randomness source. 117 * 118 * @param bits the number of bits to be returned 119 * @return the integer containing the appropriate number of bits 120 */ 121 @Override 122 public final int next(final int bits) { 123 final long s = (stateA += 0xC6BC279692B5C323L); 124 final long z = (s ^ s >>> 31) * (stateB += 0x9E3779B97F4A7C16L); 125 return (int)(z ^ z >>> 26 ^ z >>> 6) >>> (32 - bits); 126 } 127 /** 128 * Using this method, any algorithm that needs to efficiently generate more 129 * than 32 bits of random data can interface with this randomness source. 130 * <p> 131 * Get a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive). 132 * 133 * @return a random long between Long.MIN_VALUE and Long.MAX_VALUE (both inclusive) 134 */ 135 @Override 136 public final long nextLong() { 137 final long s = (stateA += 0xC6BC279692B5C323L); 138 final long z = (s ^ s >>> 31) * (stateB += 0x9E3779B97F4A7C16L); 139 return z ^ z >>> 26 ^ z >>> 6; 140 } 141 142 /** 143 * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the 144 * copy, both will generate the same sequence of random numbers from the point copy() was called. This just need to 145 * copy the state so it isn't shared, usually, and produce a new value with the same exact state. 146 * 147 * @return a copy of this RandomnessSource 148 */ 149 @Override 150 public TangleRNG copy() { 151 return new TangleRNG(stateA, stateB); 152 } 153 @Override 154 public String toString() { 155 return "TangleRNG with stateA 0x" + StringKit.hex(stateA) + "L and stateB 0x" + StringKit.hex(stateB) + 'L'; 156 } 157 158 @Override 159 public boolean equals(Object o) { 160 if (this == o) return true; 161 if (o == null || getClass() != o.getClass()) return false; 162 163 TangleRNG tangleRNG = (TangleRNG) o; 164 165 return stateA == tangleRNG.stateA && stateB == tangleRNG.stateB; 166 } 167 168 @Override 169 public int hashCode() { 170 return (int) (31L * (stateA ^ (stateA >>> 32)) + (stateB ^ stateB >>> 32)); 171 } 172 173 /** 174 * Advances or rolls back the SkippingRandomness' state without actually generating each number. Skips forward 175 * or backward a number of steps specified by advance, where a step is equal to one call to {@link #nextLong()}, 176 * and returns the random number produced at that step. Negative numbers can be used to step backward, or 0 can be 177 * given to get the most-recently-generated long from {@link #nextLong()}. 178 * 179 * @param advance Number of future generations to skip over; can be negative to backtrack, 0 gets the most-recently-generated number 180 * @return the random long generated after skipping forward or backwards by {@code advance} numbers 181 */ 182 @Override 183 public long skip(long advance) { 184 final long s = (stateA += 0xC6BC279692B5C323L * advance); 185 final long z = (s ^ s >>> 31) * (stateB += 0x9E3779B97F4A7C16L * advance); 186 return z ^ z >>> 26 ^ z >>> 6; 187 } 188 /** 189 * Gets a long that identifies which stream of numbers this generator is producing; this stream identifier is always 190 * an odd long and won't change by generating numbers. It is determined at construction and will usually (not 191 * always) change if {@link #setStateA(long)} or {@link #setStateB(long)} are called. Each stream is a 192 * probably-unique sequence of 2 to the 64 longs, where approximately 1/3 of all possible longs will not ever occur 193 * (while others occur twice or more), but this set of results is different for every stream. There are 2 to the 63 194 * possible streams, one for every odd long. 195 * @return an odd long that identifies which stream this TangleRNG is generating from 196 */ 197 public long getStream() 198 { 199 return stateB - (stateA * 0x1743CE5C6E1B848BL) * 0x9E3779B97F4A7C16L; 200 } 201 202}