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 */
17package org.apache.commons.math.random;
18
19import org.apache.commons.math.exception.NotStrictlyPositiveException;
20import org.apache.commons.math.util.FastMath;
21
22/** Base class for random number generators that generates bits streams.
23
24 * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 août 2010) $
25 * @since 2.0
26
27 */
28public abstract class BitsStreamGenerator implements RandomGenerator {
29
30    /** Next gaussian. */
31    private double nextGaussian;
32
33    /** Creates a new random number generator.
34     */
35    public BitsStreamGenerator() {
36        nextGaussian = Double.NaN;
37    }
38
39    /** {@inheritDoc} */
40    public abstract void setSeed(int seed);
41
42    /** {@inheritDoc} */
43    public abstract void setSeed(int[] seed);
44
45    /** {@inheritDoc} */
46    public abstract void setSeed(long seed);
47
48    /** Generate next pseudorandom number.
49     * <p>This method is the core generation algorithm. It is used by all the
50     * public generation methods for the various primitive types {@link
51     * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()},
52     * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()},
53     * {@link #next(int)} and {@link #nextLong()}.</p>
54     * @param bits number of random bits to produce
55     * @return random bits generated
56     */
57    protected abstract int next(int bits);
58
59    /** {@inheritDoc} */
60    public boolean nextBoolean() {
61        return next(1) != 0;
62    }
63
64    /** {@inheritDoc} */
65    public void nextBytes(byte[] bytes) {
66        int i = 0;
67        final int iEnd = bytes.length - 3;
68        while (i < iEnd) {
69            final int random = next(32);
70            bytes[i]     = (byte) (random & 0xff);
71            bytes[i + 1] = (byte) ((random >>  8) & 0xff);
72            bytes[i + 2] = (byte) ((random >> 16) & 0xff);
73            bytes[i + 3] = (byte) ((random >> 24) & 0xff);
74            i += 4;
75        }
76        int random = next(32);
77        while (i < bytes.length) {
78            bytes[i++] = (byte) (random & 0xff);
79            random     = random >> 8;
80        }
81    }
82
83    /** {@inheritDoc} */
84    public double nextDouble() {
85        final long high = ((long) next(26)) << 26;
86        final int  low  = next(26);
87        return (high | low) * 0x1.0p-52d;
88    }
89
90    /** {@inheritDoc} */
91    public float nextFloat() {
92        return next(23) * 0x1.0p-23f;
93    }
94
95    /** {@inheritDoc} */
96    public double nextGaussian() {
97
98        final double random;
99        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}
154