--- jsr166/src/main/java/util/SplittableRandom.java 2013/07/10 23:42:43 1.2
+++ jsr166/src/main/java/util/SplittableRandom.java 2013/07/11 23:14:45 1.5
@@ -40,7 +40,7 @@ import java.util.stream.DoubleStream;
* A generator of uniform pseudorandom values applicable for use in
* (among other contexts) isolated parallel computations that may
* generate subtasks. Class SplittableRandom supports methods for
- * producing pseudorandom nunmbers of type {@code int}, {@code long},
+ * producing pseudorandom numbers of type {@code int}, {@code long},
* and {@code double} with similar usages as for class
* {@link java.util.Random} but differs in the following ways:
*
@@ -178,6 +178,12 @@ public class SplittableRandom {
private static final long DEFAULT_SEED_GAMMA = 0xBD24B73A95FB84D9L;
/**
+ * The least non-zero value returned by nextDouble(). This value
+ * is scaled by a random value of 53 bits to produce a result.
+ */
+ private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
+
+ /**
* The next seed for default constructors.
*/
private static final AtomicLong defaultSeedGenerator =
@@ -311,12 +317,16 @@ public class SplittableRandom {
* evenly divisible by the range. The loop rejects candidates
* computed from otherwise over-represented values. The
* expected number of iterations under an ideal generator
- * varies from 1 to 2, depending on the bound.
+ * varies from 1 to 2, depending on the bound. The loop itself
+ * takes an unlovable form. Because the first candidate is
+ * already available, we need a break-in-the-middle
+ * construction, which is concisely but cryptically performed
+ * within the while-condition of a body-less for loop.
*
* 4. Otherwise, the range cannot be represented as a positive
- * long. Repeatedly generate unbounded longs until obtaining
- * a candidate meeting constraints (with an expected number of
- * iterations of less than two).
+ * long. The loop repeatedly generates unbounded longs until
+ * obtaining a candidate meeting constraints (with an expected
+ * number of iterations of less than two).
*/
long r = mix64(nextSeed());
@@ -376,8 +386,7 @@ public class SplittableRandom {
* @return a pseudorandom value
*/
final double internalNextDouble(double origin, double bound) {
- long bits = (1023L << 52) | (nextLong() >>> 12);
- double r = Double.longBitsToDouble(bits) - 1.0;
+ double r = (nextLong() >>> 11) * DOUBLE_UNIT;
if (origin < bound) {
r = r * (bound - origin) + origin;
if (r == bound) // correct for rounding
@@ -541,8 +550,7 @@ public class SplittableRandom {
* (inclusive) and {@code 1.0} (exclusive)
*/
public double nextDouble() {
- long bits = (1023L << 52) | (nextLong() >>> 12);
- return Double.longBitsToDouble(bits) - 1.0;
+ return (nextLong() >>> 11) * DOUBLE_UNIT;
}
/**
@@ -869,8 +877,7 @@ public class SplittableRandom {
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
- Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.IMMUTABLE);
+ Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(IntConsumer consumer) {
@@ -924,8 +931,7 @@ public class SplittableRandom {
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
- Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.IMMUTABLE);
+ Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(LongConsumer consumer) {
@@ -980,8 +986,7 @@ public class SplittableRandom {
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
- Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.IMMUTABLE);
+ Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(DoubleConsumer consumer) {