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 <= 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 <= 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 }