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 }