ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
(Generate patch)

Comparing jsr166/src/main/java/util/SplittableRandom.java (file contents):
Revision 1.8 by jsr166, Fri Jul 12 19:45:19 2013 UTC vs.
Revision 1.11 by dl, Tue Jul 16 12:32:05 2013 UTC

# Line 41 | Line 41 | import java.util.stream.DoubleStream;
41   * generate subtasks. Class SplittableRandom supports methods for
42   * producing pseudorandom numbers of type {@code int}, {@code long},
43   * and {@code double} with similar usages as for class
44 < * {@link java.util.Random} but differs in the following ways: <ul>
44 > * {@link java.util.Random} but differs in the following ways:
45 > *
46 > * <ul>
47   *
48   * <li>Series of generated values pass the DieHarder suite testing
49   * independence and uniformity properties of random number generators.
# Line 49 | Line 51 | import java.util.stream.DoubleStream;
51   * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
52   * 3.31.1</a>.) These tests validate only the methods for certain
53   * types and ranges, but similar properties are expected to hold, at
54 < * least approximately, for others as well.  </li>
54 > * least approximately, for others as well. The <em>period</em>
55 > * (length of any series of generated values before it repeats) is at
56 > * least 2<sup>64</sup>. </li>
57   *
58   * <li> Method {@link #split} constructs and returns a new
59   * SplittableRandom instance that shares no mutable state with the
# Line 154 | Line 158 | public class SplittableRandom {
158       * SplittableRandom. Unlike other cases, this split must be
159       * performed in a thread-safe manner. We use
160       * AtomicLong.compareAndSet as the (typically) most efficient
161 <     * mechanism. To bootstrap, we start off using System.nanotime(),
162 <     * and update using another "genuinely random" constant
163 <     * DEFAULT_SEED_GAMMA. The default constructor uses GAMMA_GAMMA,
164 <     * not 0, for its splitSeed argument (addGammaModGeorge(0,
165 <     * GAMMA_GAMMA) == GAMMA_GAMMA) to reflect that each is split from
166 <     * this root generator, even though the root is not explicitly
167 <     * represented as a SplittableRandom.
161 >     * mechanism. To bootstrap, we start off using a function of the
162 >     * current System time as seed, and update using another
163 >     * "genuinely random" constant DEFAULT_SEED_GAMMA. The default
164 >     * constructor uses GAMMA_GAMMA, not 0, for its splitSeed argument
165 >     * (addGammaModGeorge(0, GAMMA_GAMMA) == GAMMA_GAMMA) to reflect
166 >     * that each is split from this root generator, even though the
167 >     * root is not explicitly represented as a SplittableRandom.  When
168 >     * establishing the initial seed, we use both
169 >     * System.currentTimeMillis and System.nanoTime(), to avoid
170 >     * regularities that may occur if using either alone.
171       */
172  
173      /**
# Line 178 | Line 185 | public class SplittableRandom {
185      private static final long DEFAULT_SEED_GAMMA = 0xBD24B73A95FB84D9L;
186  
187      /**
188 +     * The value 13 with 64bit sign bit set. Used in the signed
189 +     * comparison in addGammaModGeorge.
190 +     */
191 +    private static final long BOTTOM13 = 0x800000000000000DL;
192 +
193 +    /**
194       * The least non-zero value returned by nextDouble(). This value
195       * is scaled by a random value of 53 bits to produce a result.
196       */
# Line 187 | Line 200 | public class SplittableRandom {
200       * The next seed for default constructors.
201       */
202      private static final AtomicLong defaultSeedGenerator =
203 <        new AtomicLong(System.nanoTime());
203 >        new AtomicLong(mix64(System.currentTimeMillis()) ^
204 >                       mix64(System.nanoTime()));
205  
206      /**
207       * The seed, updated only via method nextSeed.
# Line 215 | Line 229 | public class SplittableRandom {
229       * George < 2^64; thus we need only a conditional, not a loop,
230       * to be sure of getting a representable value.
231       *
232 <     * @param s a seed value
232 >     * Because Java comparison operators are signed, we implement this
233 >     * by conceptually offsetting seed values downwards by 2^63, so
234 >     * 0..13 is represented as Long.MIN_VALUE..BOTTOM13.
235 >     *
236 >     * @param s a seed value, viewed as a signed long
237       * @param g a gamma value, 13 <= g (as unsigned)
238       */
239      private static long addGammaModGeorge(long s, long g) {
240          long p = s + g;
241 <        if (Long.compareUnsigned(p, g) >= 0)
224 <            return p;
225 <        long q = p - 13L;
226 <        return (Long.compareUnsigned(p, 13L) >= 0) ? q : (q + g);
241 >        return (p >= s) ? p : ((p >= BOTTOM13) ? p  : p + g) - 13L;
242      }
243  
244      /**
# Line 262 | Line 277 | public class SplittableRandom {
277          do { // ensure gamma >= 13, considered as an unsigned integer
278              s = addGammaModGeorge(s, GAMMA_GAMMA);
279              g = mix64(s);
280 <        } while (Long.compareUnsigned(g, 13L) < 0);
280 >        } while (g >= 0L && g < 13L);
281          this.gamma = g;
282          this.nextSplit = s;
283      }
# Line 401 | Line 416 | public class SplittableRandom {
416      /**
417       * Creates a new SplittableRandom instance using the specified
418       * initial seed. SplittableRandom instances created with the same
419 <     * seed generate identical sequences of values.
419 >     * seed in the same program generate identical sequences of values.
420       *
421       * @param seed the initial seed
422       */
# Line 453 | Line 468 | public class SplittableRandom {
468       * @param bound the bound on the random number to be returned.  Must be
469       *        positive.
470       * @return a pseudorandom {@code int} value between zero
471 <     *         (inclusive) and the bound (exclusive).
471 >     *         (inclusive) and the bound (exclusive)
472       * @throws IllegalArgumentException if the bound is less than zero
473       */
474      public int nextInt(int bound) {
# Line 480 | Line 495 | public class SplittableRandom {
495       * @param origin the least value returned
496       * @param bound the upper bound (exclusive)
497       * @return a pseudorandom {@code int} value between the origin
498 <     *         (inclusive) and the bound (exclusive).
498 >     *         (inclusive) and the bound (exclusive)
499       * @throws IllegalArgumentException if {@code origin} is greater than
500       *         or equal to {@code bound}
501       */
# Line 506 | Line 521 | public class SplittableRandom {
521       * @param bound the bound on the random number to be returned.  Must be
522       *        positive.
523       * @return a pseudorandom {@code long} value between zero
524 <     *         (inclusive) and the bound (exclusive).
524 >     *         (inclusive) and the bound (exclusive)
525       * @throws IllegalArgumentException if {@code bound} is less than zero
526       */
527      public long nextLong(long bound) {
# Line 533 | Line 548 | public class SplittableRandom {
548       * @param origin the least value returned
549       * @param bound the upper bound (exclusive)
550       * @return a pseudorandom {@code long} value between the origin
551 <     *         (inclusive) and the bound (exclusive).
551 >     *         (inclusive) and the bound (exclusive)
552       * @throws IllegalArgumentException if {@code origin} is greater than
553       *         or equal to {@code bound}
554       */
# Line 551 | Line 566 | public class SplittableRandom {
566       * (inclusive) and one (exclusive)
567       */
568      public double nextDouble() {
569 <        return (nextLong() >>> 11) * DOUBLE_UNIT;
569 >        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
570      }
571  
572      /**
# Line 561 | Line 576 | public class SplittableRandom {
576       * @param bound the bound on the random number to be returned.  Must be
577       *        positive.
578       * @return a pseudorandom {@code double} value between zero
579 <     *         (inclusive) and the bound (exclusive).
579 >     *         (inclusive) and the bound (exclusive)
580       * @throws IllegalArgumentException if {@code bound} is less than zero
581       */
582      public double nextDouble(double bound) {
583          if (!(bound > 0.0))
584              throw new IllegalArgumentException("bound must be positive");
585 <        double result = nextDouble() * bound;
585 >        double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
586          return (result < bound) ?  result : // correct for rounding
587              Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
588      }
# Line 579 | Line 594 | public class SplittableRandom {
594       * @param origin the least value returned
595       * @param bound the upper bound
596       * @return a pseudorandom {@code double} value between the origin
597 <     *         (inclusive) and the bound (exclusive).
597 >     *         (inclusive) and the bound (exclusive)
598       * @throws IllegalArgumentException if {@code origin} is greater than
599       *         or equal to {@code bound}
600       */
# Line 589 | Line 604 | public class SplittableRandom {
604          return internalNextDouble(origin, bound);
605      }
606  
607 +    /**
608 +     * Returns a pseudorandom {@code boolean} value.
609 +     *
610 +     * @return a pseudorandom {@code boolean} value
611 +     */
612 +    public boolean nextBoolean() {
613 +        return mix32(nextSeed()) < 0;
614 +    }
615 +
616      // stream methods, coded in a way intended to better isolate for
617      // maintenance purposes the small differences across forms.
618  
# Line 612 | Line 636 | public class SplittableRandom {
636  
637      /**
638       * Returns an effectively unlimited stream of pseudorandom {@code int}
639 <     * values
639 >     * values.
640       *
641       * @implNote This method is implemented to be equivalent to {@code
642       * ints(Long.MAX_VALUE)}.
# Line 635 | Line 659 | public class SplittableRandom {
659       * @param randomNumberOrigin the origin of each random value
660       * @param randomNumberBound the bound of each random value
661       * @return a stream of pseudorandom {@code int} values,
662 <     *         each with the given origin and bound.
662 >     *         each with the given origin and bound
663       * @throws IllegalArgumentException if {@code streamSize} is
664       *         less than zero, or {@code randomNumberOrigin}
665       *         is greater than or equal to {@code randomNumberBound}
# Line 662 | Line 686 | public class SplittableRandom {
686       * @param randomNumberOrigin the origin of each random value
687       * @param randomNumberBound the bound of each random value
688       * @return a stream of pseudorandom {@code int} values,
689 <     *         each with the given origin and bound.
689 >     *         each with the given origin and bound
690       * @throws IllegalArgumentException if {@code randomNumberOrigin}
691       *         is greater than or equal to {@code randomNumberBound}
692       */
# Line 718 | Line 742 | public class SplittableRandom {
742       * @param randomNumberOrigin the origin of each random value
743       * @param randomNumberBound the bound of each random value
744       * @return a stream of pseudorandom {@code long} values,
745 <     *         each with the given origin and bound.
745 >     *         each with the given origin and bound
746       * @throws IllegalArgumentException if {@code streamSize} is
747       *         less than zero, or {@code randomNumberOrigin}
748       *         is greater than or equal to {@code randomNumberBound}
# Line 745 | Line 769 | public class SplittableRandom {
769       * @param randomNumberOrigin the origin of each random value
770       * @param randomNumberBound the bound of each random value
771       * @return a stream of pseudorandom {@code long} values,
772 <     *         each with the given origin and bound.
772 >     *         each with the given origin and bound
773       * @throws IllegalArgumentException if {@code randomNumberOrigin}
774       *         is greater than or equal to {@code randomNumberBound}
775       */
# Line 803 | Line 827 | public class SplittableRandom {
827       * @param randomNumberOrigin the origin of each random value
828       * @param randomNumberBound the bound of each random value
829       * @return a stream of pseudorandom {@code double} values,
830 <     * each with the given origin and bound.
830 >     * each with the given origin and bound
831       * @throws IllegalArgumentException if {@code streamSize} is
832 <     * less than zero.
832 >     * less than zero
833       * @throws IllegalArgumentException if {@code randomNumberOrigin}
834       *         is greater than or equal to {@code randomNumberBound}
835       */
# Line 831 | Line 855 | public class SplittableRandom {
855       * @param randomNumberOrigin the origin of each random value
856       * @param randomNumberBound the bound of each random value
857       * @return a stream of pseudorandom {@code double} values,
858 <     * each with the given origin and bound.
858 >     * each with the given origin and bound
859       * @throws IllegalArgumentException if {@code randomNumberOrigin}
860       *         is greater than or equal to {@code randomNumberBound}
861       */
# Line 852 | Line 876 | public class SplittableRandom {
876       * approach. The long and double versions of this class are
877       * identical except for types.
878       */
879 <    static class RandomIntsSpliterator implements Spliterator.OfInt {
879 >    static final class RandomIntsSpliterator implements Spliterator.OfInt {
880          final SplittableRandom rng;
881          long index;
882          final long fence;
# Line 906 | Line 930 | public class SplittableRandom {
930      /**
931       * Spliterator for long streams.
932       */
933 <    static class RandomLongsSpliterator implements Spliterator.OfLong {
933 >    static final class RandomLongsSpliterator implements Spliterator.OfLong {
934          final SplittableRandom rng;
935          long index;
936          final long fence;
# Line 961 | Line 985 | public class SplittableRandom {
985      /**
986       * Spliterator for double streams.
987       */
988 <    static class RandomDoublesSpliterator implements Spliterator.OfDouble {
988 >    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
989          final SplittableRandom rng;
990          long index;
991          final long fence;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines