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