1 /***
2 *
3 * Copyright 2004 Protique Ltd
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18
19 package org.codehaus.activemq.transport.reliable;
20
21 /***
22 * A Shuffled Multiple Combined Linear Congruential Generator Uses L'Ecuyer's CLCG4 with a Bays-Durham shuffle. From
23 * <cite>Numerical Recipes inC </cite> This produces a more random stream of results than just
24 * <code>java.util.Random</code>
25 *
26 * @version $Revision: 1.1 $
27 */
28 public class SMLCGRandom {
29 private static final long MULTIPLIER_1 = 40014;
30 private static final long MOD_1 = 2147483563;
31 private static final long MULTIPLIER_2 = 40692;
32 private static final long MOD_2 = 2147483399;
33 private static final int SHUFFLE_LEN = 32;
34 private static final int WARMUP_LENGTH = 19;
35 private int generated_1, generated_2, state;
36 private int[] shuffle;
37
38 /***
39 * Creates a new pseudorandom number generator, seeded from the current time.
40 */
41 public SMLCGRandom() {
42 this(System.currentTimeMillis());
43 }
44
45 /***
46 * Creates the generator with the provided seed
47 *
48 * @param seed
49 */
50 public SMLCGRandom(long seed) {
51 shuffle = new int[SHUFFLE_LEN];
52 this.setSeed(seed);
53 }
54
55 /***
56 * Set the seed for the random generator
57 * @param seed
58 * @throws IllegalArgumentException
59 */
60 public void setSeed(long seed) throws IllegalArgumentException {
61 int i;
62 generated_1 = generated_2 = (int) (seed & 0x7FFFFFFFFL);
63 for (i = 0;i < WARMUP_LENGTH;i++) {
64 generated_1 = (int) ((generated_1 * MULTIPLIER_1) % MOD_1);
65 }
66 for (i = 0;i < SHUFFLE_LEN;i++) {
67 generated_1 = (int) ((generated_1 * MULTIPLIER_1) % MOD_1);
68 shuffle[(SHUFFLE_LEN - 1) - i] = generated_1;
69 }
70 state = shuffle[0];
71 }
72
73 /***
74 * @return the next random, uniformly distrubted, <tt>short</tt> value
75 */
76 public short nextShort() {
77 return (short) ((((short) nextByte()) << 8) | ((short) (nextByte() & 0xFF)));
78 }
79
80 /***
81 * @return the next random, uniformly distrubted, <tt>int</tt> value
82 */
83 public int nextInt() {
84 return (int) ((((int) nextShort()) << 16) | (((int) nextShort()) & 0xFFFF));
85 }
86
87 /***
88 * @return the next random, uniformly distrubted, <tt>long</tt> value
89 */
90 public long nextLong() {
91 return (long) ((((long) nextInt()) << 32) | (((long) nextInt()) & 0xFFFFFFFFl));
92 }
93
94 /***
95 * @return the next random, uniformly distributed, <tt>float</tt> value, greater than or equal to 0 and less than
96 * 1.
97 */
98 public float nextFloat() {
99 return (float) ((nextInt() & 0x7FFFFFFF) / (0x7FFFFFFF * 1.0));
100 }
101
102 /***
103 * @return the next random, uniformly distributed, <tt>double</tt> value, greater than or equal to 0 and less than
104 * 1.
105 */
106 public double nextDouble() {
107 return (double) ((nextLong() & 0x7FFFFFFFFFFFFFFFl) / (0x7FFFFFFFFFFFFFFFl * 1.0));
108 }
109
110 /***
111 * @return the next random, uniformly distrubted, <tt>byte</tt> value
112 */
113 public byte nextByte() {
114 int i = 0;
115 generated_1 = (int) ((generated_1 * MULTIPLIER_1) % MOD_1);
116 generated_2 = (int) ((generated_2 * MULTIPLIER_2) % MOD_2);
117 i = state / (1 + (((int) MOD_1) - 1) / SHUFFLE_LEN);
118 i = Math.abs(i);
119 state = (int) ((((long) shuffle[i]) + generated_2) % MOD_1);
120 shuffle[i] = generated_1;
121 return (byte) (state / (1 + (((int) MOD_1) - 1) / 256));
122 }
123 }