001package squidpony.squidmath; 002 003import squidpony.StringKit; 004 005/** 006 * One of Mark Overton's subcycle generators from <a href="http://www.drdobbs.com/tools/229625477">this article</a>, 007 * specifically a cmr^cmr with two 64-bit states. It is extremely fast, faster than {@link LinnormRNG} and 008 * {@link TangleRNG}, but its period is unknown. The period is at the very least 2 to the 38, since each of its 009 * sub-generators has been checked up to that period length without running out of period, and the total period of a 010 * Mover64RNG should be greater than 2 to the 64 with a very high likelihood. The total period is also very unlikely to 011 * be a power of two or even a number close to a power of two; it could be odd or even. The guarantees of Linnorm and 012 * Tangle that they are certain to have a period of 2 to the 64 may be worthwhile reasons to use them; they also will be 013 * faster when setting the state often. LightRNG is a SkippingRandomness and a StatefulRandomness, but this is neither, 014 * so you may want to prefer LightRNG for that reason. This generator is not equidistributed, so it can return some long 015 * values more often than others and some not at all; you may want to use a generator with guarantees on distribution if 016 * you don't want to see some returned values (or pairs of values) more often than others. {@link Starfish32RNG} is 017 * 2-dimensionally equidistributed for ints, so it returns all pairs of ints with equal likelihood, and it may be a good 018 * RandomnessSource to use if distribution matters (though you should prefer {@link GWTRNG}, which is implemented using 019 * Starfish32RNG, because it is specialized to use a 32-bit generator). 020 * <br> 021 * This seems to do well in PractRand testing, passing a full 32TB with two ("unusual") anomalies, but this is not one 022 * of the exact generators Overton tested. "Chaotic" generators like this one tend to score well in PractRand, but it 023 * isn't clear if they will fail other tests (in particular, they probably can't generate all possible long values, and 024 * maybe can't generate some ints). This generator is not equidistributed. 025 * <br> 026 * The generator has two similar parts, each updated without needing to read from the other part. Each is a 64-bit CMR 027 * generator, which multiplies a state by a constant, rotates by another constant, and stores that as the next state. 028 * The multiplier constants used here were chosen arbitrarily, since almost all odd-number multipliers produce a period 029 * for a 64-bit CMR generator that is too long to iterate through and compare. One multiplier is close to the LCG 030 * multiplier used in PractRand (0x41C64E6B); the other is very close to the golden ratio times 2 to the 32 031 * (0x9E3779B9). Better multipliers are almost guaranteed to exist, but finding them would be a challenge. The rotation 032 * constants, 28 and 37, were chosen so they were sufficiently different and so the sum of their (left or right) 033 * rotation amounts is close to 64, which seems to help quality. Oddly, substituting an addition for one of the two 034 * multiplications slows this generator down reliably, and does nothing to help quality. Even though addition should be 035 * faster, the two near-identical operations performed on two states may be able to be compiled into vector operations 036 * if the compiler is clever enough, but an addition on one state and a multiplication on the other would not make sense 037 * to see SIMD optimization. 038 * <br> 039 * This is a RandomnessSource but not a StatefulRandomness because it needs to take care and avoid seeds that would put 040 * it in a short-period subcycle. It uses two generators with different cycle lengths, and skips at most 65536 times 041 * into each generator's cycle independently when seeding. It uses constants to store 128 known midpoints for each 042 * generator, which ensures it calculates an advance for each generator at most 511 times. There are 2 to the 32 043 * possible starting states for this generator when using {@link #setState(int)}, but it is unknown if that method 044 * actually puts the generator in the longest possible cycle, or just a sufficiently long one. 045 * <br> 046 * The name comes from M. Overton, who discovered this category of subcycle generators, and also how this generator can 047 * really move when it comes to speed. 048 * <br> 049 * Created by Tommy Ettinger on 9/13/2018. 050 * @author Mark Overton 051 * @author Tommy Ettinger 052 */ 053public final class Mover64RNG implements RandomnessSource { 054 private long stateA, stateB; 055 public Mover64RNG() 056 { 057 setState((int)((Math.random() * 2.0 - 1.0) * 0x80000000)); 058 } 059 public Mover64RNG(final int state) 060 { 061 setState(state); 062 } 063 064 /** 065 * Not advised for external use; prefer {@link #Mover64RNG(int)} because it guarantees a good subcycle. This 066 * constructor allows all subcycles to be produced, including ones with a shorter period. 067 * @param stateA 068 * @param stateB 069 */ 070 public Mover64RNG(final long stateA, final long stateB) 071 { 072 this.stateA = stateA == 0L ? 1L : stateA; 073 this.stateB = stateB == 0L ? 1L : stateB; 074 } 075 076 private static final long[] startingA = { 077 0x0000000000000001L, 0x770391C6587202CDL, 0x0148D0D6B055DE19L, 0x2CFFDEE4C4C8654FL, 0x3669291DE218F372L, 0x5B744ACB07F3D380L, 0x103F93C86BDF21D0L, 0x9A1D980831BCF2ABL, 078 0x92D56961736A4B50L, 0x71A9832527530EADL, 0x4C524342889BCFE1L, 0xF39CFA3D37AB4038L, 0xA3E9A70AD8EEF84DL, 0x65C7AFEFFC4DA898L, 0x4D455E304CDC7741L, 0xA6EDACBD6740B1A7L, 079 0xAA7F8E77C41AF5EBL, 0x96B50AD6E4AA2B18L, 0x77432395B55EDFD9L, 0x2748C2DD4565F1F0L, 0x3CAC2CDB2F8318D0L, 0x7D983C0295175158L, 0xDCFC33F629C3D00FL, 0x1EF0C5B47164F981L, 080 0x3AB9A3877956251EL, 0xBA230F415A833533L, 0xA489CC2EF532A6BEL, 0xB212F25D09BFC366L, 0xB9014F210A77310DL, 0x8590EF3967A8C6E0L, 0x1011FD4E97B1F81AL, 0x1C57F18A80F4C131L, 081 0x4AA90F013DB975E3L, 0xB3FAAC7A9374BD99L, 0xA15B9AA709431B2DL, 0xD3201A4C3953FFA2L, 0x0B34634F0B74BAB5L, 0x501389102E6E08EEL, 0xFCAC8A7CFCEB534DL, 0xA6A1A2C7CB5CEE8FL, 082 0x5F461436431B3D6DL, 0x1F3DE41F1E991A39L, 0x96A5BD1D16EDC265L, 0xAEC3F8C461FA0749L, 0x4445933104846C0BL, 0xAD088B25A4AA0E59L, 0x862FCA81FF8B1BE5L, 0x12E5A795C17DA902L, 083 0x5CA3CDC494DF2B93L, 0xCF612FCBDD25B41EL, 0xAD0CC4406EC6FCC3L, 0x352336C92FA965EAL, 0x675AB684694EE4A8L, 0x811A5D47EE8B3568L, 0x4937A92A07C372A4L, 0xE1483C680A24BEA4L, 084 0x1B3E829B910E343CL, 0x0F5F8EF159F931C0L, 0x7F5DDFDA98EFE7EAL, 0xA2FA4A6C79F5C6EFL, 0xEA416C98A2A0945CL, 0x29CC34E89FCC5D02L, 0x157FC5094CCC1795L, 0x27252C1165C6E255L, 085 0xAB963445C144A9BCL, 0x601530DECC304F69L, 0xC92D8F3257316572L, 0xC348074025724519L, 0x0F8305789523701EL, 0xD288EFE7BDDABF47L, 0xC428DA0AD18149BAL, 0xBA1D19D35E61A11EL, 086 0x6D81979DC0110FA2L, 0x3C144A6DC2C2982BL, 0x7593425EA77652A8L, 0xBA416F84332EFD0AL, 0x691EAA02B1351B41L, 0xF1B15F5AD69A16BAL, 0x026D58B160B39D4CL, 0x813B48A15DA161E6L, 087 0xCC92B59765EF4C5FL, 0x46B6C1ED44BF6877L, 0xA679D47C27EA4A03L, 0x393BEF21C904261CL, 0xE40A734EFE039992L, 0xD114E560A35EC443L, 0x85A46B901B80F546L, 0xCC8C80C6AB27F53CL, 088 0xC9B5FCE7C3EE4A83L, 0x64D4B2A2A91ADC11L, 0x7157576E65940314L, 0x75BF0B0737304143L, 0x4A11300B7F32C8C5L, 0x4B4FB70D7701DD60L, 0xE877F97BEC9E8FACL, 0x151E431374EF9D79L, 089 0x636214B0856DF427L, 0x088F1774DE7730CFL, 0x9E3B5CD7FF590F81L, 0x4DA157EA25850BC1L, 0xE9C7C31744E062F4L, 0x4767FCAF076B9508L, 0xC5C767D939AC8425L, 0x1ABAF0D4EC698A8FL, 090 0x5035DC94FA971B81L, 0x718EE38E931713E2L, 0x497DB43133CEF0F2L, 0xF01BE721B0145805L, 0x9D6239853FF80744L, 0x256B893D4DD0689AL, 0x256647CAA07563D6L, 0xCE4087F877A6D24FL, 091 0x68A0537869364FE2L, 0x32BA732DEC14AE42L, 0x3AAF6CDE0CE8DB48L, 0x552C1D9594CE212AL, 0x8BC1A33AE250B2E9L, 0xC02FCB678B465D00L, 0x496F580658AFD50AL, 0x6D0D982E45AD15A9L, 092 0xC8E87307F336E8D0L, 0x257E726598418548L, 0xFADF2ED10B13D148L, 0x46FA6CC74F293535L, 0xF03227995C268856L, 0x46087E39622EA4CDL, 0x17EE09D3D2181207L, 0x9C7518A1E5AD4544L, 093 }, startingB = { 094 0x0000000000000001L, 0x07293E6E09EC6368L, 0x96D969CADB4CD368L, 0x3FF86768F89EAEB3L, 0x2F9FAC39CC8E5CB7L, 0xF0ACF2D0542EE141L, 0x7BF403A079DCD087L, 0xDA68703F5EAB9409L, 095 0xF887EDE8E8AD388BL, 0xB93108A12DD8DC5CL, 0x98676A8BE90BB48EL, 0x3C66E22B602A7007L, 0x69A56A92BAD39B5BL, 0x58857B966DDF07BCL, 0x3B6890E3EDB96D6EL, 0xF0363B595221C86DL, 096 0x62EE3C3A7A528614L, 0xB0175247E00B4935L, 0xE70D810777ED42ACL, 0x275CE4F27473631AL, 0xB5DF57C4502967E9L, 0xB8EB0B9EC111C7FEL, 0xC28F3B422CA03689L, 0xD09DD3A8FEAB2DD1L, 097 0x4E2C713B5A7A0FFCL, 0x9AFC4BE99ED5F1AAL, 0xA89BFD2F6C2E97AEL, 0xF8735B9A6DF5F258L, 0xB2F89E533D9B9897L, 0xD89711EA7777E671L, 0x9658217AF4F448CAL, 0xEE3F474204385F6BL, 098 0x2B20D085EAB7ECC0L, 0xDF4FBDB5877EC70AL, 0xA27D970C88F1246BL, 0x88D0B336E63ADE23L, 0xC06AF42B0855C181L, 0x00E8B464987358DBL, 0xDA1DF8BA1E45586EL, 0x4C12347AB35D2F03L, 099 0x752C4942F1095640L, 0x608BD5FC9E04FA0AL, 0xB253E48775CDD5E1L, 0x643E8401460AAA59L, 0xE248C00B3A622F06L, 0xB01AD54DFE588BF2L, 0x1D486285F47A99D0L, 0x4ACE70E9A24E7B42L, 100 0xE498314246C2E894L, 0x67BB0785AEA67873L, 0xAB50922AD5171ABDL, 0x4BFA6DEE10549DC3L, 0x889BB7C03B745D65L, 0x705D68BC7379AEECL, 0x08BC6282C82C8B72L, 0xB967A84918604EDCL, 101 0x17F2AE6E78487967L, 0x038874F2D394FB80L, 0x7F7A2F1A581C66D3L, 0x99977A67381F6F7FL, 0x6B62915A4927F8D3L, 0x4DE18BB59A3C182DL, 0x94E508A682455109L, 0x986BE18241462557L, 102 0x0578DFAE00F8A0D6L, 0x29B22988B2264886L, 0xD552345E6E2A3125L, 0x5DB9E3195164C051L, 0x0E43BA334827D573L, 0x3AFAF8799E87209CL, 0xBC0E249E28B42DE9L, 0x022A07577137E25FL, 103 0x7DEB553C69DAA1FFL, 0x4A69C3A72EF45E41L, 0xBEBAC3CF3B608398L, 0xEB5771FF214E2487L, 0x9FB5E8C5B36B4CC9L, 0xC09F95341A44B518L, 0x668BEA20B4AE0875L, 0x633E56557743D5CBL, 104 0x60F91113C85EAAAAL, 0xB7FD377C14A36222L, 0xFCF5360544E39E14L, 0xC8201F79E019A016L, 0x9298BE81EFD5200FL, 0xBEB6A71A91068F67L, 0xB48125BFEFE20180L, 0xC470152566C3E1A0L, 105 0x46646F5388059BA1L, 0x6B2EFA0363CEB524L, 0xC60186015E2573E1L, 0x514BF9772FA2ACCEL, 0x1C44DACDE62A44EDL, 0x0CC4356D150B5469L, 0xDF21F9DAE98D5C86L, 0xA22573A5D741ACECL, 106 0x722CB87504029D8AL, 0x5727EA9D310F90F7L, 0x06D1E7DC6CF5C689L, 0x735BAEB75FDD9F85L, 0xEF96C3AF03785BEAL, 0xBE453FC733BEFA00L, 0xE27E2672BFCC1C44L, 0x541C5523E0FBB038L, 107 0xA04B840944E17E54L, 0x313CA18B6537B063L, 0xC7B93061D18C2FFEL, 0xE1D991D2E4A8CD20L, 0x5BB21B4ED59FAE91L, 0x7DB82C96F57D18C5L, 0x9EEBA39CBD611F6EL, 0x093E9402ABCC23F7L, 108 0x9A7637252A4475F7L, 0x0C8A522F0B70DB19L, 0x3532D24B07A4D08BL, 0x633C908FA64BB58AL, 0x16A3123AD6B3DD79L, 0x1169BB0D6BD6DEC5L, 0xDABFB787CED62E83L, 0x8F17A15C52A3B9BDL, 109 0xA2F3FA0F0F5F6FDFL, 0x95DA83EA34697FEFL, 0xFE1541E512CBAC77L, 0xE68287CDEB9302A5L, 0xB928A0223B695207L, 0x3F9D05B291DE5A8AL, 0x5E28B275895A2C79L, 0x8E9BD22FBFD57A6CL, 110 }; 111 112 public final void setState(final int s) { 113 stateA = startingA[s >>> 9 & 0x7F]; 114 for (int i = s & 0x1FF; i > 0; i--) { 115 stateA *= 0x41C64E6BL; 116 stateA = (stateA << 28 | stateA >>> 36); 117 } 118 stateB = startingB[s >>> 25]; 119 for (int i = s >>> 16 & 0x1FF; i > 0; i--) { 120 stateB *= 0x9E3779B9L; 121 stateB = (stateB << 37 | stateB >>> 27); 122 } 123 } 124 125 public final int nextInt() 126 { 127 final long a = stateA * 0x41C64E6BL; 128 final long b = stateB * 0x9E3779B9L; 129 return (int)((stateA = (a << 28 | a >>> 36)) ^ (stateB = (b << 37 | b >>> 27))); 130 } 131 @Override 132 public final int next(final int bits) 133 { 134 final long a = stateA * 0x41C64E6BL; 135 final long b = stateB * 0x9E3779B9L; 136 return (int)((stateA = (a << 28 | a >>> 36)) ^ (stateB = (b << 37 | b >>> 27))) >>> (32 - bits); 137 } 138 @Override 139 public final long nextLong() 140 { 141 final long a = stateA * 0x41C64E6BL; 142 final long b = stateB * 0x9E3779B9L; 143 return (stateA = (a << 28 | a >>> 36)) ^ (stateB = (b << 37 | b >>> 27)); 144 } 145 146 /** 147 * Produces a copy of this Mover64RNG that, if next() and/or nextLong() are called on this object and the 148 * copy, both will generate the same sequence of random numbers from the point copy() was called. This just need to 149 * copy the state so it isn't shared, usually, and produce a new value with the same exact state. 150 * 151 * @return a copy of this Mover64RNG 152 */ 153 @Override 154 public Mover64RNG copy() { 155 return new Mover64RNG(stateA, stateB); 156 } 157 158 /** 159 * Gets the "A" part of the state; if this generator was set with {@link #Mover64RNG()}, {@link #Mover64RNG(int)}, 160 * or {@link #setState(int)}, then this will be on the optimal subcycle, otherwise it may not be. 161 * @return the "A" part of the state, an int 162 */ 163 public long getStateA() 164 { 165 return stateA; 166 } 167 168 /** 169 * Gets the "B" part of the state; if this generator was set with {@link #Mover64RNG()}, {@link #Mover64RNG(int)}, 170 * or {@link #setState(int)}, then this will be on the optimal subcycle, otherwise it may not be. 171 * @return the "B" part of the state, an int 172 */ 173 public long getStateB() 174 { 175 return stateB; 176 } 177 /** 178 * Sets the "A" part of the state to any long, which may put the generator in a low-period subcycle. 179 * Use {@link #setState(int)} to guarantee a good subcycle. 180 * @param stateA any int 181 */ 182 public void setStateA(final long stateA) 183 { 184 this.stateA = stateA; 185 } 186 187 /** 188 * Sets the "B" part of the state to any long, which may put the generator in a low-period subcycle. 189 * Use {@link #setState(int)} to guarantee a good subcycle. 190 * @param stateB any int 191 */ 192 public void setStateB(final long stateB) 193 { 194 this.stateB = stateB; 195 } 196 197 @Override 198 public String toString() { 199 return "Mover64RNG with stateA 0x" + StringKit.hex(stateA) + " and stateB 0x" + StringKit.hex(stateB); 200 } 201 202 @Override 203 public boolean equals(Object o) { 204 if (this == o) return true; 205 if (o == null || getClass() != o.getClass()) return false; 206 207 Mover64RNG mover64RNG = (Mover64RNG) o; 208 209 return stateA == mover64RNG.stateA && stateB == mover64RNG.stateB; 210 } 211 212 @Override 213 public int hashCode() { 214 long h = 31L * stateA + stateB; 215 return (int)(h ^ h >>> 32); 216 } 217 218// public static void main(String[] args) 219// { 220// // A 10 0xC010AEB4 221// // B 22 0x195B9108 222// // all 0x04C194F3485D5A68 223// 224// // A 17 0xF7F87D28 225// // B 14 0xF023E25B 226// // all 0xE89BB7902049CD38 227// 228// 229// // A11 B14 0xBBDA9763B6CA318D 230// // A8 B14 0xC109F954C76CB09C 231// // A17 B14 0xE89BB7902049CD38 232//// BigInteger result = BigInteger.valueOf(0xF7F87D28L); 233//// BigInteger tmp = BigInteger.valueOf(0xF023E25BL); 234//// result = tmp.divide(result.gcd(tmp)).multiply(result); 235//// System.out.printf("0x%016X\n", result.longValue()); 236// int stateA = 1, i = 0; 237// for (; ; i++) { 238// if((stateA = Integer.rotateLeft(stateA * 0x9E37, 17)) == 1) 239// { 240// System.out.printf("0x%08X\n", i); 241// break; 242// } 243// } 244// BigInteger result = BigInteger.valueOf(i & 0xFFFFFFFFL); 245// i = 0; 246// for (; ; i++) { 247// if((stateA = Integer.rotateLeft(stateA * 0x4E6D, 14)) == 1) 248// { 249// System.out.printf("0x%08X\n", i); 250// break; 251// } 252// } 253// BigInteger tmp = BigInteger.valueOf(i & 0xFFFFFFFFL); 254// result = tmp.divide(result.gcd(tmp)).multiply(result); 255// System.out.printf("\n0x%016X\n", result.longValue()); 256// 257// } 258 259// public static void main(String[] args) 260// { 261// Mover32RNG m = new Mover32RNG(); 262// System.out.println("int[] startingA = {"); 263// for (int i = 0, ctr = 0; ctr < 128; ctr++, i+= 0x00000200) { 264// m.setState(i); 265// System.out.printf("0x%08X, ", m.stateA); 266// if((ctr & 7) == 7) 267// System.out.println(); 268// } 269// System.out.println("}, startingB = {"); 270// for (int i = 0, ctr = 0; ctr < 128; ctr++, i+= 0x02000000) { 271// m.setState(i); 272// System.out.printf("0x%08X, ", m.stateB); 273// if((ctr & 7) == 7) 274// System.out.println(); 275// } 276// System.out.println("};"); 277// } 278 279///////// BEGIN subcycle finder code and period evaluator 280// public static void main(String[] args) 281// { 282// // multiplying 283// // A refers to 0x9E377 284// // A 10 0xC010AEB4 285// // B refers to 0x64E6D 286// // B 22 0x195B9108 287// // all 0x04C194F3485D5A68 288// 289// // A=Integer.rotateLeft(A*0x9E377, 17) 0xF7F87D28 290// // B=Integer.rotateLeft(A*0x64E6D, 14) 0xF023E25B 291// // all 0xE89BB7902049CD38 292// 293// 294// // A11 B14 0xBBDA9763B6CA318D 295// // A8 B14 0xC109F954C76CB09C 296// // A17 B14 0xE89BB7902049CD38 297//// BigInteger result = BigInteger.valueOf(0xF7F87D28L); 298//// BigInteger tmp = BigInteger.valueOf(0xF023E25BL); 299//// result = tmp.divide(result.gcd(tmp)).multiply(result); 300//// System.out.printf("0x%016X\n", result.longValue()); 301// // 0x9E37 302// // rotation 27: 0xEE06F34D 303// // 0x9E35 304// // rotation 6 : 0xE1183C3A 305// // rotation 19: 0xC4FCFC55 306// // 0x9E3B 307// // rotation 25: 0xE69313ED 308// // 0xDE4D 309// // rotation 3 : 0xF6C16607 310// // rotation 23: 0xD23AD58D 311// // rotation 29: 0xC56DC41F 312// // 0x1337 313// // rotation 7: 0xF41BD009 314// // rotation 20: 0xF5846878 315// // rotation 25: 0xF38658F9 316// // 0xACED 317// // rotation 28: 0xFC98CC08 318// // rotation 31: 0xFA18CD57 319// // 0xBA55 320// // rotation 19: 0xFB059E43 321// // 0xC6D5 322// // rotation 05: 0xFFD78FD4 323// // 0x5995 324// // rotation 28: 0xFF4AB87D 325// // rotation 02: 0xFF2AA5D5 326// // 0xA3A9 327// // rotation 09: 0xFF6B3AF7 328// // 0xB9EF 329// // rotation 23: 0xFFAEB037 330// // 0x3D29 331// // rotation 04: 0xFF6B92C5 332// // 0x5FAB 333// // rotation 09: 0xFF7E3277 // seems to be very composite 334// // 0xCB7F 335// // rotation 01: 0xFF7F28FE 336// // 0x89A7 337// // rotation 13: 0xFFFDBF50 // wow! note that this is a multiple of 16 338// // 0xBCFD 339// // rotation 17: 0xFFF43787 // second-highest yet, also an odd number 340// // 0xA01B 341// // rotation 28: 0xFFEDA0B5 342// // 0xC2B9 343// // rotation 16: 0xFFEA9001 344// 345// 346// // adding 347// // 0x9E3779B9 348// // rotation 2 : 0xFFCC8933 349// // rotation 7 : 0xF715CEDF 350// // rotation 25: 0xF715CEDF 351// // rotation 30: 0xFFCC8933 352// // 0x6C8E9CF5 353// // rotation 6 : 0xF721971A 354// // 0x41C64E6D 355// // rotation 13: 0xFA312DBF 356// // rotation 19: 0xFA312DBF 357// // rotation 1 : 0xF945B8A7 358// // rotation 31: 0xF945B8A7 359// // 0xC3564E95 360// // rotation 1 : 0xFA69E895 also 31 361// // rotation 5 : 0xF2BF5E23 also 27 362// // 0x76BAF5E3 363// // rotation 14: 0xF4DDFC5A also 18 364// // 0xA67943A3 365// // rotation 11: 0xF1044048 also 21 366// // 0x6C96FEE7 367// // rotation 2 : 0xF4098F0D 368// // 0xA3014337 369// // rotation 15: 0xF3700ABF also 17 370// // 0x9E3759B9 371// // rotation 1 : 0xFB6547A2 also 31 372// // 0x6C8E9CF7 373// // rotation 7 : 0xFF151D74 also 25 374// // rotation 13: 0xFD468E2B also 19 375// // rotation 6 : 0xF145A7EB also 26 376// // 0xB531A935 377// // rotation 13: 0xFF9E2F67 also 19 378// // 0xC0EF50EB 379// // rotation 07: 0xFFF8A98D also 25 380// // 0x518DC14F 381// // rotation 09: 0xFFABD755 also 23 // probably not prime 382// // 0xA5F152BF 383// // rotation 07: 0xFFB234B2 also 27 384// // 0x8092D909 385// // rotation 10: 0xFFA82F7C also 22 386// // 0x73E2CCAB 387// // rotation 09: 0xFF9DE8B1 also 23 388// // stateB = rotate32(stateB + 0xB531A935, 13) 389// // stateC = rotate32(stateC + 0xC0EF50EB, 7) 390// 391// // subtracting, rotating, and bitwise NOT: 392// // 0xC68E9CF3 393// // rotation 13: 0xFEF97E17, also 19 394// // 0xC68E9CB7 395// // rotation 12: 0xFE3D7A2E 396// 397// // left xorshift 398// // 5 399// // rotation 15: 0xFFF7E000 400// // 13 401// // rotation 17: 0xFFFD8000 402// 403// // minus left shift, then xor 404// // state - (state << 12) ^ 0xC68E9CB7, rotation 21: 0xFFD299CB 405// // add xor 406// // state + 0xC68E9CB7 ^ 0xDFF4ECB9, rotation 30: 0xFFDAEDF7 407// // state + 0xC68E9CB7 ^ 0xB5402ED7, rotation 01: 0xFFE73631 408// // state + 0xC68E9CB7 ^ 0xB2B386E5, rotation 24: 0xFFE29F5D 409// // sub xor 410// // state - 0x9E3779B9 ^ 0xE541440F, rotation 22: 0xFFFC9E3E 411// 412// 413// // best power of two: 414// // can get 63.999691 with: (period is 0xFFF1F6F18B2A1330) 415// // multiplying A by 0x89A7 and rotating left by 13 416// // multiplying B by 0xBCFD and rotating left by 17 417// // can get 63.998159 with: (period is 0xFFAC703E2B6B1A30) 418// // multiplying A by 0x89A7 and rotating left by 13 419// // multiplying B by 0xB9EF and rotating left by 23 420// // can get 63.998 with: 421// // adding 0x9E3779B9 for A and rotating left by 2 422// // xorshifting B left by 5 (B ^ B << 5) and rotating left by 15 423// // can get 63.99 with: 424// // adding 0x9E3779B9 for A and rotating left by 2 425// // adding 0x6C8E9CF7 for B and rotating left by 7 426// // can get 63.98 with: 427// // adding 0x9E3779B9 for A and rotating left by 2 428// // multiplying by 0xACED, NOTing, and rotating left by 28 for B 429// // 0xFF6B3AF7L 0xFFAEB037L 0xFFD78FD4L 430// 431// // 0xFF42E24AF92DCD8C, 63.995831 432// //BigInteger result = BigInteger.valueOf(0xFF6B3AF7L), tmp = BigInteger.valueOf(0xFFD78FD4L); 433// 434// BigInteger result = BigInteger.valueOf(0xFFFDBF50L), tmp = BigInteger.valueOf(0xFFF43787L); 435// result = tmp.divide(result.gcd(tmp)).multiply(result); 436// tmp = BigInteger.valueOf(0xFFEDA0B5L); 437// result = tmp.divide(result.gcd(tmp)).multiply(result); 438// System.out.printf("\n0x%s, %2.6f\n", result.toString(16).toUpperCase(), Math.log(result.doubleValue()) / Math.log(2)); 439//// tmp = BigInteger.valueOf(0xFFABD755L); 440//// result = tmp.divide(result.gcd(tmp)).multiply(result); 441//// System.out.printf("\n0x%s, %2.6f\n", result.toString(16).toUpperCase(), Math.log(result.doubleValue()) / Math.log(2)); 442// int stateA = 1, i; 443// LinnormRNG lin = new LinnormRNG(); 444// System.out.println(lin.getState()); 445// Random rand = new RNG(lin).asRandom(); 446// for (int c = 1; c <= 200; c++) { 447// //final int r = (ThrustAltRNG.determineInt(20007 + c) & 0xFFFF)|1; 448// final int r = BigInteger.probablePrime(20, rand).intValue(); 449// //System.out.printf("(x ^ x << %d) + 0xC68E9CB7\n", c); 450// System.out.printf("%03d/200, testing r = 0x%08X\n", c, r); 451// for (int j = 1; j < 32; j++) { 452// i = 0; 453// for (; ; i++) { 454// if ((stateA = Integer.rotateLeft(stateA * r, j)) == 1) { 455// if (i >>> 24 == 0xFF) 456// System.out.printf("(state * 0x%08X, rotation %02d: 0x%08X\n", r, j, i); 457// break; 458// } 459// } 460// } 461// } 462// 463//// int stateA = 1, i = 0; 464//// for (; ; i++) { 465//// if((stateA = Integer.rotateLeft(~(stateA * 0x9E37), 7)) == 1) 466//// { 467//// System.out.printf("0x%08X\n", i); 468//// break; 469//// } 470//// } 471//// BigInteger result = BigInteger.valueOf(i & 0xFFFFFFFFL); 472//// i = 0; 473//// for (; ; i++) { 474//// if((stateA = Integer.rotateLeft(~(stateA * 0x4E6D), 17)) == 1) 475//// { 476//// System.out.printf("0x%08X\n", i); 477//// break; 478//// } 479//// } 480//// BigInteger tmp = BigInteger.valueOf(i & 0xFFFFFFFFL); 481//// result = tmp.divide(result.gcd(tmp)).multiply(result); 482//// System.out.printf("\n0x%016X\n", result.longValue()); 483// 484// } 485///////// END subcycle finder code and period evaluator 486 487 488// public static void main(String[] args) 489// { 490// long stateA = 1, stateB = 1; 491// System.out.println("long[] startingA = {"); 492// for (int ctr = 0; ctr < 128; ctr++) { 493// System.out.printf("0x%016XL, ", stateA); 494// if((ctr & 7) == 7) 495// System.out.println(); 496// for (int i = 0; i < 512; i++) { 497// stateA *= 0x41C64E6BL; 498// stateA = (stateA << 28 | stateA >>> 36); 499// } 500// } 501// System.out.println("}, startingB = {"); 502// for (int ctr = 0; ctr < 128; ctr++) { 503// System.out.printf("0x%016XL, ", stateB); 504// if((ctr & 7) == 7) 505// System.out.println(); 506// for (int i = 0; i < 512; i++) { 507// stateB *= 0x9E3779B9L; 508// stateB = (stateB << 37 | stateB >>> 27); 509// } 510// } 511// System.out.println("};"); 512// } 513}