1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. 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 package org.apache.commons.math.random; 18 19 import org.apache.commons.math.exception.NotStrictlyPositiveException; 20 import org.apache.commons.math.util.FastMath; 21 22 /** Base class for random number generators that generates bits streams. 23 24 * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 aot 2010) $ 25 * @since 2.0 26 27 */ 28 public abstract class BitsStreamGenerator implements RandomGenerator { 29 30 /** Next gaussian. */ 31 private double nextGaussian; 32 33 /** Creates a new random number generator. 34 */ 35 public BitsStreamGenerator() { 36 nextGaussian = Double.NaN; 37 } 38 39 /** {@inheritDoc} */ 40 public abstract void setSeed(int seed); 41 42 /** {@inheritDoc} */ 43 public abstract void setSeed(int[] seed); 44 45 /** {@inheritDoc} */ 46 public abstract void setSeed(long seed); 47 48 /** Generate next pseudorandom number. 49 * <p>This method is the core generation algorithm. It is used by all the 50 * public generation methods for the various primitive types {@link 51 * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()}, 52 * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()}, 53 * {@link #next(int)} and {@link #nextLong()}.</p> 54 * @param bits number of random bits to produce 55 * @return random bits generated 56 */ 57 protected abstract int next(int bits); 58 59 /** {@inheritDoc} */ 60 public boolean nextBoolean() { 61 return next(1) != 0; 62 } 63 64 /** {@inheritDoc} */ 65 public void nextBytes(byte[] bytes) { 66 int i = 0; 67 final int iEnd = bytes.length - 3; 68 while (i < iEnd) { 69 final int random = next(32); 70 bytes[i] = (byte) (random & 0xff); 71 bytes[i + 1] = (byte) ((random >> 8) & 0xff); 72 bytes[i + 2] = (byte) ((random >> 16) & 0xff); 73 bytes[i + 3] = (byte) ((random >> 24) & 0xff); 74 i += 4; 75 } 76 int random = next(32); 77 while (i < bytes.length) { 78 bytes[i++] = (byte) (random & 0xff); 79 random = random >> 8; 80 } 81 } 82 83 /** {@inheritDoc} */ 84 public double nextDouble() { 85 final long high = ((long) next(26)) << 26; 86 final int low = next(26); 87 return (high | low) * 0x1.0p-52d; 88 } 89 90 /** {@inheritDoc} */ 91 public float nextFloat() { 92 return next(23) * 0x1.0p-23f; 93 } 94 95 /** {@inheritDoc} */ 96 public double nextGaussian() { 97 98 final double random; 99 if (Double.isNaN(nextGaussian)) { 100 // generate a new pair of gaussian numbers 101 final double x = nextDouble(); 102 final double y = nextDouble(); 103 final double alpha = 2 * FastMath.PI * x; 104 final double r = FastMath.sqrt(-2 * FastMath.log(y)); 105 random = r * FastMath.cos(alpha); 106 nextGaussian = r * FastMath.sin(alpha); 107 } else { 108 // use the second element of the pair already generated 109 random = nextGaussian; 110 nextGaussian = Double.NaN; 111 } 112 113 return random; 114 115 } 116 117 /** {@inheritDoc} */ 118 public int nextInt() { 119 return next(32); 120 } 121 122 /** {@inheritDoc} */ 123 public int nextInt(int n) throws IllegalArgumentException { 124 125 if (n < 1) { 126 throw new NotStrictlyPositiveException(n); 127 } 128 129 // find bit mask for n 130 int mask = n; 131 mask |= mask >> 1; 132 mask |= mask >> 2; 133 mask |= mask >> 4; 134 mask |= mask >> 8; 135 mask |= mask >> 16; 136 137 while (true) { 138 final int random = next(32) & mask; 139 if (random < n) { 140 return random; 141 } 142 } 143 144 } 145 146 /** {@inheritDoc} */ 147 public long nextLong() { 148 final long high = ((long) next(32)) << 32; 149 final long low = ((long) next(32)) & 0xffffffffL; 150 return high | low; 151 } 152 153 } 154