View Javadoc

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 }