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    }