    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    }