Author: sebb
Date: Sat Feb 6 02:36:55 2010
New Revision: 907160
URL: http://svn.apache.org/viewvc?rev=907160&view=rev
Log:
Revert nextInt() and nextLong() to 2.4 behaviour, i.e MAX_VALUE is not included
Rewrite nextLong(long) based on Harmony's implementation of nextInt(int)
Modified:
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/math/JVMRandom.java
Modified:
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/math/JVMRandom.java
URL:
http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/math/JVMRandom.java?rev=907160&r1=907159&r2=907160&view=diff
==============================================================================
---
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/math/JVMRandom.java
(original)
+++
commons/proper/lang/branches/LANG_2_X/src/main/java/org/apache/commons/lang/math/JVMRandom.java
Sat Feb 6 02:36:55 2010
@@ -24,10 +24,15 @@
* <p><code>JVMRandom</code> is a wrapper that supports all possible
* Random methods via the {...@link java.lang.Math#random()} method
* and its system-wide {...@link Random} object.</p>
- *
+ * <p>
* It does this to allow for a Random class in which the seed is
* shared between all members of the class - a better name would
* have been SharedSeedRandom.
+ * <p>
+ * <b>N.B.</b> the current implementation overrides the methods
+ * {...@link Random#nextInt(int)} and {...@link Random#nextLong()}
+ * to produce positive numbers ranging from 0 (inclusive)
+ * to MAX_VALUE (exclusive).
*
* @since 2.0
* @version $Id$
@@ -90,15 +95,14 @@
/**
* <p>Returns the next pseudorandom, uniformly distributed int value
* from the Math.random() sequence.</p>
+ * Identical to <code>nextInt(Integer.MAX_VALUE)</code>
+ * <p>
* <b>N.B. All values are >= 0.<b>
+ * </p>
* @return the random int
*/
public int nextInt() {
- int value = Math.abs(SHARED_RANDOM.nextInt());
- if (value < 0){ // Integer.MIN_VALUE
- value = 0; // ensures 0 occurs equally often as other +ve values
- }
- return value;
+ return nextInt(Integer.MAX_VALUE);
}
/**
@@ -117,15 +121,14 @@
/**
* <p>Returns the next pseudorandom, uniformly distributed long value
* from the Math.random() sequence.</p>
+ * Identical to <code>nextLong(Long.MAX_VALUE)</code>
+ * <p>
* <b>N.B. All values are >= 0.<b>
+ * </p>
* @return the random long
*/
public long nextLong() {
- long value = Math.abs(SHARED_RANDOM.nextLong());
- if (value < 0){ // Long.MIN_VALUE
- value = 0; // ensures 0 occurs equally often as other +ve values
- }
- return value;
+ return nextLong(Long.MAX_VALUE);
}
@@ -144,8 +147,20 @@
"Upper bound for nextInt must be positive"
);
}
- // TODO: check this cannot return 'n'
- return (long)(SHARED_RANDOM.nextDouble() * n);
+ // Code adapted from Harmony Random#nextInt(int)
+ if ((n & -n) == n) { // n is power of 2
+ // dropping lower order bits improves behaviour for low values of n
+ return next63bits() >> 63 // drop all the bits
+ - bitsRequired(n-1); // except the ones we need
+ }
+ // Not a power of two
+ long val;
+ long bits;
+ do { // reject some values to improve distribution
+ bits = next63bits();
+ val = bits % n;
+ } while (bits - val + (n - 1) < 0);
+ return val;
}
/**
@@ -157,6 +172,7 @@
public boolean nextBoolean() {
return SHARED_RANDOM.nextBoolean();
}
+
/**
* <p>Returns the next pseudorandom, uniformly distributed float value
* between <code>0.0</code> and <code>1.0</code> from the Math.random()
@@ -167,6 +183,7 @@
public float nextFloat() {
return SHARED_RANDOM.nextFloat();
}
+
/**
* <p>Synonymous to the Math.random() call.</p>
*
@@ -176,4 +193,32 @@
return SHARED_RANDOM.nextDouble();
}
+ /**
+ * Get the next unsigned random long
+ * @return unsigned random long
+ */
+ private static long next63bits(){
+ // drop the sign bit to leave 63 random bits
+ return SHARED_RANDOM.nextLong() & 0x7fffffffffffffffL;
+ }
+
+ /**
+ * Count the number of bits required to represent a long number.
+ *
+ * @param num long number
+ * @return number of bits required
+ */
+ private static int bitsRequired(long num){
+ // Derived from Hacker's Delight, Figure 5-9
+ long y=num; // for checking right bits
+ int n=0; // number of leading zeros found
+ while(true){
+ // 64 = number of bits in a long
+ if (num < 0) return 64-n; // no leading zeroes left
+ if (y == 0) return n; // no bits left to check
+ n++;
+ num=num << 1; // check leading bits
+ y=y >> 1; // check trailing bits
+ }
+ }
}