KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgap > util > randomLEcuyer


1 package org.jgap.util;
2
3
4 /**
5     Implementation of a <b>randomX</b>-compliant class using
6     L'Ecuyer's two-sequence generator with a Bays-Durham shuffle, as
7     described on page 282 of Press et al., <cite>Numerical Recipes in
8     C</cite>, 2nd edition. Their implementation was constrained by
9     the absence of a 64-bit integer data type. Since Java guarantees
10     a <tt>long</tt> to be 64 bit, we can use L'Ecuyer's multiplier and modulus
11     directly, rather than flailing around with Schrage's algorithm.
12     Further, 64-bit <tt>long</tt> arithmetic allows us to directly combine
13     the results from the two generators by adding and taking the modulus of
14     one of them, bypassing the subtract and test for negative gimmick used
15     in <cite>Numerical Recipes</cite>.
16
17     <p>
18     For additional details, see L'Ecuyer's original 1968 paper
19     at page 742 of <cite>Communications of the ACM</cite>,
20     Vol. 31.
21
22     <p>
23     Designed and implemented in July 1996 by
24     <a HREF="http://www.fourmilab.ch/">John Walker</a>,
25     <a HREF="mailto:kelvin@fourmilab.ch">kelvin@fourmilab.ch</a>.
26 */

27 public class randomLEcuyer extends randomX {
28
29     /* L'Ecuyer's recommended multiplier and modulus for the two
30        multiplicative congruential generators. Even though the
31        values fit in 32 bits, we declare them as long so that the
32        arithmetic in calculating the next value will be automatically
33        done in long without need for casting. */

34
35     static final long mul1 = 40014,
36                       mod1 = 2147483563,
37                       mul2 = 40692,
38                       mod2 = 2147483399;
39     static final int shuffleSize = 32, // Shuffle table size
40
warmup = 19; /* Number of initial warmup
41                                                 results to "burn" */

42
43     int gen1, gen2, state;
44     int [] shuffle;
45
46     // Constructors
47

48     /** Creates a new pseudorandom number generator, seeded from
49         the current time. */

50
51     public randomLEcuyer() {
52         shuffle = new int[shuffleSize];
53         this.setSeed(System.currentTimeMillis());
54     }
55
56     /** Creates a new pseudorandom number generator with a
57         specified nonzero seed.
58
59 @param seed initial seed for the generator
60     */

61
62     public randomLEcuyer(long seed) throws IllegalArgumentException JavaDoc {
63         shuffle = new int[shuffleSize];
64         this.setSeed(seed);
65     }
66
67     // Seed access
68

69     /** Set seed for generator. Subsequent values will be based
70         on the given nonzero seed.
71
72 @param seed seed for the generator
73     */

74
75     public void setSeed(long seed) throws IllegalArgumentException JavaDoc {
76         int i;
77
78         if (seed == 0) {
79             throw new IllegalArgumentException JavaDoc("seed must be nonzero");
80         }
81         gen1 = gen2 = (int) (seed & 0x7FFFFFFFFL);
82
83         /* "Warm up" the generator for a number of rounds to eliminate
84            any residual inflence of the seed. */

85
86         for (i = 0; i < warmup; i++) {
87             gen1 = (int) ((gen1 * mul1) % mod1);
88         }
89
90         // Fill the shuffle table with values
91

92         for (i = 0; i < shuffleSize; i++) {
93             gen1 = (int) ((gen1 * mul1) % mod1);
94             shuffle[(shuffleSize - 1) - i] = gen1;
95         }
96         state = shuffle[0];
97     }
98
99     /** Get next byte from generator.
100
101 @return the next byte from the generator.
102     */

103
104     public byte nextByte() {
105         int i;
106
107         gen1 = (int) ((gen1 * mul1) % mod1); // Cycle generator 1
108
gen2 = (int) ((gen2 * mul2) % mod2); // Cycle generator 2
109

110         /* Extract shuffle table index from most significant part
111            of the previous result. */

112
113         i = state / (1 + (((int) mod1) - 1) / shuffleSize);
114
115         // New state is sum of generators modulo one of their moduli
116

117         state = (int) ((((long) shuffle[i]) + gen2) % mod1);
118
119         // Replace value in shuffle table with generator 1 result
120

121         shuffle[i] = gen1;
122
123         return (byte) (state / (1 + (((int) mod1) - 1) / 256));
124     }
125 };
126
Popular Tags