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 32-bit states; this is the fastest 32-bit generator that still passes statistical
008 * tests, plus it's optimized for GWT (sometimes). It has a period of just under 2 to the 64, 0xFFF1F6F18B2A1330, which
009 * is roughly 2 to the 63.999691, and allows 2 to the 32 initial seeds.
010 * <br>
011 * This seems to do well in PractRand testing (32 TB passed), but this is not a generator Overton tested. "Chaotic"
012 * generators like this one tend to score well in PractRand, but it isn't clear if they will fail other tests (in
013 * particular, they can't generate all possible long values, and also can't generate 0 or possibly some other ints). As
014 * for desktop/server speed, this is faster than {@link Starfish32RNG} (which is also high-quality) and is also faster
015 * than {@link Lathe32RNG} (which is very fast but has quality issues). However, this is slower than Lathe32RNG when
016 * using GWT and viewing in Firefox; for some reason {@link Starfish32RNG} optimizes well on Firefox and less well on
017 * Chrome, but Mover does ver well in older Chrome (faster than Lathe) and rather poorly on Firefox. It doesn't do
018 * amazingly well in current Chrome versions, however, and Lathe beats it most of the time there. On 64-bit desktop or
019 * server Java, you may want to prefer {@link Mover64RNG}, which is the same algorithm using larger words and constants,
020 * or {@link MiniMover64RNG}, which is even faster but probably has a shorter period than this generator (millions of
021 * seeds have been checked to ensure a minimum period of 2 to the 20 for it, though). While each of the two parts
022 * of a Mover32RNG can have their full period evaluated, making the total period possible to calculate, the same cannot
023 * be said for Mover64RNG or MiniMover64RNG (their maximum periods are high enough for most usage, but the actual totals
024 * are still unknown).
025 * <br>
026 * Its period is 0xFFF1F6F18B2A1330 for the largest cycle, which it always initializes into if {@link #setState(int)} is
027 * used. setState() only allows 2 to the 32 starting states, but less than 2 to the 64 states are in the largest cycle,
028 * so using a long or two ints to set the state seems ill-advised. The generator has two similar parts, each updated
029 * without needing to read from the other part. Each is a 32-bit CMR generator, which multiplies a state by a constant,
030 * rotates by another constant, and stores that as the next state. The particular constants used here were found by
031 * randomly picking 16-bit odd numbers as multipliers, checking the period for every non-zero rotation, and reporting
032 * the multiplier and rotation amount when a period was found that was greater than 0xFF000000. Better multipliers are
033 * almost guaranteed to exist, but finding them would be a challenge.
034 * <br>
035 * This is a RandomnessSource but not a StatefulRandomness because it needs to take care and avoid seeds that would put
036 * it in a short-period subcycle. It uses two generators with different cycle lengths, and skips at most 65536 times
037 * into each generator's cycle independently when seeding. It uses constants to store 128 known midpoints for each
038 * generator, which ensures it calculates an advance for each generator at most 511 times. 
039 * <br>
040 * The name comes from M. Overton, who discovered this category of subcycle generators, and also how this generator can
041 * really move when it comes to speed.
042 * <br>
043 * Created by Tommy Ettinger on 8/6/2018.
044 * @author Mark Overton
045 * @author Tommy Ettinger
046 */
047public final class Mover32RNG implements RandomnessSource {
048    private int stateA, stateB;
049    public Mover32RNG()
050    {
051        setState((int)((Math.random() * 2.0 - 1.0) * 0x80000000));
052    }
053    public Mover32RNG(final int state)
054    {
055        setState(state);
056    }
057
058    /**
059     * Not advised for external use; prefer {@link #Mover32RNG(int)} because it guarantees a good subcycle. This
060     * constructor allows all subcycles to be produced, including ones with a shorter period.
061     * @param stateA
062     * @param stateB
063     */
064    public Mover32RNG(final int stateA, final int stateB)
065    {
066        this.stateA = stateA == 0 ? 1 : stateA;
067        this.stateB = stateB == 0 ? 1 : stateB;
068    }
069
070    private static final int[] startingA = {
071            0x00000001, 0xCB2DA1A7, 0x215A5ADF, 0x2688266B, 0xEA31ECEE, 0x3F02F6A8, 0xB0833422, 0xC791ACA6,
072            0x976236C8, 0xF57961C0, 0x16EBE830, 0xCCCC2F10, 0x165D9801, 0x15E02FEA, 0xA302CC65, 0xAF68AE37,
073            0x4997CCA3, 0xF331F604, 0xF1DE5DA7, 0x07F21BA7, 0xD1752EC7, 0x308B16F2, 0x1B92D899, 0xF1A38AC8,
074            0x58F317B2, 0x1CC8EC79, 0x62588F4B, 0x975BF8FE, 0xE589C2D0, 0xB087C03D, 0x600F5DD0, 0xA32BD629,
075            0x3B52D26D, 0x0C7C18FD, 0xEB037A63, 0xE6F8BC93, 0x2CD250CF, 0x84327882, 0xA708FC6E, 0x5873EF12,
076            0x72FD78CF, 0xFFE73771, 0x18817285, 0x8EB3BC50, 0xE68597E0, 0xDF719E77, 0x35FE32C8, 0xF60532A1,
077            0xE93A1484, 0x697DF36B, 0xDFD41306, 0x37E0FADD, 0x6883EB39, 0xAF9CF955, 0xE11EB329, 0xDA951CC2,
078            0x325ECD67, 0x1DD8AC79, 0x7632669F, 0x0949BCB0, 0x965B0557, 0xB72DC0BC, 0x84448A7C, 0x6AC9B9CF,
079            0x92B7742A, 0xCFB27744, 0xFF154B26, 0xFD11E5F7, 0x5B6DE8D4, 0x59727211, 0x0A36FF7F, 0x56657899,
080            0xF9848758, 0x59415D9E, 0xE70E6901, 0x90858D00, 0x10B73995, 0x324FC7AD, 0xC62F801D, 0x4BBDA0E8,
081            0x70C8FDD5, 0xCC4376F1, 0x489AD7B7, 0xF4FB2500, 0x2279E051, 0x7840BF9E, 0x876AABF9, 0xF374F7BD,
082            0x6074B429, 0xC2EE6430, 0x238172DA, 0xFE3D050E, 0x5EF2F6B4, 0xF6359946, 0x127AAD89, 0xECA6FA56,
083            0x678B27CE, 0xDCD03A3C, 0xA45371BB, 0x5F2F422C, 0xE26B613C, 0x70DD9AF4, 0x1B0787BB, 0x0B8D2553,
084            0x3A430C3F, 0xAFF29AE2, 0x9DFAEB51, 0x1DE0F40E, 0x0467D74A, 0x85949411, 0xF8BC0358, 0x558BA744,
085            0x41A5B43A, 0x6B7E1C89, 0x9BF095BD, 0x5E2473CC, 0x4DFBF45B, 0xFB3510DC, 0xB7EC5786, 0xA99D6129,
086            0x120988F6, 0x796A7DE7, 0x9DEFD945, 0x0D2B25CE, 0xB7C1107E, 0x72E29D75, 0x85E01D79, 0x69AB992F,
087    }, startingB = {
088            0x00000001, 0xAB7EE445, 0x6FB35C9C, 0x459AB7A2, 0xEA61D065, 0x306F5E5F, 0xCE50A64A, 0x6D76B642,
089            0x11F3C6D4, 0xB3FF1D66, 0x657E6790, 0x4C62472D, 0xBEABAB16, 0xFD455176, 0xDCB98EDB, 0x1FC27360,
090            0x80C1241C, 0xC0C5BCC0, 0x6A67518B, 0xF2D69A39, 0xFA7D6C16, 0xE906A517, 0x899FFA7B, 0x2E42A99D,
091            0xBAF5B6E8, 0x3BBDC45A, 0x2497A707, 0xEA2DB138, 0x7D4ABF97, 0x552F5D4E, 0x15FE4BBD, 0xBC51DF5A,
092            0x465BDC95, 0x736A018F, 0x8A72CB63, 0x103119BE, 0x40403117, 0xA295957B, 0xCDDA9C19, 0xF0551CC6,
093            0x77CBAB76, 0xA054FD6A, 0x8974C93F, 0x8E314DC1, 0x42BC030E, 0x7F090540, 0x177998EA, 0x20457F09,
094            0xC13609D7, 0xA2683753, 0xE9F84638, 0x1BE07B83, 0x5DB36480, 0x39AE5B3A, 0xE044E164, 0x6E6B6191,
095            0x6036E5C8, 0x00703FE1, 0x53935ED8, 0x6B4443F5, 0x8FB91605, 0x146478C9, 0x2D0429BB, 0x86E8F88A,
096            0xD8DFFDB7, 0x77223F7D, 0x2B065674, 0xD80D2DD6, 0x0DFE5CEB, 0x44A495A5, 0x758EF0A9, 0x5FB55BA5,
097            0x8935A9B1, 0x84189069, 0xAA2194BC, 0x5FB95103, 0x6B60B887, 0xC63A769E, 0xA74BE357, 0x9F71B1F8,
098            0x3320B09E, 0xD369B3FC, 0xBCDB4B4E, 0xDC4DBCC9, 0x01F67CD2, 0xB3F6AA2B, 0x082CA2B3, 0xA54F168F,
099            0x0A9F82C9, 0x77DC3F93, 0x18D32D96, 0x1FC3FCE5, 0x97542B7A, 0x88CA9F81, 0x75370CE4, 0x8C2749C3,
100            0x94B63AE4, 0xC55E3BB7, 0x176BA775, 0x8C2BFEFC, 0x8C457557, 0xD8BFFD54, 0xB3D322DC, 0x072D766C,
101            0x40912BF4, 0x99CA7F36, 0xBC78BE45, 0x22F95B6B, 0xB37B05C9, 0x23493DB3, 0xCFBDC9C3, 0xB0379084,
102            0x2A2BFA20, 0x9A9DA93D, 0xCDE62486, 0x079CF8E6, 0x5B45CF64, 0xA19945A8, 0x196C1AA8, 0x9B19C771,
103            0x702CC28B, 0xFF4C5B02, 0x2FDD78D2, 0x71FFBD4E, 0xDF4C60A4, 0x143FAB0B, 0xAD9C8EB0, 0x6F35837D,
104    };
105
106    public final void setState(final int s) {
107        stateA = startingA[s >>> 9 & 0x7F];
108        for (int i = s & 0x1FF; i > 0; i--) {
109            stateA *= 0x89A7;
110            stateA = (stateA << 13 | stateA >>> 19);
111        }
112        stateB = startingB[s >>> 25];
113        for (int i = s >>> 16 & 0x1FF; i > 0; i--) {
114            stateB *= 0xBCFD;
115            stateB = (stateB << 17 | stateB >>> 15);
116        }
117    }
118
119    public final int nextInt()
120    {
121        int y = stateA * 0x89A7;
122        stateA = (y = (y << 13 | y >>> 19));
123        final int x = stateB * 0xBCFD;
124        return (y ^ (stateB = (x << 17 | x >>> 15)));
125    }
126    @Override
127    public final int next(final int bits)
128    {
129        int y = stateA * 0x89A7;
130        stateA = (y = (y << 13 | y >>> 19));
131        final int x = stateB * 0xBCFD;
132        return (y ^ (stateB = (x << 17 | x >>> 15))) >>> (32 - bits);
133    }
134    @Override
135    public final long nextLong()
136    {
137        int y = stateA * 0x89A7;
138        y = (y << 13 | y >>> 19);
139        int x = stateB * 0xBCFD;
140        final long t = (y ^ (x = (x << 17 | x >>> 15))) & 0xFFFFFFFFL;
141        y *= 0x89A7;
142        stateA = (y = (y << 13 | y >>> 19));
143        x *= 0xBCFD;
144        return t << 32 | ((y ^ (stateB = (x << 17 | x >>> 15))) & 0xFFFFFFFFL);
145    }
146
147    /**
148     * Produces a copy of this Mover32RNG that, if next() and/or nextLong() are called on this object and the
149     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just need to
150     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
151     *
152     * @return a copy of this Mover32RNG
153     */
154    @Override
155    public Mover32RNG copy() {
156        return new Mover32RNG(stateA, stateB);
157    }
158
159    /**
160     * Gets the "A" part of the state; if this generator was set with {@link #Mover32RNG()}, {@link #Mover32RNG(int)},
161     * or {@link #setState(int)}, then this will be on the optimal subcycle, otherwise it may not be. 
162     * @return the "A" part of the state, an int
163     */
164    public int getStateA()
165    {
166        return stateA;
167    }
168
169    /**
170     * Gets the "B" part of the state; if this generator was set with {@link #Mover32RNG()}, {@link #Mover32RNG(int)},
171     * or {@link #setState(int)}, then this will be on the optimal subcycle, otherwise it may not be. 
172     * @return the "B" part of the state, an int
173     */
174    public int getStateB()
175    {
176        return stateB;
177    }
178    /**
179     * Sets the "A" part of the state to any int, which may put the generator in a low-period subcycle.
180     * Use {@link #setState(int)} to guarantee a good subcycle.
181     * @param stateA any int
182     */
183    public void setStateA(final int stateA)
184    {
185        this.stateA = stateA;
186    }
187
188    /**
189     * Sets the "B" part of the state to any int, which may put the generator in a low-period subcycle.
190     * Use {@link #setState(int)} to guarantee a good subcycle.
191     * @param stateB any int
192     */
193    public void setStateB(final int stateB)
194    {
195        this.stateB = stateB;
196    }
197    
198    @Override
199    public String toString() {
200        return "Mover32RNG with stateA 0x" + StringKit.hex(stateA) + " and stateB 0x" + StringKit.hex(stateB);
201    }
202
203    @Override
204    public boolean equals(Object o) {
205        if (this == o) return true;
206        if (o == null || getClass() != o.getClass()) return false;
207
208        Mover32RNG mover32RNG = (Mover32RNG) o;
209
210        return stateA == mover32RNG.stateA && stateB == mover32RNG.stateB;
211    }
212
213    @Override
214    public int hashCode() {
215        return 31 * stateA + stateB | 0;
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//        int stateA = 1, stateB = 1;
491//        System.out.println("int[] startingA = {");
492//        for (int ctr = 0; ctr < 128; ctr++) {
493//            System.out.printf("0x%08X, ", stateA);
494//            if((ctr & 7) == 7)
495//                System.out.println();
496//            for (int i = 0; i < 512; i++) {
497//                stateA *= 0x89A7;
498//                stateA = (stateA << 13 | stateA >>> 19);
499//            }
500//        }
501//        System.out.println("}, startingB = {");
502//        for (int ctr = 0; ctr < 128; ctr++) {
503//            System.out.printf("0x%08X, ", stateB);
504//            if((ctr & 7) == 7)
505//                System.out.println();
506//            for (int i = 0; i < 512; i++) {
507//                stateB *= 0xBCFD;
508//                stateB = (stateB << 17 | stateB >>> 15);
509//            }
510//        }
511//        System.out.println("};");
512//    }
513}