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.math.random;
018    
019    import org.apache.commons.math.exception.NotStrictlyPositiveException;
020    import org.apache.commons.math.util.FastMath;
021    
022    /** Base class for random number generators that generates bits streams.
023    
024     * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 ao??t 2010) $
025     * @since 2.0
026    
027     */
028    public abstract class BitsStreamGenerator implements RandomGenerator {
029    
030        /** Next gaussian. */
031        private double nextGaussian;
032    
033        /** Creates a new random number generator.
034         */
035        public BitsStreamGenerator() {
036            nextGaussian = Double.NaN;
037        }
038    
039        /** {@inheritDoc} */
040        public abstract void setSeed(int seed);
041    
042        /** {@inheritDoc} */
043        public abstract void setSeed(int[] seed);
044    
045        /** {@inheritDoc} */
046        public abstract void setSeed(long seed);
047    
048        /** Generate next pseudorandom number.
049         * <p>This method is the core generation algorithm. It is used by all the
050         * public generation methods for the various primitive types {@link
051         * #nextBoolean()}, {@link #nextBytes(byte[])}, {@link #nextDouble()},
052         * {@link #nextFloat()}, {@link #nextGaussian()}, {@link #nextInt()},
053         * {@link #next(int)} and {@link #nextLong()}.</p>
054         * @param bits number of random bits to produce
055         * @return random bits generated
056         */
057        protected abstract int next(int bits);
058    
059        /** {@inheritDoc} */
060        public boolean nextBoolean() {
061            return next(1) != 0;
062        }
063    
064        /** {@inheritDoc} */
065        public void nextBytes(byte[] bytes) {
066            int i = 0;
067            final int iEnd = bytes.length - 3;
068            while (i < iEnd) {
069                final int random = next(32);
070                bytes[i]     = (byte) (random & 0xff);
071                bytes[i + 1] = (byte) ((random >>  8) & 0xff);
072                bytes[i + 2] = (byte) ((random >> 16) & 0xff);
073                bytes[i + 3] = (byte) ((random >> 24) & 0xff);
074                i += 4;
075            }
076            int random = next(32);
077            while (i < bytes.length) {
078                bytes[i++] = (byte) (random & 0xff);
079                random     = random >> 8;
080            }
081        }
082    
083        /** {@inheritDoc} */
084        public double nextDouble() {
085            final long high = ((long) next(26)) << 26;
086            final int  low  = next(26);
087            return (high | low) * 0x1.0p-52d;
088        }
089    
090        /** {@inheritDoc} */
091        public float nextFloat() {
092            return next(23) * 0x1.0p-23f;
093        }
094    
095        /** {@inheritDoc} */
096        public double nextGaussian() {
097    
098            final double random;
099            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    }