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.3 by jsr166, Thu Jul 11 03:31:26 2013 UTC vs.
Revision 1.11 by dl, Tue Jul 16 12:32:05 2013 UTC

# Line 35 | Line 35 | import java.util.stream.IntStream;
35   import java.util.stream.LongStream;
36   import java.util.stream.DoubleStream;
37  
38
38   /**
39   * A generator of uniform pseudorandom values applicable for use in
40   * (among other contexts) isolated parallel computations that may
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 50 | 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
60 < * current instance. However, with very high probability, the set of
61 < * values collectively generated by the two objects has the same
60 > * current instance. However, with very high probability, the
61 > * values collectively generated by the two objects have the same
62   * statistical properties as if the same quantity of values were
63   * generated by a single thread using a single {@code
64   * SplittableRandom} object.  </li>
# Line 97 | Line 100 | public class SplittableRandom {
100       * Random-Number Generation for Dynamic-Multithreading Platforms",
101       * PPoPP 2012, but improves and extends it in several ways.
102       *
103 <     * The primary update step is simply to add a constant ("gamma")
104 <     * to the current seed, modulo a prime ("George"). However, the
105 <     * nextLong and nextInt methods do not return this value, but
106 <     * instead the results of bit-mixing transformations that produce
107 <     * more uniformly distributed sequences.
103 >     * The primary update step (see method nextSeed()) is simply to
104 >     * add a constant ("gamma") to the current seed, modulo a prime
105 >     * ("George"). However, the nextLong and nextInt methods do not
106 >     * return this value, but instead the results of bit-mixing
107 >     * transformations that produce more uniformly distributed
108 >     * sequences.
109       *
110       * "George" is the otherwise nameless (because it cannot be
111       * represented) prime number 2^64+13. Using a prime number larger
# 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 +     */
197 +    private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
198 +
199 +    /**
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 200 | Line 220 | public class SplittableRandom {
220      private final long nextSplit;
221  
222      /**
203     * Internal constructor used by all other constructors and by
204     * method split. Establishes the initial seed for this instance,
205     * and uses the given splitSeed to establish gamma, as well as the
206     * nextSplit to use by this instance.
207     */
208    private SplittableRandom(long seed, long splitSeed) {
209        this.seed = seed;
210        long s = splitSeed, g;
211        do { // ensure gamma >= 13, considered as an unsigned integer
212            s = addGammaModGeorge(s, GAMMA_GAMMA);
213            g = mix64(s);
214        } while (Long.compareUnsigned(g, 13L) < 0);
215        this.gamma = g;
216        this.nextSplit = s;
217    }
218
219    /**
223       * Adds the given gamma value, g, to the given seed value s, mod
224       * George (2^64+13). We regard s and g as unsigned values
225       * (ranging from 0 to 2^64-1). We add g to s either once or twice
# Line 226 | 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)
235 <            return p;
236 <        long q = p - 13L;
237 <        return (Long.compareUnsigned(p, 13L) >= 0) ? q : (q + g);
238 <    }
239 <
240 <    /**
241 <     * Updates in-place and returns seed.
242 <     * See above for explanation.
243 <     */
244 <    private long nextSeed() {
245 <        return seed = addGammaModGeorge(seed, gamma);
241 >        return (p >= s) ? p : ((p >= BOTTOM13) ? p  : p + g) - 13L;
242      }
243  
244      /**
# Line 269 | Line 265 | public class SplittableRandom {
265      }
266  
267      /**
268 <     * Atomically updates and returns next seed for default constructor
268 >     * Internal constructor used by all other constructors and by
269 >     * method split. Establishes the initial seed for this instance,
270 >     * and uses the given splitSeed to establish gamma, as well as the
271 >     * nextSplit to use by this instance. The loop to skip ineligible
272 >     * gammas very rarely iterates, and does so at most 13 times.
273 >     */
274 >    private SplittableRandom(long seed, long splitSeed) {
275 >        this.seed = seed;
276 >        long s = splitSeed, g;
277 >        do { // ensure gamma >= 13, considered as an unsigned integer
278 >            s = addGammaModGeorge(s, GAMMA_GAMMA);
279 >            g = mix64(s);
280 >        } while (g >= 0L && g < 13L);
281 >        this.gamma = g;
282 >        this.nextSplit = s;
283 >    }
284 >
285 >    /**
286 >     * Updates in-place and returns seed.
287 >     * See above for explanation.
288 >     */
289 >    private long nextSeed() {
290 >        return seed = addGammaModGeorge(seed, gamma);
291 >    }
292 >
293 >    /**
294 >     * Atomically updates and returns next seed for default constructor.
295       */
296      private static long nextDefaultSeed() {
297          long oldSeed, newSeed;
# Line 311 | Line 333 | public class SplittableRandom {
333           * evenly divisible by the range. The loop rejects candidates
334           * computed from otherwise over-represented values.  The
335           * expected number of iterations under an ideal generator
336 <         * varies from 1 to 2, depending on the bound.
336 >         * varies from 1 to 2, depending on the bound. The loop itself
337 >         * takes an unlovable form. Because the first candidate is
338 >         * already available, we need a break-in-the-middle
339 >         * construction, which is concisely but cryptically performed
340 >         * within the while-condition of a body-less for loop.
341           *
342           * 4. Otherwise, the range cannot be represented as a positive
343 <         * long.  Repeatedly generate unbounded longs until obtaining
344 <         * a candidate meeting constraints (with an expected number of
345 <         * iterations of less than two).
343 >         * long.  The loop repeatedly generates unbounded longs until
344 >         * obtaining a candidate meeting constraints (with an expected
345 >         * number of iterations of less than two).
346           */
347  
348          long r = mix64(nextSeed());
349          if (origin < bound) {
350              long n = bound - origin, m = n - 1;
351 <            if ((n & m) == 0L) // power of two
351 >            if ((n & m) == 0L)  // power of two
352                  r = (r & m) + origin;
353 <            else if (n > 0) { // reject over-represented candidates
353 >            else if (n > 0L) {  // reject over-represented candidates
354                  for (long u = r >>> 1;            // ensure nonnegative
355 <                     u + m - (r = u % n) < 0L;    // reject
355 >                     u + m - (r = u % n) < 0L;    // rejection check
356                       u = mix64(nextSeed()) >>> 1) // retry
357                      ;
358                  r += origin;
359              }
360 <            else {             // range not representable as long
360 >            else {              // range not representable as long
361                  while (r < origin || r >= bound)
362                      r = mix64(nextSeed());
363              }
# Line 355 | Line 381 | public class SplittableRandom {
381                  r = (r & m) + origin;
382              else if (n > 0) {
383                  for (int u = r >>> 1;
384 <                     u + m - (r = u % n) < 0L;
384 >                     u + m - (r = u % n) < 0;
385                       u = mix32(nextSeed()) >>> 1)
386                      ;
387                  r += origin;
# Line 376 | Line 402 | public class SplittableRandom {
402       * @return a pseudorandom value
403       */
404      final double internalNextDouble(double origin, double bound) {
405 <        long bits = (1023L << 52) | (nextLong() >>> 12);
380 <        double r = Double.longBitsToDouble(bits) - 1.0;
405 >        double r = (nextLong() >>> 11) * DOUBLE_UNIT;
406          if (origin < bound) {
407              r = r * (bound - origin) + origin;
408 <            if (r == bound) // correct for rounding
408 >            if (r >= bound) // correct for rounding
409                  r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
410          }
411          return r;
# Line 389 | Line 414 | public class SplittableRandom {
414      /* ---------------- public methods ---------------- */
415  
416      /**
417 <     * Creates a new SplittableRandom instance using the given initial
418 <     * seed. Two SplittableRandom instances created with the same seed
419 <     * generate identical sequences of values.
417 >     * Creates a new SplittableRandom instance using the specified
418 >     * initial seed. SplittableRandom instances created with the same
419 >     * seed in the same program generate identical sequences of values.
420       *
421       * @param seed the initial seed
422       */
# Line 430 | Line 455 | public class SplittableRandom {
455      /**
456       * Returns a pseudorandom {@code int} value.
457       *
458 <     * @return a pseudorandom value
458 >     * @return a pseudorandom {@code int} value
459       */
460      public int nextInt() {
461          return mix32(nextSeed());
462      }
463  
464      /**
465 <     * Returns a pseudorandom {@code int} value between 0 (inclusive)
465 >     * Returns a pseudorandom {@code int} value between zero (inclusive)
466       * and the specified bound (exclusive).
467       *
468       * @param bound the bound on the random number to be returned.  Must be
469       *        positive.
470 <     * @return a pseudorandom {@code int} value between {@code 0}
471 <     *         (inclusive) and the bound (exclusive).
472 <     * @exception IllegalArgumentException if the bound is not positive
470 >     * @return a pseudorandom {@code int} value between zero
471 >     *         (inclusive) and the bound (exclusive)
472 >     * @throws IllegalArgumentException if the bound is less than zero
473       */
474      public int nextInt(int bound) {
475          if (bound <= 0)
# Line 456 | Line 481 | public class SplittableRandom {
481              r &= m;
482          else { // reject over-represented candidates
483              for (int u = r >>> 1;
484 <                 u + m - (r = u % bound) < 0L;
484 >                 u + m - (r = u % bound) < 0;
485                   u = mix32(nextSeed()) >>> 1)
486                  ;
487          }
# Line 470 | 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).
499 <     * @exception IllegalArgumentException if {@code origin} is greater than
498 >     *         (inclusive) and the bound (exclusive)
499 >     * @throws IllegalArgumentException if {@code origin} is greater than
500       *         or equal to {@code bound}
501       */
502      public int nextInt(int origin, int bound) {
# Line 483 | Line 508 | public class SplittableRandom {
508      /**
509       * Returns a pseudorandom {@code long} value.
510       *
511 <     * @return a pseudorandom value
511 >     * @return a pseudorandom {@code long} value
512       */
513      public long nextLong() {
514          return mix64(nextSeed());
515      }
516  
517      /**
518 <     * Returns a pseudorandom {@code long} value between 0 (inclusive)
518 >     * Returns a pseudorandom {@code long} value between zero (inclusive)
519       * and the specified bound (exclusive).
520       *
521       * @param bound the bound on the random number to be returned.  Must be
522       *        positive.
523 <     * @return a pseudorandom {@code long} value between {@code 0}
524 <     *         (inclusive) and the bound (exclusive).
525 <     * @exception IllegalArgumentException if the bound is not positive
523 >     * @return a pseudorandom {@code long} value between zero
524 >     *         (inclusive) and the bound (exclusive)
525 >     * @throws IllegalArgumentException if {@code bound} is less than zero
526       */
527      public long nextLong(long bound) {
528          if (bound <= 0)
# Line 523 | 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).
552 <     * @exception IllegalArgumentException if {@code origin} is greater than
551 >     *         (inclusive) and the bound (exclusive)
552 >     * @throws IllegalArgumentException if {@code origin} is greater than
553       *         or equal to {@code bound}
554       */
555      public long nextLong(long origin, long bound) {
# Line 534 | Line 559 | public class SplittableRandom {
559      }
560  
561      /**
562 <     * Returns a pseudorandom {@code double} value between {@code 0.0}
563 <     * (inclusive) and {@code 1.0} (exclusive).
562 >     * Returns a pseudorandom {@code double} value between zero
563 >     * (inclusive) and one (exclusive).
564       *
565 <     * @return a pseudorandom value between {@code 0.0}
566 <     * (inclusive) and {@code 1.0} (exclusive)
565 >     * @return a pseudorandom {@code double} value between zero
566 >     * (inclusive) and one (exclusive)
567       */
568      public double nextDouble() {
569 <        long bits = (1023L << 52) | (nextLong() >>> 12);
545 <        return Double.longBitsToDouble(bits) - 1.0;
569 >        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
570      }
571  
572      /**
# Line 551 | Line 575 | public class SplittableRandom {
575       *
576       * @param bound the bound on the random number to be returned.  Must be
577       *        positive.
578 <     * @return a pseudorandom {@code double} value between {@code 0.0}
579 <     *         (inclusive) and the bound (exclusive).
580 <     * @throws IllegalArgumentException if {@code bound} is not positive
578 >     * @return a pseudorandom {@code double} value between zero
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)
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      }
589  
590      /**
591 <     * Returns a pseudorandom {@code double} value between the given
591 >     * Returns a pseudorandom {@code double} value between the specified
592       * origin (inclusive) and bound (exclusive).
593       *
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       */
601      public double nextDouble(double origin, double bound) {
602 <        if (origin >= bound)
602 >        if (!(origin < bound))
603              throw new IllegalArgumentException("bound must be greater than origin");
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  
619      /**
620 <     * Returns a stream with the given {@code streamSize} number of
620 >     * Returns a stream producing the given {@code streamSize} number of
621       * pseudorandom {@code int} values.
622       *
623       * @param streamSize the number of values to generate
624       * @return a stream of pseudorandom {@code int} values
625       * @throws IllegalArgumentException if {@code streamSize} is
626 <     * less than zero
626 >     *         less than zero
627       */
628      public IntStream ints(long streamSize) {
629          if (streamSize < 0L)
# Line 603 | 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 618 | Line 651 | public class SplittableRandom {
651      }
652  
653      /**
654 <     * Returns a stream with the given {@code streamSize} number of
654 >     * Returns a stream producing the given {@code streamSize} number of
655       * pseudorandom {@code int} values, each conforming to the given
656       * origin and bound.
657       *
# Line 626 | 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.
632 <     * @throws IllegalArgumentException if {@code randomNumberOrigin}
664 >     *         less than zero, or {@code randomNumberOrigin}
665       *         is greater than or equal to {@code randomNumberBound}
666       */
667      public IntStream ints(long streamSize, int randomNumberOrigin,
# Line 654 | 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 668 | Line 700 | public class SplittableRandom {
700      }
701  
702      /**
703 <     * Returns a stream with the given {@code streamSize} number of
703 >     * Returns a stream producing the given {@code streamSize} number of
704       * pseudorandom {@code long} values.
705       *
706       * @param streamSize the number of values to generate
707 <     * @return a stream of {@code long} values
707 >     * @return a stream of pseudorandom {@code long} values
708       * @throws IllegalArgumentException if {@code streamSize} is
709 <     * less than zero
709 >     *         less than zero
710       */
711      public LongStream longs(long streamSize) {
712          if (streamSize < 0L)
# Line 702 | Line 734 | public class SplittableRandom {
734      }
735  
736      /**
737 <     * Returns a stream with the given {@code streamSize} number of
737 >     * Returns a stream producing the given {@code streamSize} number of
738       * pseudorandom {@code long} values, each conforming to the
739       * given origin and bound.
740       *
# Line 710 | 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.
716 <     * @throws IllegalArgumentException if {@code randomNumberOrigin}
747 >     *         less than zero, or {@code randomNumberOrigin}
748       *         is greater than or equal to {@code randomNumberBound}
749       */
750      public LongStream longs(long streamSize, long randomNumberOrigin,
# Line 738 | 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 752 | Line 783 | public class SplittableRandom {
783      }
784  
785      /**
786 <     * Returns a stream with the given {@code streamSize} number of
787 <     * pseudorandom {@code double} values, each between {@code 0.0}
788 <     * (inclusive) and {@code 1.0} (exclusive).
786 >     * Returns a stream producing the given {@code streamSize} number of
787 >     * pseudorandom {@code double} values, each between zero
788 >     * (inclusive) and one (exclusive).
789       *
790       * @param streamSize the number of values to generate
791       * @return a stream of {@code double} values
792       * @throws IllegalArgumentException if {@code streamSize} is
793 <     * less than zero
793 >     *         less than zero
794       */
795      public DoubleStream doubles(long streamSize) {
796          if (streamSize < 0L)
# Line 772 | Line 803 | public class SplittableRandom {
803  
804      /**
805       * Returns an effectively unlimited stream of pseudorandom {@code
806 <     * double} values, each between {@code 0.0} (inclusive) and {@code
807 <     * 1.0} (exclusive).
806 >     * double} values, each between zero (inclusive) and one
807 >     * (exclusive).
808       *
809       * @implNote This method is implemented to be equivalent to {@code
810       * doubles(Long.MAX_VALUE)}.
# Line 788 | Line 819 | public class SplittableRandom {
819      }
820  
821      /**
822 <     * Returns a stream with the given {@code streamSize} number of
822 >     * Returns a stream producing the given {@code streamSize} number of
823       * pseudorandom {@code double} values, each conforming to the
824       * given origin and bound.
825       *
# Line 796 | 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 806 | Line 837 | public class SplittableRandom {
837                                  double randomNumberBound) {
838          if (streamSize < 0L)
839              throw new IllegalArgumentException("negative Stream size");
840 <        if (randomNumberOrigin >= randomNumberBound)
840 >        if (!(randomNumberOrigin < randomNumberBound))
841              throw new IllegalArgumentException("bound must be greater than origin");
842          return StreamSupport.doubleStream
843              (new RandomDoublesSpliterator
# Line 824 | 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       */
862      public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
863 <        if (randomNumberOrigin >= randomNumberBound)
863 >        if (!(randomNumberOrigin < randomNumberBound))
864              throw new IllegalArgumentException("bound must be greater than origin");
865          return StreamSupport.doubleStream
866              (new RandomDoublesSpliterator
# Line 839 | Line 870 | public class SplittableRandom {
870  
871      /**
872       * Spliterator for int streams.  We multiplex the four int
873 <     * versions into one class by treating and bound < origin as
873 >     * versions into one class by treating a bound less than origin as
874       * unbounded, and also by treating "infinite" as equivalent to
875       * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
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 869 | Line 900 | public class SplittableRandom {
900  
901          public int characteristics() {
902              return (Spliterator.SIZED | Spliterator.SUBSIZED |
903 <                    Spliterator.ORDERED | Spliterator.NONNULL |
873 <                    Spliterator.IMMUTABLE);
903 >                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
904          }
905  
906          public boolean tryAdvance(IntConsumer consumer) {
# Line 900 | 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 924 | Line 954 | public class SplittableRandom {
954  
955          public int characteristics() {
956              return (Spliterator.SIZED | Spliterator.SUBSIZED |
957 <                    Spliterator.ORDERED | Spliterator.NONNULL |
928 <                    Spliterator.IMMUTABLE);
957 >                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
958          }
959  
960          public boolean tryAdvance(LongConsumer consumer) {
# Line 956 | 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;
# Line 980 | Line 1009 | public class SplittableRandom {
1009  
1010          public int characteristics() {
1011              return (Spliterator.SIZED | Spliterator.SUBSIZED |
1012 <                    Spliterator.ORDERED | Spliterator.NONNULL |
984 <                    Spliterator.IMMUTABLE);
1012 >                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
1013          }
1014  
1015          public boolean tryAdvance(DoubleConsumer consumer) {
# Line 1009 | Line 1037 | public class SplittableRandom {
1037      }
1038  
1039   }
1012

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines