001package squidpony.squidmath; 002 003import squidpony.StringKit; 004 005import java.io.Serializable; 006 007/** 008 * A modification of Blackman and Vigna's xoroshiro128+ generator using two 32-bit ints of state instead of two 64-bit 009 * longs and also incorporating a large-increment counter (Weyl sequence) that is added to the rotated xoroshiro output; 010 * this is tied with {@link Lathe32RNG} for the fastest generator on GWT I have found that also passes the full 32TB 011 * battery of PractRand's statistical tests. Starfish32RNG has 2D equidistribution while this only has 1D; this means 012 * Starfish32RNG (and GWTRNG) can produce all pairs of ints or all longs (except for one) with equal likelihood, while 013 * Oriole32RNG (and Lathe32RNG) produce some pairs more often than others. In statistical testing, xoroshiro always 014 * fails some binary matrix rank tests, but smaller-state versions fail other tests as well. The changes Oriole makes 015 * apply only to the output of xoroshiro, not its well-tested state transition for the "xoroshiro state" part of this 016 * generator, and these changes eliminate all statistical failures on 32TB of tested data, avoiding the failures the 017 * small-state variant of xoroshiro suffers on BinaryRank, BCFN, DC6, and FPF. It avoids multiplication, like xoroshiro 018 * and much of the xorshift family of generators, and any arithmetic it performs is safe for GWT. Oriole takes advantage 019 * of xoroshiro's flaws being mostly confined to its output's lower bits by rotating the output of xoroshiro (the weaker 020 * 32-bit-state version) and adding a "Weyl sequence," essentially a large-increment counter that overflows and wraps 021 * frequently, to the output. Although the upper bits of xoroshiro are not free of artifacts either, they are harder to 022 * find issues with (see 023 * <a href="http://www.pcg-random.org/posts/xoroshiro-fails-truncated.html">this article by PCG-Random's author</a> for 024 * more detail). It is unclear if the changes made here would improve the larger-state version, but they probably would 025 * help to some extent with at least the binary rank failures. The period is also improved by incorporating the Weyl 026 * sequence, up to 0xFFFFFFFFFFFFFFFF00000000 . 027 * <br> 028 * The name comes from the insectivorous orange songbird called an oriole, which as I have found from the one that 029 * visits my backyard, reacts quickly and is always looking for bugs to remove. It also sounds like "xoro." 030 * <br> 031 * <a href="http://xoroshiro.di.unimi.it/xoroshiro128plus.c">Original version here for xorshiro128+</a>; this version 032 * uses <a href="https://groups.google.com/d/msg/prng/Ll-KDIbpO8k/bfHK4FlUCwAJ">different constants</a> by the same 033 * author, Sebastiano Vigna. 034 * <br> 035 * Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org) 036 * Ported and modified in 2018 by Tommy Ettinger 037 * @author Sebastiano Vigna 038 * @author David Blackman 039 * @author Tommy Ettinger (if there's a flaw, use SquidLib's or Sarong's issues and don't bother Vigna or Blackman, it's probably a mistake in SquidLib's implementation) 040 * @see Lathe32RNG A related generator that implements StatefulRandomness and has very similar speed 041 */ 042public final class Oriole32RNG implements RandomnessSource, Serializable { 043 044 private static final long serialVersionUID = 2L; 045 046 private int stateA, stateB, stateC; 047 048 /** 049 * Creates a new generator seeded using three calls to Math.random(). 050 */ 051 public Oriole32RNG() { 052 setState((int)((Math.random() * 2.0 - 1.0) * 0x80000000), (int)((Math.random() * 2.0 - 1.0) * 0x80000000), 053 (int)((Math.random() * 2.0 - 1.0) * 0x80000000)); 054 } 055 /** 056 * Constructs this Oriole32RNG by dispersing the bits of seed using {@link #setSeed(int)} across the two parts of state 057 * this has. 058 * @param seed a long that won't be used exactly, but will affect both components of state 059 */ 060 public Oriole32RNG(final int seed) { 061 setSeed(seed); 062 } 063 /** 064 * Constructs this Oriole32RNG by calling {@link #setState(int, int, int)} on stateA and stateB as given but 065 * producing stateC via {@code stateA ^ stateB}; see that method for the specific details (stateA and stateB are 066 * kept as-is unless they are both 0). 067 * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0 068 * @param stateB the number to use as the second part of the state 069 */ 070 public Oriole32RNG(final int stateA, final int stateB) { 071 setState(stateA, stateB, stateA ^ stateB); 072 } 073 074 /** 075 * Constructs this Oriole32RNG by calling {@link #setState(int, int, int)} on the arguments as given; see that 076 * method for the specific details (stateA and stateB are kept as-is unless they are both 0). 077 * @param stateA the number to use as the first part of the state; this will be 1 instead if both seeds are 0 078 * @param stateB the number to use as the second part of the state 079 * @param stateC the number to use as the counter part of the state (third part) 080 */ 081 public Oriole32RNG(final int stateA, final int stateB, final int stateC) { 082 setState(stateA, stateB, stateC); 083 } 084 085 @Override 086 public final int next(int bits) { 087 final int s0 = stateA; 088 int s1 = stateB; 089 final int result = s0 + s1; 090 s1 ^= s0; 091 stateA = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b 092 stateB = (s1 << 28 | s1 >>> 4); // c 093 return (result << 29 | result >>> 3) + (stateC += 0x632BE5AB) >>> (32 - bits); 094 } 095 096 /** 097 * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer. 098 * @return any int, all 32 bits are random 099 */ 100 public final int nextInt() { 101 final int s0 = stateA; 102 int s1 = stateB; 103 final int result = s0 + s1; 104 s1 ^= s0; 105 stateA = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b 106 stateB = (s1 << 28 | s1 >>> 4); // c 107 return (result << 29 | result >>> 3) + (stateC += 0x632BE5AB); 108 } 109 110 @Override 111 public final long nextLong() { 112 final int s0 = stateA; 113 int s1 = stateB; 114 final int high = s0 + s1; 115 s1 ^= s0; 116 final int s00 = (s0 << 13 | s0 >>> 19) ^ s1 ^ (s1 << 5); // a, b 117 s1 = (s1 << 28 | s1 >>> 4); // c 118 final int low = s00 + s1; 119 s1 ^= s00; 120 stateA = (s00 << 13 | s00 >>> 19) ^ s1 ^ (s1 << 5); // a, b 121 stateB = (s1 << 28 | s1 >>> 4); // c 122 return ((high << 29 | high >>> 3) + (stateC + 0x632BE5ABL)) << 32 | ((low << 29 | low >>> 3) + (stateC += 0xC657CB56) & 0xFFFFFFFFL); 123 } 124 125 /** 126 * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the 127 * copy, both will generate the same sequence of random numbers from the point copy() was called. This just needs to 128 * copy the state so it isn't shared, usually, and produce a new value with the same exact state. 129 * 130 * @return a copy of this RandomnessSource 131 */ 132 @Override 133 public Oriole32RNG copy() { 134 return new Oriole32RNG(stateA, stateB, stateC); 135 } 136 137 /** 138 * Sets the state of this generator using one int, running it through Zog32RNG's algorithm three times to get 139 * three ints. 140 * @param seed the int to use to assign this generator's state 141 */ 142 public void setSeed(final int seed) { 143 int z = seed + 0xC74EAD55, a = seed ^ z; 144 a ^= a >>> 14; 145 z = (z ^ z >>> 10) * 0xA5CB3; 146 a ^= a >>> 15; 147 stateA = (z ^ z >>> 20) + (a ^= a << 13); 148 z = seed + 0x8E9D5AAA; 149 a ^= a >>> 14; 150 z = (z ^ z >>> 10) * 0xA5CB3; 151 a ^= a >>> 15; 152 stateB = (z ^ z >>> 20) + (a ^ a << 13); 153 if((stateA | stateB) == 0) 154 stateA = 1; 155 z = seed - 0xC74EAD55; 156 a ^= a >>> 14; 157 z = (z ^ z >>> 10) * 0xA5CB3; 158 a ^= a >>> 15; 159 stateC = (z ^ z >>> 20) + (a ^ a << 13); 160 } 161 162 public int getStateA() 163 { 164 return stateA; 165 } 166 public void setStateA(int stateA) 167 { 168 this.stateA = (stateA | stateB) == 0 ? 1 : stateA; 169 } 170 public int getStateB() 171 { 172 return stateB; 173 } 174 public void setStateB(int stateB) 175 { 176 this.stateB = stateB; 177 if((stateB | stateA) == 0) stateA = 1; 178 } 179 public int getStateC() 180 { 181 return stateC; 182 } 183 public void setStateC(int stateC) 184 { 185 this.stateC = stateC; 186 } 187 188 /** 189 * Sets the current internal state of this Oriole32RNG with three ints, where stateA and stateB can each be any int 190 * unless they are both 0, and stateC can be any int without restrictions. 191 * @param stateA any int except 0 (0 will be treated as 1 instead) 192 * @param stateB any int 193 */ 194 public void setState(int stateA, int stateB, int stateC) 195 { 196 this.stateA = (stateA | stateB) == 0 ? 1 : stateA; 197 this.stateB = stateB; 198 this.stateC = stateC; 199 } 200 @Override 201 public String toString() { 202 return "Oriole32RNG with stateA 0x" + StringKit.hex(stateA) + ", stateB 0x" + StringKit.hex(stateB) + ", and stateC 0x" + StringKit.hex(stateC); 203 } 204 205 @Override 206 public boolean equals(Object o) { 207 if (this == o) return true; 208 if (o == null || getClass() != o.getClass()) return false; 209 210 Oriole32RNG oriole32RNG = (Oriole32RNG) o; 211 212 return stateA == oriole32RNG.stateA && stateB == oriole32RNG.stateB && stateC == oriole32RNG.stateC; 213 } 214 215 @Override 216 public int hashCode() { 217 return 31 * stateA + stateB; 218 } 219} 220