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     * 
028     * @since 2.0
029     * @version $Id: JVMRandom.java 471626 2006-11-06 04:02:09Z bayard $
030     */
031    public final class JVMRandom extends Random {
032    
033        /**
034         * Required for serialization support.
035         * 
036         * @see java.io.Serializable
037         */
038        private static final long serialVersionUID = 1L;
039    
040        /**
041         * Ensures that only the constructor can call reseed.
042         */
043        private boolean constructed = false;
044    
045        /**
046         * Constructs a new instance.
047         */
048        public JVMRandom() {
049            this.constructed = true;
050        }
051        
052        /**
053         * Unsupported in 2.0.
054         * 
055         * @param seed ignored
056         * @throws UnsupportedOperationException
057         */
058        public synchronized void setSeed(long seed) {
059            if (this.constructed) {
060                throw new UnsupportedOperationException();
061            }
062        }
063    
064        /**
065         * Unsupported in 2.0.
066         * 
067         * @return Nothing, this method always throws an UnsupportedOperationException.
068         * @throws UnsupportedOperationException
069         */
070        public synchronized double nextGaussian() {
071            throw new UnsupportedOperationException();
072        }
073    
074        /**
075         * Unsupported in 2.0.
076         * 
077         * @param byteArray ignored
078         * @throws UnsupportedOperationException
079         */
080        public void nextBytes(byte[] byteArray) {
081            throw new UnsupportedOperationException();
082        }
083    
084        /**
085         * <p>Returns the next pseudorandom, uniformly distributed int value
086         * from the Math.random() sequence.</p>
087         *
088         * @return the random int
089         */
090        public int nextInt() {
091            return nextInt(Integer.MAX_VALUE);
092        }
093        /**
094         * <p>Returns a pseudorandom, uniformly distributed int value between
095         * <code>0</code> (inclusive) and the specified value (exclusive), from
096         * the Math.random() sequence.</p>
097         *
098         * @param n  the specified exclusive max-value
099         * @return the random int
100         * @throws IllegalArgumentException when <code>n &lt;= 0</code>
101         */
102        public int nextInt(int n) {
103            if (n <= 0) {
104                throw new IllegalArgumentException(
105                    "Upper bound for nextInt must be positive"
106                );
107            }
108            // TODO: check this cannot return 'n'
109            return (int)(Math.random() * n);
110        }
111        /**
112         * <p>Returns the next pseudorandom, uniformly distributed long value
113         * from the Math.random() sequence.</p>
114         * @return the random long
115         */
116        public long nextLong() {
117            // possible loss of precision?
118            return nextLong(Long.MAX_VALUE);
119        }
120    
121    
122        /**
123         * <p>Returns a pseudorandom, uniformly distributed long value between
124         * <code>0</code> (inclusive) and the specified value (exclusive), from
125         * the Math.random() sequence.</p>
126         *
127         * @param n  the specified exclusive max-value
128         * @return the random long
129         * @throws IllegalArgumentException when <code>n &lt;= 0</code>
130         */
131        public static long nextLong(long n) {
132            if (n <= 0) {
133                throw new IllegalArgumentException(
134                    "Upper bound for nextInt must be positive"
135                );
136            }
137            // TODO: check this cannot return 'n'
138            return (long)(Math.random() * n);
139         }
140    
141        /**
142         * <p>Returns the next pseudorandom, uniformly distributed boolean value
143         * from the Math.random() sequence.</p>
144         *
145         * @return the random boolean
146         */
147        public boolean nextBoolean() {
148            return Math.random() > 0.5;
149        }
150        /**
151         * <p>Returns the next pseudorandom, uniformly distributed float value
152         * between <code>0.0</code> and <code>1.0</code> from the Math.random()
153         * sequence.</p>
154         *
155         * @return the random float
156         */
157        public float nextFloat() {
158            return (float)Math.random();
159        }
160        /**
161         * <p>Synonymous to the Math.random() call.</p>
162         *
163         * @return the random double
164         */
165        public double nextDouble() {
166            return Math.random();
167        }
168        
169    }