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 }