    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one
    003     * or more contributor license agreements.  See the NOTICE file
    004     * distributed with this work for additional information
    005     * regarding copyright ownership.  The ASF licenses this file
    006     * to you under the Apache License, Version 2.0 (the
    007     * "License"); you may not use this file except in compliance
    008     * with the License.  You may obtain a copy of the License at
    009     *
    010     * http://www.apache.org/licenses/LICENSE-2.0
    011     *
    012     * Unless required by applicable law or agreed to in writing,
    013     * software distributed under the License is distributed on an
    014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015     * KIND, either express or implied.  See the License for the
    016     * specific language governing permissions and limitations
    017     * under the License.
    018     */
    019    package org.apache.commons.lang.math;
    020
    021    import java.util.Random;
    022
    023    /**
    024     * <p><code>JVMRandom</code> is a wrapper that supports all possible
    025     * Random methods via the {@link java.lang.Math#random()} method
    026     * and its system-wide {@link Random} object.</p>
    027     * <p>
    028     * It does this to allow for a Random class in which the seed is
    029     * shared between all members of the class - a better name would
    030     * have been SharedSeedRandom.
    031     * <p>
    032     * <b>N.B.</b> the current implementation overrides the methods
    033     * {@link Random#nextInt(int)} and {@link Random#nextLong()}
    034     * to produce positive numbers ranging from 0 (inclusive)
    035     * to MAX_VALUE (exclusive).
    036     *
    037     * @since 2.0
    038     * @version $Id: JVMRandom.java 911986 2010-02-19 21:19:05Z niallp $
    039     */
    040    public final class JVMRandom extends Random {
    041
    042        /**
    043         * Required for serialization support.
    044         *
    045         * @see java.io.Serializable
    046         */
    047        private static final long serialVersionUID = 1L;
    048
    049        private static final Random SHARED_RANDOM = new Random();
    050
    051        /**
    052         * Ensures that only the parent constructor can call reseed.
    053         */
    054        private boolean constructed = false;
    055
    056        /**
    057         * Constructs a new instance.
    058         */
    059        public JVMRandom() {
    060            this.constructed = true;
    061        }
    062
    063        /**
    064         * Unsupported in 2.0.
    065         *
    066         * @param seed ignored
    067         * @throws UnsupportedOperationException
    068         */
    069        public synchronized void setSeed(long seed) {
    070            if (this.constructed) {
    071                throw new UnsupportedOperationException();
    072            }
    073        }
    074
    075        /**
    076         * Unsupported in 2.0.
    077         *
    078         * @return Nothing, this method always throws an UnsupportedOperationException.
    079         * @throws UnsupportedOperationException
    080         */
    081        public synchronized double nextGaussian() {
    082            throw new UnsupportedOperationException();
    083        }
    084
    085        /**
    086         * Unsupported in 2.0.
    087         *
    088         * @param byteArray ignored
    089         * @throws UnsupportedOperationException
    090         */
    091        public void nextBytes(byte[] byteArray) {
    092            throw new UnsupportedOperationException();
    093        }
    094
    095        /**
    096         * <p>Returns the next pseudorandom, uniformly distributed int value
    097         * from the Math.random() sequence.</p>
    098         * Identical to <code>nextInt(Integer.MAX_VALUE)</code>
    099         * <p>
    100         * <b>N.B. All values are >= 0.<b>
    101         * </p>
    102         * @return the random int
    103         */
    104        public int nextInt() {
    105            return nextInt(Integer.MAX_VALUE);
    106        }
    107
    108        /**
    109         * <p>Returns a pseudorandom, uniformly distributed int value between
    110         * <code>0</code> (inclusive) and the specified value (exclusive), from
    111         * the Math.random() sequence.</p>
    112         *
    113         * @param n  the specified exclusive max-value
    114         * @return the random int
    115         * @throws IllegalArgumentException when <code>n &lt;= 0</code>
    116         */
    117        public int nextInt(int n) {
    118            return SHARED_RANDOM.nextInt(n);
    119        }
    120
    121        /**
    122         * <p>Returns the next pseudorandom, uniformly distributed long value
    123         * from the Math.random() sequence.</p>
    124         * Identical to <code>nextLong(Long.MAX_VALUE)</code>
    125         * <p>
    126         * <b>N.B. All values are >= 0.<b>
    127         * </p>
    128         * @return the random long
    129         */
    130        public long nextLong() {
    131            return nextLong(Long.MAX_VALUE);
    132        }
    133
    134
    135        /**
    136         * <p>Returns a pseudorandom, uniformly distributed long value between
    137         * <code>0</code> (inclusive) and the specified value (exclusive), from
    138         * the Math.random() sequence.</p>
    139         *
    140         * @param n  the specified exclusive max-value
    141         * @return the random long
    142         * @throws IllegalArgumentException when <code>n &lt;= 0</code>
    143         */
    144        public static long nextLong(long n) {
    145            if (n <= 0) {
    146                throw new IllegalArgumentException(
    147                    "Upper bound for nextInt must be positive"
    148                );
    149            }
    150            // Code adapted from Harmony Random#nextInt(int)
    151            if ((n & -n) == n) { // n is power of 2
    152                // dropping lower order bits improves behaviour for low values of n
    153                return next63bits() >> 63 // drop all the bits
    154                     - bitsRequired(n-1); // except the ones we need
    155            }
    156            // Not a power of two
    157            long val;
    158            long bits;
    159            do { // reject some values to improve distribution
    160                bits = next63bits();
    161                val = bits % n;
    162            } while (bits - val + (n - 1) < 0);
    163            return val;
    164         }
    165
    166        /**
    167         * <p>Returns the next pseudorandom, uniformly distributed boolean value
    168         * from the Math.random() sequence.</p>
    169         *
    170         * @return the random boolean
    171         */
    172        public boolean nextBoolean() {
    173            return SHARED_RANDOM.nextBoolean();
    174        }
    175
    176        /**
    177         * <p>Returns the next pseudorandom, uniformly distributed float value
    178         * between <code>0.0</code> and <code>1.0</code> from the Math.random()
    179         * sequence.</p>
    180         *
    181         * @return the random float
    182         */
    183        public float nextFloat() {
    184            return SHARED_RANDOM.nextFloat();
    185        }
    186
    187        /**
    188         * <p>Synonymous to the Math.random() call.</p>
    189         *
    190         * @return the random double
    191         */
    192        public double nextDouble() {
    193            return SHARED_RANDOM.nextDouble();
    194        }
    195
    196        /**
    197         * Get the next unsigned random long
    198         * @return unsigned random long
    199         */
    200        private static long next63bits(){
    201            // drop the sign bit to leave 63 random bits
    202            return SHARED_RANDOM.nextLong() & 0x7fffffffffffffffL;
    203        }
    204
    205        /**
    206         * Count the number of bits required to represent a long number.
    207         *
    208         * @param num long number
    209         * @return number of bits required
    210         */
    211        private static int bitsRequired(long num){
    212            // Derived from Hacker's Delight, Figure 5-9
    213            long y=num; // for checking right bits
    214            int n=0; // number of leading zeros found
    215            while(true){
    216                // 64 = number of bits in a long
    217                if (num < 0) {
    218                    return 64-n; // no leading zeroes left
    219                }
    220                if (y == 0) {
    221                    return n; // no bits left to check
    222                }
    223                n++;
    224                num=num << 1; // check leading bits
    225                y=y >> 1; // check trailing bits
    226            }
    227        }
    228    }