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.math3.random;
18
19 import java.io.Serializable;
20
21 import org.apache.commons.math3.exception.NotStrictlyPositiveException;
22 import org.apache.commons.math3.util.FastMath;
23
24 /** Base class for random number generators that generates bits streams.
25 *
26 * @version $Id: BitsStreamGenerator.java 1454897 2013-03-10 19:02:54Z luc $
27 * @since 2.0
28 */
29 public abstract class BitsStreamGenerator
30 implements RandomGenerator,
31 Serializable {
32 /** Serializable version identifier */
33 private static final long serialVersionUID = 20130104L;
34 /** Next gaussian. */
35 private double nextGaussian;
36
37 /**
38 * Creates a new random number generator.
39 */
40 public BitsStreamGenerator() {
41 nextGaussian = Double.NaN;
42 }
43
44 /** {@inheritDoc} */
45 public abstract void setSeed(int seed);
46
47 /** {@inheritDoc} */
48 public abstract void setSeed(int[] seed);
49
50 /** {@inheritDoc} */
51 public abstract void setSeed(long seed);
52
53 /** Generate next pseudorandom number.
54 * <p>This method is the core generation algorithm. It is used by all the
55 * public generation methods for the various primitive types {@link
56 * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()},
57 * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()},
58 * {@link #next(int)} and {@link #nextLong()}.</p>
59 * @param bits number of random bits to produce
60 * @return random bits generated
61 */
62 protected abstract int next(int bits);
63
64 /** {@inheritDoc} */
65 public boolean nextBoolean() {
66 return next(1) != 0;
67 }
68
69 /** {@inheritDoc} */
70 public void nextBytes(byte[] bytes) {
71 int i = 0;
72 final int iEnd = bytes.length - 3;
73 while (i < iEnd) {
74 final int random = next(32);
75 bytes[i] = (byte) (random & 0xff);
76 bytes[i + 1] = (byte) ((random >> 8) & 0xff);
77 bytes[i + 2] = (byte) ((random >> 16) & 0xff);
78 bytes[i + 3] = (byte) ((random >> 24) & 0xff);
79 i += 4;
80 }
81 int random = next(32);
82 while (i < bytes.length) {
83 bytes[i++] = (byte) (random & 0xff);
84 random = random >> 8;
85 }
86 }
87
88 /** {@inheritDoc} */
89 public double nextDouble() {
90 final long high = ((long) next(26)) << 26;
91 final int low = next(26);
92 return (high | low) * 0x1.0p-52d;
93 }
94
95 /** {@inheritDoc} */
96 public float nextFloat() {
97 return next(23) * 0x1.0p-23f;
98 }
99
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 * Returns a pseudorandom, uniformly distributed <tt>long</tt> value
167 * between 0 (inclusive) and the specified value (exclusive), drawn from
168 * this random number generator's sequence.
169 *
170 * @param n the bound on the random number to be returned. Must be
171 * positive.
172 * @return a pseudorandom, uniformly distributed <tt>long</tt>
173 * value between 0 (inclusive) and n (exclusive).
174 * @throws IllegalArgumentException if n is not positive.
175 */
176 public long nextLong(long n) throws IllegalArgumentException {
177 if (n > 0) {
178 long bits;
179 long val;
180 do {
181 bits = ((long) next(31)) << 32;
182 bits = bits | (((long) next(32)) & 0xffffffffL);
183 val = bits % n;
184 } while (bits - val + (n - 1) < 0);
185 return val;
186 }
187 throw new NotStrictlyPositiveException(n);
188 }
189
190 /**
191 * Clears the cache used by the default implementation of
192 * {@link #nextGaussian}.
193 */
194 public void clear() {
195 nextGaussian = Double.NaN;
196 }
197
198 }