--- jsr166/src/main/java/util/SplittableRandom.java 2013/07/11 03:31:26 1.3 +++ jsr166/src/main/java/util/SplittableRandom.java 2013/07/11 23:14:45 1.5 @@ -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) {