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    }