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.MathRuntimeException; 020 021 /** Base class for random number generators that generates bits streams. 022 023 * @version $Revision: 796552 $ $Date: 2009-07-21 17:51:30 -0400 (Tue, 21 Jul 2009) $ 024 * @since 2.0 025 026 */ 027 public abstract class BitsStreamGenerator implements RandomGenerator { 028 029 /** Next gaussian. */ 030 private double nextGaussian; 031 032 /** Creates a new random number generator. 033 */ 034 public BitsStreamGenerator() { 035 nextGaussian = Double.NaN; 036 } 037 038 /** {@inheritDoc} */ 039 public abstract void setSeed(int seed); 040 041 /** {@inheritDoc} */ 042 public abstract void setSeed(int[] seed); 043 044 /** {@inheritDoc} */ 045 public abstract void setSeed(long seed); 046 047 /** Generate next pseudorandom number. 048 * <p>This method is the core generation algorithm. It is used by all the 049 * public generation methods for the various primitive types {@link 050 * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()}, 051 * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()}, 052 * {@link #next(int)} and {@link #nextLong()}.</p> 053 * @param bits number of random bits to produce 054 * @return random bits generated 055 */ 056 protected abstract int next(int bits); 057 058 /** {@inheritDoc} */ 059 public boolean nextBoolean() { 060 return next(1) != 0; 061 } 062 063 /** {@inheritDoc} */ 064 public void nextBytes(byte[] bytes) { 065 int i = 0; 066 final int iEnd = bytes.length - 3; 067 while (i < iEnd) { 068 final int random = next(32); 069 bytes[i] = (byte) (random & 0xff); 070 bytes[i + 1] = (byte) ((random >> 8) & 0xff); 071 bytes[i + 2] = (byte) ((random >> 16) & 0xff); 072 bytes[i + 3] = (byte) ((random >> 24) & 0xff); 073 i += 4; 074 } 075 int random = next(32); 076 while (i < bytes.length) { 077 bytes[i++] = (byte) (random & 0xff); 078 random = random >> 8; 079 } 080 } 081 082 /** {@inheritDoc} */ 083 public double nextDouble() { 084 final long high = ((long) next(26)) << 26; 085 final int low = next(26); 086 return (high | low) * 0x1.0p-52d; 087 } 088 089 /** {@inheritDoc} */ 090 public float nextFloat() { 091 return next(23) * 0x1.0p-23f; 092 } 093 094 /** {@inheritDoc} */ 095 public double nextGaussian() { 096 097 final double random; 098 if (Double.isNaN(nextGaussian)) { 099 // generate a new pair of gaussian numbers 100 final double x = nextDouble(); 101 final double y = nextDouble(); 102 final double alpha = 2 * Math.PI * x; 103 final double r = Math.sqrt(-2 * Math.log(y)); 104 random = r * Math.cos(alpha); 105 nextGaussian = r * Math.sin(alpha); 106 } else { 107 // use the second element of the pair already generated 108 random = nextGaussian; 109 nextGaussian = Double.NaN; 110 } 111 112 return random; 113 114 } 115 116 /** {@inheritDoc} */ 117 public int nextInt() { 118 return next(32); 119 } 120 121 /** {@inheritDoc} */ 122 public int nextInt(int n) throws IllegalArgumentException { 123 124 if (n < 1) { 125 throw MathRuntimeException.createIllegalArgumentException( 126 "upper bound must be positive ({0})", 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 }