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 */ 017package org.apache.commons.math3.random; 018 019import java.io.Serializable; 020 021import org.apache.commons.math3.exception.NotStrictlyPositiveException; 022import org.apache.commons.math3.util.FastMath; 023 024/** Base class for random number generators that generates bits streams. 025 * 026 * @since 2.0 027 */ 028public abstract class BitsStreamGenerator 029 implements RandomGenerator, 030 Serializable { 031 /** Serializable version identifier */ 032 private static final long serialVersionUID = 20130104L; 033 /** Next gaussian. */ 034 private double nextGaussian; 035 036 /** 037 * Creates a new random number generator. 038 */ 039 public BitsStreamGenerator() { 040 nextGaussian = Double.NaN; 041 } 042 043 /** {@inheritDoc} */ 044 public abstract void setSeed(int seed); 045 046 /** {@inheritDoc} */ 047 public abstract void setSeed(int[] seed); 048 049 /** {@inheritDoc} */ 050 public abstract void setSeed(long seed); 051 052 /** Generate next pseudorandom number. 053 * <p>This method is the core generation algorithm. It is used by all the 054 * public generation methods for the various primitive types {@link 055 * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()}, 056 * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()}, 057 * {@link #next(int)} and {@link #nextLong()}.</p> 058 * @param bits number of random bits to produce 059 * @return random bits generated 060 */ 061 protected abstract int next(int bits); 062 063 /** {@inheritDoc} */ 064 public boolean nextBoolean() { 065 return next(1) != 0; 066 } 067 068 /** {@inheritDoc} */ 069 public void nextBytes(byte[] bytes) { 070 int i = 0; 071 final int iEnd = bytes.length - 3; 072 while (i < iEnd) { 073 final int random = next(32); 074 bytes[i] = (byte) (random & 0xff); 075 bytes[i + 1] = (byte) ((random >> 8) & 0xff); 076 bytes[i + 2] = (byte) ((random >> 16) & 0xff); 077 bytes[i + 3] = (byte) ((random >> 24) & 0xff); 078 i += 4; 079 } 080 int random = next(32); 081 while (i < bytes.length) { 082 bytes[i++] = (byte) (random & 0xff); 083 random >>= 8; 084 } 085 } 086 087 /** {@inheritDoc} */ 088 public double nextDouble() { 089 final long high = ((long) next(26)) << 26; 090 final int low = next(26); 091 return (high | low) * 0x1.0p-52d; 092 } 093 094 /** {@inheritDoc} */ 095 public float nextFloat() { 096 return next(23) * 0x1.0p-23f; 097 } 098 099 /** {@inheritDoc} */ 100 public double nextGaussian() { 101 102 final double random; 103 if (Double.isNaN(nextGaussian)) { 104 // generate a new pair of gaussian numbers 105 final double x = nextDouble(); 106 final double y = nextDouble(); 107 final double alpha = 2 * FastMath.PI * x; 108 final double r = FastMath.sqrt(-2 * FastMath.log(y)); 109 random = r * FastMath.cos(alpha); 110 nextGaussian = r * FastMath.sin(alpha); 111 } else { 112 // use the second element of the pair already generated 113 random = nextGaussian; 114 nextGaussian = Double.NaN; 115 } 116 117 return random; 118 119 } 120 121 /** {@inheritDoc} */ 122 public int nextInt() { 123 return next(32); 124 } 125 126 /** 127 * {@inheritDoc} 128 * <p>This default implementation is copied from Apache Harmony 129 * java.util.Random (r929253).</p> 130 * 131 * <p>Implementation notes: <ul> 132 * <li>If n is a power of 2, this method returns 133 * {@code (int) ((n * (long) next(31)) >> 31)}.</li> 134 * 135 * <li>If n is not a power of 2, what is returned is {@code next(31) % n} 136 * with {@code next(31)} values rejected (i.e. regenerated) until a 137 * value that is larger than the remainder of {@code Integer.MAX_VALUE / n} 138 * is generated. Rejection of this initial segment is necessary to ensure 139 * a uniform distribution.</li></ul></p> 140 */ 141 public int nextInt(int n) throws IllegalArgumentException { 142 if (n > 0) { 143 if ((n & -n) == n) { 144 return (int) ((n * (long) next(31)) >> 31); 145 } 146 int bits; 147 int val; 148 do { 149 bits = next(31); 150 val = bits % n; 151 } while (bits - val + (n - 1) < 0); 152 return val; 153 } 154 throw new NotStrictlyPositiveException(n); 155 } 156 157 /** {@inheritDoc} */ 158 public long nextLong() { 159 final long high = ((long) next(32)) << 32; 160 final long low = ((long) next(32)) & 0xffffffffL; 161 return high | low; 162 } 163 164 /** 165 * Returns a pseudorandom, uniformly distributed {@code long} value 166 * between 0 (inclusive) and the specified value (exclusive), drawn from 167 * this random number generator's sequence. 168 * 169 * @param n the bound on the random number to be returned. Must be 170 * positive. 171 * @return a pseudorandom, uniformly distributed {@code long} 172 * value between 0 (inclusive) and n (exclusive). 173 * @throws IllegalArgumentException if n is not positive. 174 */ 175 public long nextLong(long n) throws IllegalArgumentException { 176 if (n > 0) { 177 long bits; 178 long val; 179 do { 180 bits = ((long) next(31)) << 32; 181 bits |= ((long) next(32)) & 0xffffffffL; 182 val = bits % n; 183 } while (bits - val + (n - 1) < 0); 184 return val; 185 } 186 throw new NotStrictlyPositiveException(n); 187 } 188 189 /** 190 * Clears the cache used by the default implementation of 191 * {@link #nextGaussian}. 192 */ 193 public void clear() { 194 nextGaussian = Double.NaN; 195 } 196 197}