001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math.random; 018 019 import org.apache.commons.math.exception.NotStrictlyPositiveException; 020 import org.apache.commons.math.util.FastMath; 021 022 /** Base class for random number generators that generates bits streams. 023 024 * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 ao??t 2010) $ 025 * @since 2.0 026 027 */ 028 public abstract class BitsStreamGenerator implements RandomGenerator { 029 030 /** Next gaussian. */ 031 private double nextGaussian; 032 033 /** Creates a new random number generator. 034 */ 035 public BitsStreamGenerator() { 036 nextGaussian = Double.NaN; 037 } 038 039 /** {@inheritDoc} */ 040 public abstract void setSeed(int seed); 041 042 /** {@inheritDoc} */ 043 public abstract void setSeed(int[] seed); 044 045 /** {@inheritDoc} */ 046 public abstract void setSeed(long seed); 047 048 /** Generate next pseudorandom number. 049 * <p>This method is the core generation algorithm. It is used by all the 050 * public generation methods for the various primitive types {@link 051 * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()}, 052 * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()}, 053 * {@link #next(int)} and {@link #nextLong()}.</p> 054 * @param bits number of random bits to produce 055 * @return random bits generated 056 */ 057 protected abstract int next(int bits); 058 059 /** {@inheritDoc} */ 060 public boolean nextBoolean() { 061 return next(1) != 0; 062 } 063 064 /** {@inheritDoc} */ 065 public void nextBytes(byte[] bytes) { 066 int i = 0; 067 final int iEnd = bytes.length - 3; 068 while (i < iEnd) { 069 final int random = next(32); 070 bytes[i] = (byte) (random & 0xff); 071 bytes[i + 1] = (byte) ((random >> 8) & 0xff); 072 bytes[i + 2] = (byte) ((random >> 16) & 0xff); 073 bytes[i + 3] = (byte) ((random >> 24) & 0xff); 074 i += 4; 075 } 076 int random = next(32); 077 while (i < bytes.length) { 078 bytes[i++] = (byte) (random & 0xff); 079 random = random >> 8; 080 } 081 } 082 083 /** {@inheritDoc} */ 084 public double nextDouble() { 085 final long high = ((long) next(26)) << 26; 086 final int low = next(26); 087 return (high | low) * 0x1.0p-52d; 088 } 089 090 /** {@inheritDoc} */ 091 public float nextFloat() { 092 return next(23) * 0x1.0p-23f; 093 } 094 095 /** {@inheritDoc} */ 096 public double nextGaussian() { 097 098 final double random; 099 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 }