ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.11
Committed: Tue Jul 16 12:32:05 2013 UTC (10 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.10: +43 -21 lines
Log Message:
Incorporate suggestions

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4     *
5     * This code is free software; you can redistribute it and/or modify it
6     * under the terms of the GNU General Public License version 2 only, as
7     * published by the Free Software Foundation. Oracle designates this
8     * particular file as subject to the "Classpath" exception as provided
9     * by Oracle in the LICENSE file that accompanied this code.
10     *
11     * This code is distributed in the hope that it will be useful, but WITHOUT
12     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13     * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14     * version 2 for more details (a copy is included in the LICENSE file that
15     * accompanied this code).
16     *
17     * You should have received a copy of the GNU General Public License version
18     * 2 along with this work; if not, write to the Free Software Foundation,
19     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20     *
21     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22     * or visit www.oracle.com if you need additional information or have any
23     * questions.
24     */
25    
26     package java.util;
27    
28     import java.util.concurrent.atomic.AtomicLong;
29     import java.util.Spliterator;
30     import java.util.function.IntConsumer;
31     import java.util.function.LongConsumer;
32     import java.util.function.DoubleConsumer;
33     import java.util.stream.StreamSupport;
34     import java.util.stream.IntStream;
35     import java.util.stream.LongStream;
36     import java.util.stream.DoubleStream;
37    
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 jsr166 1.3 * producing pseudorandom numbers of type {@code int}, {@code long},
43 dl 1.1 * and {@code double} with similar usages as for class
44 jsr166 1.9 * {@link java.util.Random} but differs in the following ways:
45     *
46     * <ul>
47 dl 1.1 *
48     * <li>Series of generated values pass the DieHarder suite testing
49     * independence and uniformity properties of random number generators.
50     * (Most recently validated with <a
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 dl 1.11 * 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 dl 1.1 *
58     * <li> Method {@link #split} constructs and returns a new
59     * SplittableRandom instance that shares no mutable state with the
60 dl 1.7 * current instance. However, with very high probability, the
61     * values collectively generated by the two objects have the same
62 dl 1.1 * statistical properties as if the same quantity of values were
63     * generated by a single thread using a single {@code
64     * SplittableRandom} object. </li>
65     *
66     * <li>Instances of SplittableRandom are <em>not</em> thread-safe.
67     * They are designed to be split, not shared, across threads. For
68     * example, a {@link java.util.concurrent.ForkJoinTask
69     * fork/join-style} computation using random numbers might include a
70     * construction of the form {@code new
71     * Subtask(aSplittableRandom.split()).fork()}.
72     *
73     * <li>This class provides additional methods for generating random
74     * streams, that employ the above techniques when used in {@code
75     * stream.parallel()} mode.</li>
76     *
77     * </ul>
78     *
79     * @author Guy Steele
80 dl 1.2 * @author Doug Lea
81 dl 1.1 * @since 1.8
82     */
83     public class SplittableRandom {
84    
85     /*
86     * File organization: First the non-public methods that constitute
87     * the main algorithm, then the main public methods, followed by
88     * some custom spliterator classes needed for stream methods.
89     *
90     * Credits: Primary algorithm and code by Guy Steele. Stream
91     * support methods by Doug Lea. Documentation jointly produced
92     * with additional help from Brian Goetz.
93     */
94    
95     /*
96     * Implementation Overview.
97     *
98     * This algorithm was inspired by the "DotMix" algorithm by
99     * Leiserson, Schardl, and Sukha "Deterministic Parallel
100     * Random-Number Generation for Dynamic-Multithreading Platforms",
101     * PPoPP 2012, but improves and extends it in several ways.
102     *
103 dl 1.7 * 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 dl 1.1 *
110     * "George" is the otherwise nameless (because it cannot be
111     * represented) prime number 2^64+13. Using a prime number larger
112     * than can fit in a long ensures that all possible long values
113     * can occur, plus 13 others that just get skipped over when they
114     * are encountered; see method addGammaModGeorge. For this to
115     * work, initial gamma values must be at least 13.
116     *
117     * The value of gamma differs for each instance across a series of
118     * splits, and is generated using a slightly stripped-down variant
119     * of the same algorithm, but operating across calls to split(),
120 dl 1.2 * not calls to nextSeed(): Each instance carries the state of
121 dl 1.1 * this generator as nextSplit, and uses mix64(nextSplit) as its
122     * own gamma value. Computations of gammas themselves use a fixed
123     * constant as the second argument to the addGammaModGeorge
124     * function, GAMMA_GAMMA, a "genuinely random" number from a
125     * radioactive decay reading (obtained from
126     * http://www.fourmilab.ch/hotbits/) meeting the above range
127     * constraint. Using a fixed constant maintains the invariant that
128     * the value of gamma is the same for every instance that is at
129     * the same split-distance from their common root. (Note: there is
130     * nothing especially magic about obtaining this constant from a
131     * "truly random" physical source rather than just choosing one
132     * arbitrarily; using "hotbits" was merely an aesthetically pleasing
133     * choice. In either case, good statistical behavior of the
134     * algorithm should be, and was, verified by using the DieHarder
135     * test suite.)
136     *
137     * The mix64 bit-mixing function called by nextLong and other
138     * methods computes the same value as the "64-bit finalizer"
139     * function in Austin Appleby's MurmurHash3 algorithm. See
140     * http://code.google.com/p/smhasher/wiki/MurmurHash3 , which
141     * comments: "The constants for the finalizers were generated by a
142     * simple simulated-annealing algorithm, and both avalanche all
143     * bits of 'h' to within 0.25% bias." It also appears to work to
144     * use instead any of the variants proposed by David Stafford at
145     * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
146     * but these variants have not yet been tested as thoroughly
147     * in the context of the implementation of SplittableRandom.
148     *
149     * The mix32 function used for nextInt just consists of two of the
150     * five lines of mix64; avalanche testing shows that the 64-bit result
151     * has its top 32 bits avalanched well, though not the bottom 32 bits.
152     * DieHarder tests show that it is adequate for generating one
153     * random int from the 64-bit result of nextSeed.
154     *
155     * Support for the default (no-argument) constructor relies on an
156     * AtomicLong (defaultSeedGenerator) to help perform the
157     * equivalent of a split of a statically constructed
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 dl 1.11 * 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 dl 1.1 */
172    
173     /**
174     * The "genuinely random" value for producing new gamma values.
175     * The value is arbitrary, subject to the requirement that it be
176     * greater or equal to 13.
177     */
178     private static final long GAMMA_GAMMA = 0xF2281E2DBA6606F3L;
179    
180     /**
181     * The "genuinely random" seed update value for default constructors.
182     * The value is arbitrary, subject to the requirement that it be
183     * greater or equal to 13.
184     */
185     private static final long DEFAULT_SEED_GAMMA = 0xBD24B73A95FB84D9L;
186    
187     /**
188 dl 1.11 * 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 dl 1.5 * The least non-zero value returned by nextDouble(). This value
195 dl 1.7 * is scaled by a random value of 53 bits to produce a result.
196 dl 1.5 */
197     private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
198    
199     /**
200 dl 1.1 * The next seed for default constructors.
201     */
202     private static final AtomicLong defaultSeedGenerator =
203 dl 1.11 new AtomicLong(mix64(System.currentTimeMillis()) ^
204     mix64(System.nanoTime()));
205 dl 1.1
206     /**
207     * The seed, updated only via method nextSeed.
208     */
209     private long seed;
210    
211     /**
212     * The constant value added to seed (mod George) on each update.
213     */
214     private final long gamma;
215    
216     /**
217     * The next seed to use for splits. Propagated using
218     * addGammaModGeorge across instances.
219     */
220     private final long nextSplit;
221    
222     /**
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
226     * (mod George) as necessary to produce an (unsigned) result less
227     * than 2^64. We require that g must be at least 13. This
228     * guarantees that if (s+g) mod George >= 2^64 then (s+g+g) mod
229     * George < 2^64; thus we need only a conditional, not a loop,
230     * to be sure of getting a representable value.
231     *
232 dl 1.11 * 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 dl 1.1 * @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 dl 1.11 return (p >= s) ? p : ((p >= BOTTOM13) ? p : p + g) - 13L;
242 dl 1.1 }
243    
244     /**
245     * Returns a bit-mixed transformation of its argument.
246     * See above for explanation.
247     */
248     private static long mix64(long z) {
249     z ^= (z >>> 33);
250     z *= 0xff51afd7ed558ccdL;
251     z ^= (z >>> 33);
252     z *= 0xc4ceb9fe1a85ec53L;
253     z ^= (z >>> 33);
254     return z;
255     }
256    
257     /**
258     * Returns a bit-mixed int transformation of its argument.
259     * See above for explanation.
260     */
261     private static int mix32(long z) {
262     z ^= (z >>> 33);
263     z *= 0xc4ceb9fe1a85ec53L;
264     return (int)(z >>> 32);
265     }
266    
267     /**
268 dl 1.7 * 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 dl 1.11 } while (g >= 0L && g < 13L);
281 dl 1.7 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 dl 1.1 */
296     private static long nextDefaultSeed() {
297     long oldSeed, newSeed;
298     do {
299     oldSeed = defaultSeedGenerator.get();
300     newSeed = addGammaModGeorge(oldSeed, DEFAULT_SEED_GAMMA);
301     } while (!defaultSeedGenerator.compareAndSet(oldSeed, newSeed));
302     return mix64(newSeed);
303     }
304    
305     /*
306     * Internal versions of nextX methods used by streams, as well as
307     * the public nextX(origin, bound) methods. These exist mainly to
308     * avoid the need for multiple versions of stream spliterators
309     * across the different exported forms of streams.
310     */
311    
312     /**
313     * The form of nextLong used by LongStream Spliterators. If
314     * origin is greater than bound, acts as unbounded form of
315     * nextLong, else as bounded form.
316     *
317     * @param origin the least value, unless greater than bound
318     * @param bound the upper bound (exclusive), must not equal origin
319     * @return a pseudorandom value
320     */
321     final long internalNextLong(long origin, long bound) {
322     /*
323     * Four Cases:
324     *
325     * 1. If the arguments indicate unbounded form, act as
326     * nextLong().
327     *
328     * 2. If the range is an exact power of two, apply the
329     * associated bit mask.
330     *
331     * 3. If the range is positive, loop to avoid potential bias
332     * when the implicit nextLong() bound (2<sup>64</sup>) is not
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 dl 1.4 * 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 dl 1.1 *
342     * 4. Otherwise, the range cannot be represented as a positive
343 dl 1.4 * 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 dl 1.1 */
347    
348     long r = mix64(nextSeed());
349     if (origin < bound) {
350     long n = bound - origin, m = n - 1;
351 dl 1.7 if ((n & m) == 0L) // power of two
352 dl 1.1 r = (r & m) + origin;
353 dl 1.7 else if (n > 0L) { // reject over-represented candidates
354 dl 1.1 for (long u = r >>> 1; // ensure nonnegative
355 dl 1.7 u + m - (r = u % n) < 0L; // rejection check
356 dl 1.1 u = mix64(nextSeed()) >>> 1) // retry
357     ;
358     r += origin;
359     }
360 dl 1.7 else { // range not representable as long
361 dl 1.1 while (r < origin || r >= bound)
362     r = mix64(nextSeed());
363     }
364     }
365     return r;
366     }
367    
368     /**
369     * The form of nextInt used by IntStream Spliterators.
370     * Exactly the same as long version, except for types.
371     *
372     * @param origin the least value, unless greater than bound
373     * @param bound the upper bound (exclusive), must not equal origin
374     * @return a pseudorandom value
375     */
376     final int internalNextInt(int origin, int bound) {
377     int r = mix32(nextSeed());
378     if (origin < bound) {
379     int n = bound - origin, m = n - 1;
380     if ((n & m) == 0L)
381     r = (r & m) + origin;
382     else if (n > 0) {
383     for (int u = r >>> 1;
384 dl 1.7 u + m - (r = u % n) < 0;
385 dl 1.1 u = mix32(nextSeed()) >>> 1)
386     ;
387     r += origin;
388     }
389     else {
390     while (r < origin || r >= bound)
391     r = mix32(nextSeed());
392     }
393     }
394     return r;
395     }
396    
397     /**
398     * The form of nextDouble used by DoubleStream Spliterators.
399     *
400     * @param origin the least value, unless greater than bound
401     * @param bound the upper bound (exclusive), must not equal origin
402     * @return a pseudorandom value
403     */
404     final double internalNextDouble(double origin, double bound) {
405 dl 1.5 double r = (nextLong() >>> 11) * DOUBLE_UNIT;
406 dl 1.1 if (origin < bound) {
407     r = r * (bound - origin) + origin;
408 dl 1.7 if (r >= bound) // correct for rounding
409 dl 1.1 r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
410     }
411     return r;
412     }
413    
414     /* ---------------- public methods ---------------- */
415    
416     /**
417 dl 1.7 * Creates a new SplittableRandom instance using the specified
418     * initial seed. SplittableRandom instances created with the same
419 dl 1.11 * seed in the same program generate identical sequences of values.
420 dl 1.1 *
421     * @param seed the initial seed
422     */
423     public SplittableRandom(long seed) {
424     this(seed, 0);
425     }
426    
427     /**
428     * Creates a new SplittableRandom instance that is likely to
429     * generate sequences of values that are statistically independent
430     * of those of any other instances in the current program; and
431     * may, and typically does, vary across program invocations.
432     */
433     public SplittableRandom() {
434     this(nextDefaultSeed(), GAMMA_GAMMA);
435     }
436    
437     /**
438     * Constructs and returns a new SplittableRandom instance that
439     * shares no mutable state with this instance. However, with very
440     * high probability, the set of values collectively generated by
441     * the two objects has the same statistical properties as if the
442     * same quantity of values were generated by a single thread using
443     * a single SplittableRandom object. Either or both of the two
444     * objects may be further split using the {@code split()} method,
445     * and the same expected statistical properties apply to the
446     * entire set of generators constructed by such recursive
447     * splitting.
448     *
449     * @return the new SplittableRandom instance
450     */
451     public SplittableRandom split() {
452     return new SplittableRandom(nextSeed(), nextSplit);
453     }
454    
455     /**
456     * Returns a pseudorandom {@code int} value.
457     *
458 dl 1.7 * @return a pseudorandom {@code int} value
459 dl 1.1 */
460     public int nextInt() {
461     return mix32(nextSeed());
462     }
463    
464     /**
465 dl 1.7 * Returns a pseudorandom {@code int} value between zero (inclusive)
466 dl 1.1 * and the specified bound (exclusive).
467     *
468     * @param bound the bound on the random number to be returned. Must be
469     * positive.
470 dl 1.7 * @return a pseudorandom {@code int} value between zero
471 jsr166 1.10 * (inclusive) and the bound (exclusive)
472 dl 1.7 * @throws IllegalArgumentException if the bound is less than zero
473 dl 1.1 */
474     public int nextInt(int bound) {
475     if (bound <= 0)
476     throw new IllegalArgumentException("bound must be positive");
477     // Specialize internalNextInt for origin 0
478     int r = mix32(nextSeed());
479     int m = bound - 1;
480     if ((bound & m) == 0L) // power of two
481     r &= m;
482     else { // reject over-represented candidates
483     for (int u = r >>> 1;
484 dl 1.7 u + m - (r = u % bound) < 0;
485 dl 1.1 u = mix32(nextSeed()) >>> 1)
486     ;
487     }
488     return r;
489     }
490    
491     /**
492     * Returns a pseudorandom {@code int} value between the specified
493     * origin (inclusive) and the specified bound (exclusive).
494     *
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 jsr166 1.10 * (inclusive) and the bound (exclusive)
499 dl 1.7 * @throws IllegalArgumentException if {@code origin} is greater than
500 dl 1.1 * or equal to {@code bound}
501     */
502     public int nextInt(int origin, int bound) {
503     if (origin >= bound)
504     throw new IllegalArgumentException("bound must be greater than origin");
505     return internalNextInt(origin, bound);
506     }
507    
508     /**
509     * Returns a pseudorandom {@code long} value.
510     *
511 dl 1.7 * @return a pseudorandom {@code long} value
512 dl 1.1 */
513     public long nextLong() {
514     return mix64(nextSeed());
515     }
516    
517     /**
518 dl 1.7 * Returns a pseudorandom {@code long} value between zero (inclusive)
519 dl 1.1 * and the specified bound (exclusive).
520     *
521     * @param bound the bound on the random number to be returned. Must be
522     * positive.
523 dl 1.7 * @return a pseudorandom {@code long} value between zero
524 jsr166 1.10 * (inclusive) and the bound (exclusive)
525 dl 1.7 * @throws IllegalArgumentException if {@code bound} is less than zero
526 dl 1.1 */
527     public long nextLong(long bound) {
528     if (bound <= 0)
529     throw new IllegalArgumentException("bound must be positive");
530     // Specialize internalNextLong for origin 0
531     long r = mix64(nextSeed());
532     long m = bound - 1;
533     if ((bound & m) == 0L) // power of two
534     r &= m;
535     else { // reject over-represented candidates
536     for (long u = r >>> 1;
537     u + m - (r = u % bound) < 0L;
538     u = mix64(nextSeed()) >>> 1)
539     ;
540     }
541     return r;
542     }
543    
544     /**
545     * Returns a pseudorandom {@code long} value between the specified
546     * origin (inclusive) and the specified bound (exclusive).
547     *
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 jsr166 1.10 * (inclusive) and the bound (exclusive)
552 dl 1.7 * @throws IllegalArgumentException if {@code origin} is greater than
553 dl 1.1 * or equal to {@code bound}
554     */
555     public long nextLong(long origin, long bound) {
556     if (origin >= bound)
557     throw new IllegalArgumentException("bound must be greater than origin");
558     return internalNextLong(origin, bound);
559     }
560    
561     /**
562 dl 1.7 * Returns a pseudorandom {@code double} value between zero
563     * (inclusive) and one (exclusive).
564 dl 1.1 *
565 dl 1.7 * @return a pseudorandom {@code double} value between zero
566     * (inclusive) and one (exclusive)
567 dl 1.1 */
568     public double nextDouble() {
569 dl 1.11 return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
570 dl 1.1 }
571    
572     /**
573     * Returns a pseudorandom {@code double} value between 0.0
574     * (inclusive) and the specified bound (exclusive).
575     *
576     * @param bound the bound on the random number to be returned. Must be
577     * positive.
578 dl 1.7 * @return a pseudorandom {@code double} value between zero
579 jsr166 1.10 * (inclusive) and the bound (exclusive)
580 dl 1.7 * @throws IllegalArgumentException if {@code bound} is less than zero
581 dl 1.1 */
582     public double nextDouble(double bound) {
583 dl 1.7 if (!(bound > 0.0))
584 dl 1.1 throw new IllegalArgumentException("bound must be positive");
585 dl 1.11 double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
586 dl 1.1 return (result < bound) ? result : // correct for rounding
587     Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
588     }
589    
590     /**
591 dl 1.7 * Returns a pseudorandom {@code double} value between the specified
592 dl 1.1 * 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 jsr166 1.10 * (inclusive) and the bound (exclusive)
598 dl 1.1 * @throws IllegalArgumentException if {@code origin} is greater than
599     * or equal to {@code bound}
600     */
601     public double nextDouble(double origin, double bound) {
602 dl 1.7 if (!(origin < bound))
603 dl 1.1 throw new IllegalArgumentException("bound must be greater than origin");
604     return internalNextDouble(origin, bound);
605     }
606    
607 dl 1.11 /**
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 dl 1.1 // stream methods, coded in a way intended to better isolate for
617     // maintenance purposes the small differences across forms.
618    
619     /**
620 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
621 dl 1.1 * 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 dl 1.7 * less than zero
627 dl 1.1 */
628     public IntStream ints(long streamSize) {
629     if (streamSize < 0L)
630     throw new IllegalArgumentException("negative Stream size");
631     return StreamSupport.intStream
632     (new RandomIntsSpliterator
633     (this, 0L, streamSize, Integer.MAX_VALUE, 0),
634     false);
635     }
636    
637     /**
638     * Returns an effectively unlimited stream of pseudorandom {@code int}
639 jsr166 1.10 * values.
640 dl 1.1 *
641     * @implNote This method is implemented to be equivalent to {@code
642     * ints(Long.MAX_VALUE)}.
643     *
644     * @return a stream of pseudorandom {@code int} values
645     */
646     public IntStream ints() {
647     return StreamSupport.intStream
648     (new RandomIntsSpliterator
649     (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
650     false);
651     }
652    
653     /**
654 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
655 dl 1.1 * pseudorandom {@code int} values, each conforming to the given
656     * origin and bound.
657     *
658     * @param streamSize the number of values to generate
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 jsr166 1.10 * each with the given origin and bound
663 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
664 dl 1.7 * less than zero, or {@code randomNumberOrigin}
665 dl 1.1 * is greater than or equal to {@code randomNumberBound}
666     */
667     public IntStream ints(long streamSize, int randomNumberOrigin,
668     int randomNumberBound) {
669     if (streamSize < 0L)
670     throw new IllegalArgumentException("negative Stream size");
671     if (randomNumberOrigin >= randomNumberBound)
672     throw new IllegalArgumentException("bound must be greater than origin");
673     return StreamSupport.intStream
674     (new RandomIntsSpliterator
675     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
676     false);
677     }
678    
679     /**
680     * Returns an effectively unlimited stream of pseudorandom {@code
681     * int} values, each conforming to the given origin and bound.
682     *
683     * @implNote This method is implemented to be equivalent to {@code
684     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
685     *
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 jsr166 1.10 * each with the given origin and bound
690 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
691     * is greater than or equal to {@code randomNumberBound}
692     */
693     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
694     if (randomNumberOrigin >= randomNumberBound)
695     throw new IllegalArgumentException("bound must be greater than origin");
696     return StreamSupport.intStream
697     (new RandomIntsSpliterator
698     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
699     false);
700     }
701    
702     /**
703 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
704 dl 1.1 * pseudorandom {@code long} values.
705     *
706     * @param streamSize the number of values to generate
707 dl 1.7 * @return a stream of pseudorandom {@code long} values
708 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
709 dl 1.7 * less than zero
710 dl 1.1 */
711     public LongStream longs(long streamSize) {
712     if (streamSize < 0L)
713     throw new IllegalArgumentException("negative Stream size");
714     return StreamSupport.longStream
715     (new RandomLongsSpliterator
716     (this, 0L, streamSize, Long.MAX_VALUE, 0L),
717     false);
718     }
719    
720     /**
721     * Returns an effectively unlimited stream of pseudorandom {@code long}
722     * values.
723     *
724     * @implNote This method is implemented to be equivalent to {@code
725     * longs(Long.MAX_VALUE)}.
726     *
727     * @return a stream of pseudorandom {@code long} values
728     */
729     public LongStream longs() {
730     return StreamSupport.longStream
731     (new RandomLongsSpliterator
732     (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
733     false);
734     }
735    
736     /**
737 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
738 dl 1.1 * pseudorandom {@code long} values, each conforming to the
739     * given origin and bound.
740     *
741     * @param streamSize the number of values to generate
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 jsr166 1.10 * each with the given origin and bound
746 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
747 dl 1.7 * less than zero, or {@code randomNumberOrigin}
748 dl 1.1 * is greater than or equal to {@code randomNumberBound}
749     */
750     public LongStream longs(long streamSize, long randomNumberOrigin,
751     long randomNumberBound) {
752     if (streamSize < 0L)
753     throw new IllegalArgumentException("negative Stream size");
754     if (randomNumberOrigin >= randomNumberBound)
755     throw new IllegalArgumentException("bound must be greater than origin");
756     return StreamSupport.longStream
757     (new RandomLongsSpliterator
758     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
759     false);
760     }
761    
762     /**
763     * Returns an effectively unlimited stream of pseudorandom {@code
764     * long} values, each conforming to the given origin and bound.
765     *
766     * @implNote This method is implemented to be equivalent to {@code
767     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
768     *
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 jsr166 1.10 * each with the given origin and bound
773 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
774     * is greater than or equal to {@code randomNumberBound}
775     */
776     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
777     if (randomNumberOrigin >= randomNumberBound)
778     throw new IllegalArgumentException("bound must be greater than origin");
779     return StreamSupport.longStream
780     (new RandomLongsSpliterator
781     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
782     false);
783     }
784    
785     /**
786 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
787     * pseudorandom {@code double} values, each between zero
788     * (inclusive) and one (exclusive).
789 dl 1.1 *
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 dl 1.7 * less than zero
794 dl 1.1 */
795     public DoubleStream doubles(long streamSize) {
796     if (streamSize < 0L)
797     throw new IllegalArgumentException("negative Stream size");
798     return StreamSupport.doubleStream
799     (new RandomDoublesSpliterator
800     (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
801     false);
802     }
803    
804     /**
805     * Returns an effectively unlimited stream of pseudorandom {@code
806 dl 1.7 * double} values, each between zero (inclusive) and one
807     * (exclusive).
808 dl 1.1 *
809     * @implNote This method is implemented to be equivalent to {@code
810     * doubles(Long.MAX_VALUE)}.
811     *
812     * @return a stream of pseudorandom {@code double} values
813     */
814     public DoubleStream doubles() {
815     return StreamSupport.doubleStream
816     (new RandomDoublesSpliterator
817     (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
818     false);
819     }
820    
821     /**
822 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
823 dl 1.1 * pseudorandom {@code double} values, each conforming to the
824     * given origin and bound.
825     *
826     * @param streamSize the number of values to generate
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 jsr166 1.10 * each with the given origin and bound
831 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
832 jsr166 1.10 * less than zero
833 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
834     * is greater than or equal to {@code randomNumberBound}
835     */
836     public DoubleStream doubles(long streamSize, double randomNumberOrigin,
837     double randomNumberBound) {
838     if (streamSize < 0L)
839     throw new IllegalArgumentException("negative Stream size");
840 dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
841 dl 1.1 throw new IllegalArgumentException("bound must be greater than origin");
842     return StreamSupport.doubleStream
843     (new RandomDoublesSpliterator
844     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
845     false);
846     }
847    
848     /**
849     * Returns an effectively unlimited stream of pseudorandom {@code
850     * double} values, each conforming to the given origin and bound.
851     *
852     * @implNote This method is implemented to be equivalent to {@code
853     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
854     *
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 jsr166 1.10 * each with the given origin and bound
859 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
860     * is greater than or equal to {@code randomNumberBound}
861     */
862     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
863 dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
864 dl 1.1 throw new IllegalArgumentException("bound must be greater than origin");
865     return StreamSupport.doubleStream
866     (new RandomDoublesSpliterator
867     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
868     false);
869     }
870    
871     /**
872     * Spliterator for int streams. We multiplex the four int
873 dl 1.7 * versions into one class by treating a bound less than origin as
874 dl 1.1 * 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 dl 1.11 static final class RandomIntsSpliterator implements Spliterator.OfInt {
880 dl 1.1 final SplittableRandom rng;
881     long index;
882     final long fence;
883     final int origin;
884     final int bound;
885     RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
886     int origin, int bound) {
887     this.rng = rng; this.index = index; this.fence = fence;
888     this.origin = origin; this.bound = bound;
889     }
890    
891     public RandomIntsSpliterator trySplit() {
892     long i = index, m = (i + fence) >>> 1;
893     return (m <= i) ? null :
894     new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
895     }
896    
897     public long estimateSize() {
898     return fence - index;
899     }
900    
901     public int characteristics() {
902     return (Spliterator.SIZED | Spliterator.SUBSIZED |
903 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
904 dl 1.1 }
905    
906     public boolean tryAdvance(IntConsumer consumer) {
907     if (consumer == null) throw new NullPointerException();
908     long i = index, f = fence;
909     if (i < f) {
910     consumer.accept(rng.internalNextInt(origin, bound));
911     index = i + 1;
912     return true;
913     }
914     return false;
915     }
916    
917     public void forEachRemaining(IntConsumer consumer) {
918     if (consumer == null) throw new NullPointerException();
919     long i = index, f = fence;
920     if (i < f) {
921     index = f;
922     int o = origin, b = bound;
923     do {
924     consumer.accept(rng.internalNextInt(o, b));
925     } while (++i < f);
926     }
927     }
928     }
929    
930     /**
931     * Spliterator for long streams.
932     */
933 dl 1.11 static final class RandomLongsSpliterator implements Spliterator.OfLong {
934 dl 1.1 final SplittableRandom rng;
935     long index;
936     final long fence;
937     final long origin;
938     final long bound;
939     RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
940     long origin, long bound) {
941     this.rng = rng; this.index = index; this.fence = fence;
942     this.origin = origin; this.bound = bound;
943     }
944    
945     public RandomLongsSpliterator trySplit() {
946     long i = index, m = (i + fence) >>> 1;
947     return (m <= i) ? null :
948     new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
949     }
950    
951     public long estimateSize() {
952     return fence - index;
953     }
954    
955     public int characteristics() {
956     return (Spliterator.SIZED | Spliterator.SUBSIZED |
957 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
958 dl 1.1 }
959    
960     public boolean tryAdvance(LongConsumer consumer) {
961     if (consumer == null) throw new NullPointerException();
962     long i = index, f = fence;
963     if (i < f) {
964     consumer.accept(rng.internalNextLong(origin, bound));
965     index = i + 1;
966     return true;
967     }
968     return false;
969     }
970    
971     public void forEachRemaining(LongConsumer consumer) {
972     if (consumer == null) throw new NullPointerException();
973     long i = index, f = fence;
974     if (i < f) {
975     index = f;
976     long o = origin, b = bound;
977     do {
978     consumer.accept(rng.internalNextLong(o, b));
979     } while (++i < f);
980     }
981     }
982    
983     }
984    
985     /**
986     * Spliterator for double streams.
987     */
988 dl 1.11 static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
989 dl 1.1 final SplittableRandom rng;
990     long index;
991     final long fence;
992     final double origin;
993     final double bound;
994     RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
995     double origin, double bound) {
996     this.rng = rng; this.index = index; this.fence = fence;
997     this.origin = origin; this.bound = bound;
998     }
999    
1000     public RandomDoublesSpliterator trySplit() {
1001     long i = index, m = (i + fence) >>> 1;
1002     return (m <= i) ? null :
1003     new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
1004     }
1005    
1006     public long estimateSize() {
1007     return fence - index;
1008     }
1009    
1010     public int characteristics() {
1011     return (Spliterator.SIZED | Spliterator.SUBSIZED |
1012 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
1013 dl 1.1 }
1014    
1015     public boolean tryAdvance(DoubleConsumer consumer) {
1016     if (consumer == null) throw new NullPointerException();
1017     long i = index, f = fence;
1018     if (i < f) {
1019     consumer.accept(rng.internalNextDouble(origin, bound));
1020     index = i + 1;
1021     return true;
1022     }
1023     return false;
1024     }
1025    
1026     public void forEachRemaining(DoubleConsumer consumer) {
1027     if (consumer == null) throw new NullPointerException();
1028     long i = index, f = fence;
1029     if (i < f) {
1030     index = f;
1031     double o = origin, b = bound;
1032     do {
1033     consumer.accept(rng.internalNextDouble(o, b));
1034     } while (++i < f);
1035     }
1036     }
1037     }
1038    
1039     }