ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.8
Committed: Fri Jul 12 19:45:19 2013 UTC (10 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.7: +0 -1 lines
Log Message:
whitespace

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     * {@link java.util.Random} but differs in the following ways: <ul>
45     *
46     * <li>Series of generated values pass the DieHarder suite testing
47     * independence and uniformity properties of random number generators.
48     * (Most recently validated with <a
49     * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
50     * 3.31.1</a>.) These tests validate only the methods for certain
51     * types and ranges, but similar properties are expected to hold, at
52     * least approximately, for others as well. </li>
53     *
54     * <li> Method {@link #split} constructs and returns a new
55     * SplittableRandom instance that shares no mutable state with the
56 dl 1.7 * current instance. However, with very high probability, the
57     * values collectively generated by the two objects have the same
58 dl 1.1 * statistical properties as if the same quantity of values were
59     * generated by a single thread using a single {@code
60     * SplittableRandom} object. </li>
61     *
62     * <li>Instances of SplittableRandom are <em>not</em> thread-safe.
63     * They are designed to be split, not shared, across threads. For
64     * example, a {@link java.util.concurrent.ForkJoinTask
65     * fork/join-style} computation using random numbers might include a
66     * construction of the form {@code new
67     * Subtask(aSplittableRandom.split()).fork()}.
68     *
69     * <li>This class provides additional methods for generating random
70     * streams, that employ the above techniques when used in {@code
71     * stream.parallel()} mode.</li>
72     *
73     * </ul>
74     *
75     * @author Guy Steele
76 dl 1.2 * @author Doug Lea
77 dl 1.1 * @since 1.8
78     */
79     public class SplittableRandom {
80    
81     /*
82     * File organization: First the non-public methods that constitute
83     * the main algorithm, then the main public methods, followed by
84     * some custom spliterator classes needed for stream methods.
85     *
86     * Credits: Primary algorithm and code by Guy Steele. Stream
87     * support methods by Doug Lea. Documentation jointly produced
88     * with additional help from Brian Goetz.
89     */
90    
91     /*
92     * Implementation Overview.
93     *
94     * This algorithm was inspired by the "DotMix" algorithm by
95     * Leiserson, Schardl, and Sukha "Deterministic Parallel
96     * Random-Number Generation for Dynamic-Multithreading Platforms",
97     * PPoPP 2012, but improves and extends it in several ways.
98     *
99 dl 1.7 * The primary update step (see method nextSeed()) is simply to
100     * add a constant ("gamma") to the current seed, modulo a prime
101     * ("George"). However, the nextLong and nextInt methods do not
102     * return this value, but instead the results of bit-mixing
103     * transformations that produce more uniformly distributed
104     * sequences.
105 dl 1.1 *
106     * "George" is the otherwise nameless (because it cannot be
107     * represented) prime number 2^64+13. Using a prime number larger
108     * than can fit in a long ensures that all possible long values
109     * can occur, plus 13 others that just get skipped over when they
110     * are encountered; see method addGammaModGeorge. For this to
111     * work, initial gamma values must be at least 13.
112     *
113     * The value of gamma differs for each instance across a series of
114     * splits, and is generated using a slightly stripped-down variant
115     * of the same algorithm, but operating across calls to split(),
116 dl 1.2 * not calls to nextSeed(): Each instance carries the state of
117 dl 1.1 * this generator as nextSplit, and uses mix64(nextSplit) as its
118     * own gamma value. Computations of gammas themselves use a fixed
119     * constant as the second argument to the addGammaModGeorge
120     * function, GAMMA_GAMMA, a "genuinely random" number from a
121     * radioactive decay reading (obtained from
122     * http://www.fourmilab.ch/hotbits/) meeting the above range
123     * constraint. Using a fixed constant maintains the invariant that
124     * the value of gamma is the same for every instance that is at
125     * the same split-distance from their common root. (Note: there is
126     * nothing especially magic about obtaining this constant from a
127     * "truly random" physical source rather than just choosing one
128     * arbitrarily; using "hotbits" was merely an aesthetically pleasing
129     * choice. In either case, good statistical behavior of the
130     * algorithm should be, and was, verified by using the DieHarder
131     * test suite.)
132     *
133     * The mix64 bit-mixing function called by nextLong and other
134     * methods computes the same value as the "64-bit finalizer"
135     * function in Austin Appleby's MurmurHash3 algorithm. See
136     * http://code.google.com/p/smhasher/wiki/MurmurHash3 , which
137     * comments: "The constants for the finalizers were generated by a
138     * simple simulated-annealing algorithm, and both avalanche all
139     * bits of 'h' to within 0.25% bias." It also appears to work to
140     * use instead any of the variants proposed by David Stafford at
141     * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
142     * but these variants have not yet been tested as thoroughly
143     * in the context of the implementation of SplittableRandom.
144     *
145     * The mix32 function used for nextInt just consists of two of the
146     * five lines of mix64; avalanche testing shows that the 64-bit result
147     * has its top 32 bits avalanched well, though not the bottom 32 bits.
148     * DieHarder tests show that it is adequate for generating one
149     * random int from the 64-bit result of nextSeed.
150     *
151     * Support for the default (no-argument) constructor relies on an
152     * AtomicLong (defaultSeedGenerator) to help perform the
153     * equivalent of a split of a statically constructed
154     * SplittableRandom. Unlike other cases, this split must be
155     * performed in a thread-safe manner. We use
156     * AtomicLong.compareAndSet as the (typically) most efficient
157     * mechanism. To bootstrap, we start off using System.nanotime(),
158     * and update using another "genuinely random" constant
159     * DEFAULT_SEED_GAMMA. The default constructor uses GAMMA_GAMMA,
160     * not 0, for its splitSeed argument (addGammaModGeorge(0,
161     * GAMMA_GAMMA) == GAMMA_GAMMA) to reflect that each is split from
162     * this root generator, even though the root is not explicitly
163     * represented as a SplittableRandom.
164     */
165    
166     /**
167     * The "genuinely random" value for producing new gamma values.
168     * The value is arbitrary, subject to the requirement that it be
169     * greater or equal to 13.
170     */
171     private static final long GAMMA_GAMMA = 0xF2281E2DBA6606F3L;
172    
173     /**
174     * The "genuinely random" seed update value for default constructors.
175     * The value is arbitrary, subject to the requirement that it be
176     * greater or equal to 13.
177     */
178     private static final long DEFAULT_SEED_GAMMA = 0xBD24B73A95FB84D9L;
179    
180     /**
181 dl 1.5 * The least non-zero value returned by nextDouble(). This value
182 dl 1.7 * is scaled by a random value of 53 bits to produce a result.
183 dl 1.5 */
184     private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
185    
186     /**
187 dl 1.1 * The next seed for default constructors.
188     */
189     private static final AtomicLong defaultSeedGenerator =
190     new AtomicLong(System.nanoTime());
191    
192     /**
193     * The seed, updated only via method nextSeed.
194     */
195     private long seed;
196    
197     /**
198     * The constant value added to seed (mod George) on each update.
199     */
200     private final long gamma;
201    
202     /**
203     * The next seed to use for splits. Propagated using
204     * addGammaModGeorge across instances.
205     */
206     private final long nextSplit;
207    
208     /**
209     * Adds the given gamma value, g, to the given seed value s, mod
210     * George (2^64+13). We regard s and g as unsigned values
211     * (ranging from 0 to 2^64-1). We add g to s either once or twice
212     * (mod George) as necessary to produce an (unsigned) result less
213     * than 2^64. We require that g must be at least 13. This
214     * guarantees that if (s+g) mod George >= 2^64 then (s+g+g) mod
215     * George < 2^64; thus we need only a conditional, not a loop,
216     * to be sure of getting a representable value.
217     *
218     * @param s a seed value
219     * @param g a gamma value, 13 <= g (as unsigned)
220     */
221     private static long addGammaModGeorge(long s, long g) {
222     long p = s + g;
223     if (Long.compareUnsigned(p, g) >= 0)
224     return p;
225     long q = p - 13L;
226     return (Long.compareUnsigned(p, 13L) >= 0) ? q : (q + g);
227     }
228    
229     /**
230     * Returns a bit-mixed transformation of its argument.
231     * See above for explanation.
232     */
233     private static long mix64(long z) {
234     z ^= (z >>> 33);
235     z *= 0xff51afd7ed558ccdL;
236     z ^= (z >>> 33);
237     z *= 0xc4ceb9fe1a85ec53L;
238     z ^= (z >>> 33);
239     return z;
240     }
241    
242     /**
243     * Returns a bit-mixed int transformation of its argument.
244     * See above for explanation.
245     */
246     private static int mix32(long z) {
247     z ^= (z >>> 33);
248     z *= 0xc4ceb9fe1a85ec53L;
249     return (int)(z >>> 32);
250     }
251    
252     /**
253 dl 1.7 * Internal constructor used by all other constructors and by
254     * method split. Establishes the initial seed for this instance,
255     * and uses the given splitSeed to establish gamma, as well as the
256     * nextSplit to use by this instance. The loop to skip ineligible
257     * gammas very rarely iterates, and does so at most 13 times.
258     */
259     private SplittableRandom(long seed, long splitSeed) {
260     this.seed = seed;
261     long s = splitSeed, g;
262     do { // ensure gamma >= 13, considered as an unsigned integer
263     s = addGammaModGeorge(s, GAMMA_GAMMA);
264     g = mix64(s);
265     } while (Long.compareUnsigned(g, 13L) < 0);
266     this.gamma = g;
267     this.nextSplit = s;
268     }
269    
270     /**
271     * Updates in-place and returns seed.
272     * See above for explanation.
273     */
274     private long nextSeed() {
275     return seed = addGammaModGeorge(seed, gamma);
276     }
277    
278     /**
279     * Atomically updates and returns next seed for default constructor.
280 dl 1.1 */
281     private static long nextDefaultSeed() {
282     long oldSeed, newSeed;
283     do {
284     oldSeed = defaultSeedGenerator.get();
285     newSeed = addGammaModGeorge(oldSeed, DEFAULT_SEED_GAMMA);
286     } while (!defaultSeedGenerator.compareAndSet(oldSeed, newSeed));
287     return mix64(newSeed);
288     }
289    
290     /*
291     * Internal versions of nextX methods used by streams, as well as
292     * the public nextX(origin, bound) methods. These exist mainly to
293     * avoid the need for multiple versions of stream spliterators
294     * across the different exported forms of streams.
295     */
296    
297     /**
298     * The form of nextLong used by LongStream Spliterators. If
299     * origin is greater than bound, acts as unbounded form of
300     * nextLong, else as bounded form.
301     *
302     * @param origin the least value, unless greater than bound
303     * @param bound the upper bound (exclusive), must not equal origin
304     * @return a pseudorandom value
305     */
306     final long internalNextLong(long origin, long bound) {
307     /*
308     * Four Cases:
309     *
310     * 1. If the arguments indicate unbounded form, act as
311     * nextLong().
312     *
313     * 2. If the range is an exact power of two, apply the
314     * associated bit mask.
315     *
316     * 3. If the range is positive, loop to avoid potential bias
317     * when the implicit nextLong() bound (2<sup>64</sup>) is not
318     * evenly divisible by the range. The loop rejects candidates
319     * computed from otherwise over-represented values. The
320     * expected number of iterations under an ideal generator
321 dl 1.4 * varies from 1 to 2, depending on the bound. The loop itself
322     * takes an unlovable form. Because the first candidate is
323     * already available, we need a break-in-the-middle
324     * construction, which is concisely but cryptically performed
325     * within the while-condition of a body-less for loop.
326 dl 1.1 *
327     * 4. Otherwise, the range cannot be represented as a positive
328 dl 1.4 * long. The loop repeatedly generates unbounded longs until
329     * obtaining a candidate meeting constraints (with an expected
330     * number of iterations of less than two).
331 dl 1.1 */
332    
333     long r = mix64(nextSeed());
334     if (origin < bound) {
335     long n = bound - origin, m = n - 1;
336 dl 1.7 if ((n & m) == 0L) // power of two
337 dl 1.1 r = (r & m) + origin;
338 dl 1.7 else if (n > 0L) { // reject over-represented candidates
339 dl 1.1 for (long u = r >>> 1; // ensure nonnegative
340 dl 1.7 u + m - (r = u % n) < 0L; // rejection check
341 dl 1.1 u = mix64(nextSeed()) >>> 1) // retry
342     ;
343     r += origin;
344     }
345 dl 1.7 else { // range not representable as long
346 dl 1.1 while (r < origin || r >= bound)
347     r = mix64(nextSeed());
348     }
349     }
350     return r;
351     }
352    
353     /**
354     * The form of nextInt used by IntStream Spliterators.
355     * Exactly the same as long version, except for types.
356     *
357     * @param origin the least value, unless greater than bound
358     * @param bound the upper bound (exclusive), must not equal origin
359     * @return a pseudorandom value
360     */
361     final int internalNextInt(int origin, int bound) {
362     int r = mix32(nextSeed());
363     if (origin < bound) {
364     int n = bound - origin, m = n - 1;
365     if ((n & m) == 0L)
366     r = (r & m) + origin;
367     else if (n > 0) {
368     for (int u = r >>> 1;
369 dl 1.7 u + m - (r = u % n) < 0;
370 dl 1.1 u = mix32(nextSeed()) >>> 1)
371     ;
372     r += origin;
373     }
374     else {
375     while (r < origin || r >= bound)
376     r = mix32(nextSeed());
377     }
378     }
379     return r;
380     }
381    
382     /**
383     * The form of nextDouble used by DoubleStream Spliterators.
384     *
385     * @param origin the least value, unless greater than bound
386     * @param bound the upper bound (exclusive), must not equal origin
387     * @return a pseudorandom value
388     */
389     final double internalNextDouble(double origin, double bound) {
390 dl 1.5 double r = (nextLong() >>> 11) * DOUBLE_UNIT;
391 dl 1.1 if (origin < bound) {
392     r = r * (bound - origin) + origin;
393 dl 1.7 if (r >= bound) // correct for rounding
394 dl 1.1 r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
395     }
396     return r;
397     }
398    
399     /* ---------------- public methods ---------------- */
400    
401     /**
402 dl 1.7 * Creates a new SplittableRandom instance using the specified
403     * initial seed. SplittableRandom instances created with the same
404     * seed generate identical sequences of values.
405 dl 1.1 *
406     * @param seed the initial seed
407     */
408     public SplittableRandom(long seed) {
409     this(seed, 0);
410     }
411    
412     /**
413     * Creates a new SplittableRandom instance that is likely to
414     * generate sequences of values that are statistically independent
415     * of those of any other instances in the current program; and
416     * may, and typically does, vary across program invocations.
417     */
418     public SplittableRandom() {
419     this(nextDefaultSeed(), GAMMA_GAMMA);
420     }
421    
422     /**
423     * Constructs and returns a new SplittableRandom instance that
424     * shares no mutable state with this instance. However, with very
425     * high probability, the set of values collectively generated by
426     * the two objects has the same statistical properties as if the
427     * same quantity of values were generated by a single thread using
428     * a single SplittableRandom object. Either or both of the two
429     * objects may be further split using the {@code split()} method,
430     * and the same expected statistical properties apply to the
431     * entire set of generators constructed by such recursive
432     * splitting.
433     *
434     * @return the new SplittableRandom instance
435     */
436     public SplittableRandom split() {
437     return new SplittableRandom(nextSeed(), nextSplit);
438     }
439    
440     /**
441     * Returns a pseudorandom {@code int} value.
442     *
443 dl 1.7 * @return a pseudorandom {@code int} value
444 dl 1.1 */
445     public int nextInt() {
446     return mix32(nextSeed());
447     }
448    
449     /**
450 dl 1.7 * Returns a pseudorandom {@code int} value between zero (inclusive)
451 dl 1.1 * and the specified bound (exclusive).
452     *
453     * @param bound the bound on the random number to be returned. Must be
454     * positive.
455 dl 1.7 * @return a pseudorandom {@code int} value between zero
456 dl 1.1 * (inclusive) and the bound (exclusive).
457 dl 1.7 * @throws IllegalArgumentException if the bound is less than zero
458 dl 1.1 */
459     public int nextInt(int bound) {
460     if (bound <= 0)
461     throw new IllegalArgumentException("bound must be positive");
462     // Specialize internalNextInt for origin 0
463     int r = mix32(nextSeed());
464     int m = bound - 1;
465     if ((bound & m) == 0L) // power of two
466     r &= m;
467     else { // reject over-represented candidates
468     for (int u = r >>> 1;
469 dl 1.7 u + m - (r = u % bound) < 0;
470 dl 1.1 u = mix32(nextSeed()) >>> 1)
471     ;
472     }
473     return r;
474     }
475    
476     /**
477     * Returns a pseudorandom {@code int} value between the specified
478     * origin (inclusive) and the specified bound (exclusive).
479     *
480     * @param origin the least value returned
481     * @param bound the upper bound (exclusive)
482     * @return a pseudorandom {@code int} value between the origin
483     * (inclusive) and the bound (exclusive).
484 dl 1.7 * @throws IllegalArgumentException if {@code origin} is greater than
485 dl 1.1 * or equal to {@code bound}
486     */
487     public int nextInt(int origin, int bound) {
488     if (origin >= bound)
489     throw new IllegalArgumentException("bound must be greater than origin");
490     return internalNextInt(origin, bound);
491     }
492    
493     /**
494     * Returns a pseudorandom {@code long} value.
495     *
496 dl 1.7 * @return a pseudorandom {@code long} value
497 dl 1.1 */
498     public long nextLong() {
499     return mix64(nextSeed());
500     }
501    
502     /**
503 dl 1.7 * Returns a pseudorandom {@code long} value between zero (inclusive)
504 dl 1.1 * and the specified bound (exclusive).
505     *
506     * @param bound the bound on the random number to be returned. Must be
507     * positive.
508 dl 1.7 * @return a pseudorandom {@code long} value between zero
509 dl 1.1 * (inclusive) and the bound (exclusive).
510 dl 1.7 * @throws IllegalArgumentException if {@code bound} is less than zero
511 dl 1.1 */
512     public long nextLong(long bound) {
513     if (bound <= 0)
514     throw new IllegalArgumentException("bound must be positive");
515     // Specialize internalNextLong for origin 0
516     long r = mix64(nextSeed());
517     long m = bound - 1;
518     if ((bound & m) == 0L) // power of two
519     r &= m;
520     else { // reject over-represented candidates
521     for (long u = r >>> 1;
522     u + m - (r = u % bound) < 0L;
523     u = mix64(nextSeed()) >>> 1)
524     ;
525     }
526     return r;
527     }
528    
529     /**
530     * Returns a pseudorandom {@code long} value between the specified
531     * origin (inclusive) and the specified bound (exclusive).
532     *
533     * @param origin the least value returned
534     * @param bound the upper bound (exclusive)
535     * @return a pseudorandom {@code long} value between the origin
536     * (inclusive) and the bound (exclusive).
537 dl 1.7 * @throws IllegalArgumentException if {@code origin} is greater than
538 dl 1.1 * or equal to {@code bound}
539     */
540     public long nextLong(long origin, long bound) {
541     if (origin >= bound)
542     throw new IllegalArgumentException("bound must be greater than origin");
543     return internalNextLong(origin, bound);
544     }
545    
546     /**
547 dl 1.7 * Returns a pseudorandom {@code double} value between zero
548     * (inclusive) and one (exclusive).
549 dl 1.1 *
550 dl 1.7 * @return a pseudorandom {@code double} value between zero
551     * (inclusive) and one (exclusive)
552 dl 1.1 */
553     public double nextDouble() {
554 dl 1.5 return (nextLong() >>> 11) * DOUBLE_UNIT;
555 dl 1.1 }
556    
557     /**
558     * Returns a pseudorandom {@code double} value between 0.0
559     * (inclusive) and the specified bound (exclusive).
560     *
561     * @param bound the bound on the random number to be returned. Must be
562     * positive.
563 dl 1.7 * @return a pseudorandom {@code double} value between zero
564 dl 1.1 * (inclusive) and the bound (exclusive).
565 dl 1.7 * @throws IllegalArgumentException if {@code bound} is less than zero
566 dl 1.1 */
567     public double nextDouble(double bound) {
568 dl 1.7 if (!(bound > 0.0))
569 dl 1.1 throw new IllegalArgumentException("bound must be positive");
570     double result = nextDouble() * bound;
571     return (result < bound) ? result : // correct for rounding
572     Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
573     }
574    
575     /**
576 dl 1.7 * Returns a pseudorandom {@code double} value between the specified
577 dl 1.1 * origin (inclusive) and bound (exclusive).
578     *
579     * @param origin the least value returned
580     * @param bound the upper bound
581     * @return a pseudorandom {@code double} value between the origin
582     * (inclusive) and the bound (exclusive).
583     * @throws IllegalArgumentException if {@code origin} is greater than
584     * or equal to {@code bound}
585     */
586     public double nextDouble(double origin, double bound) {
587 dl 1.7 if (!(origin < bound))
588 dl 1.1 throw new IllegalArgumentException("bound must be greater than origin");
589     return internalNextDouble(origin, bound);
590     }
591    
592     // stream methods, coded in a way intended to better isolate for
593     // maintenance purposes the small differences across forms.
594    
595     /**
596 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
597 dl 1.1 * pseudorandom {@code int} values.
598     *
599     * @param streamSize the number of values to generate
600     * @return a stream of pseudorandom {@code int} values
601     * @throws IllegalArgumentException if {@code streamSize} is
602 dl 1.7 * less than zero
603 dl 1.1 */
604     public IntStream ints(long streamSize) {
605     if (streamSize < 0L)
606     throw new IllegalArgumentException("negative Stream size");
607     return StreamSupport.intStream
608     (new RandomIntsSpliterator
609     (this, 0L, streamSize, Integer.MAX_VALUE, 0),
610     false);
611     }
612    
613     /**
614     * Returns an effectively unlimited stream of pseudorandom {@code int}
615     * values
616     *
617     * @implNote This method is implemented to be equivalent to {@code
618     * ints(Long.MAX_VALUE)}.
619     *
620     * @return a stream of pseudorandom {@code int} values
621     */
622     public IntStream ints() {
623     return StreamSupport.intStream
624     (new RandomIntsSpliterator
625     (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
626     false);
627     }
628    
629     /**
630 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
631 dl 1.1 * pseudorandom {@code int} values, each conforming to the given
632     * origin and bound.
633     *
634     * @param streamSize the number of values to generate
635     * @param randomNumberOrigin the origin of each random value
636     * @param randomNumberBound the bound of each random value
637     * @return a stream of pseudorandom {@code int} values,
638 dl 1.7 * each with the given origin and bound.
639 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
640 dl 1.7 * less than zero, or {@code randomNumberOrigin}
641 dl 1.1 * is greater than or equal to {@code randomNumberBound}
642     */
643     public IntStream ints(long streamSize, int randomNumberOrigin,
644     int randomNumberBound) {
645     if (streamSize < 0L)
646     throw new IllegalArgumentException("negative Stream size");
647     if (randomNumberOrigin >= randomNumberBound)
648     throw new IllegalArgumentException("bound must be greater than origin");
649     return StreamSupport.intStream
650     (new RandomIntsSpliterator
651     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
652     false);
653     }
654    
655     /**
656     * Returns an effectively unlimited stream of pseudorandom {@code
657     * int} values, each conforming to the given origin and bound.
658     *
659     * @implNote This method is implemented to be equivalent to {@code
660     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
661     *
662     * @param randomNumberOrigin the origin of each random value
663     * @param randomNumberBound the bound of each random value
664     * @return a stream of pseudorandom {@code int} values,
665 dl 1.7 * each with the given origin and bound.
666 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
667     * is greater than or equal to {@code randomNumberBound}
668     */
669     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
670     if (randomNumberOrigin >= randomNumberBound)
671     throw new IllegalArgumentException("bound must be greater than origin");
672     return StreamSupport.intStream
673     (new RandomIntsSpliterator
674     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
675     false);
676     }
677    
678     /**
679 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
680 dl 1.1 * pseudorandom {@code long} values.
681     *
682     * @param streamSize the number of values to generate
683 dl 1.7 * @return a stream of pseudorandom {@code long} values
684 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
685 dl 1.7 * less than zero
686 dl 1.1 */
687     public LongStream longs(long streamSize) {
688     if (streamSize < 0L)
689     throw new IllegalArgumentException("negative Stream size");
690     return StreamSupport.longStream
691     (new RandomLongsSpliterator
692     (this, 0L, streamSize, Long.MAX_VALUE, 0L),
693     false);
694     }
695    
696     /**
697     * Returns an effectively unlimited stream of pseudorandom {@code long}
698     * values.
699     *
700     * @implNote This method is implemented to be equivalent to {@code
701     * longs(Long.MAX_VALUE)}.
702     *
703     * @return a stream of pseudorandom {@code long} values
704     */
705     public LongStream longs() {
706     return StreamSupport.longStream
707     (new RandomLongsSpliterator
708     (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
709     false);
710     }
711    
712     /**
713 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
714 dl 1.1 * pseudorandom {@code long} values, each conforming to the
715     * given origin and bound.
716     *
717     * @param streamSize the number of values to generate
718     * @param randomNumberOrigin the origin of each random value
719     * @param randomNumberBound the bound of each random value
720     * @return a stream of pseudorandom {@code long} values,
721 dl 1.7 * each with the given origin and bound.
722 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
723 dl 1.7 * less than zero, or {@code randomNumberOrigin}
724 dl 1.1 * is greater than or equal to {@code randomNumberBound}
725     */
726     public LongStream longs(long streamSize, long randomNumberOrigin,
727     long randomNumberBound) {
728     if (streamSize < 0L)
729     throw new IllegalArgumentException("negative Stream size");
730     if (randomNumberOrigin >= randomNumberBound)
731     throw new IllegalArgumentException("bound must be greater than origin");
732     return StreamSupport.longStream
733     (new RandomLongsSpliterator
734     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
735     false);
736     }
737    
738     /**
739     * Returns an effectively unlimited stream of pseudorandom {@code
740     * long} values, each conforming to the given origin and bound.
741     *
742     * @implNote This method is implemented to be equivalent to {@code
743     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
744     *
745     * @param randomNumberOrigin the origin of each random value
746     * @param randomNumberBound the bound of each random value
747     * @return a stream of pseudorandom {@code long} values,
748 dl 1.7 * each with the given origin and bound.
749 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
750     * is greater than or equal to {@code randomNumberBound}
751     */
752     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
753     if (randomNumberOrigin >= randomNumberBound)
754     throw new IllegalArgumentException("bound must be greater than origin");
755     return StreamSupport.longStream
756     (new RandomLongsSpliterator
757     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
758     false);
759     }
760    
761     /**
762 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
763     * pseudorandom {@code double} values, each between zero
764     * (inclusive) and one (exclusive).
765 dl 1.1 *
766     * @param streamSize the number of values to generate
767     * @return a stream of {@code double} values
768     * @throws IllegalArgumentException if {@code streamSize} is
769 dl 1.7 * less than zero
770 dl 1.1 */
771     public DoubleStream doubles(long streamSize) {
772     if (streamSize < 0L)
773     throw new IllegalArgumentException("negative Stream size");
774     return StreamSupport.doubleStream
775     (new RandomDoublesSpliterator
776     (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
777     false);
778     }
779    
780     /**
781     * Returns an effectively unlimited stream of pseudorandom {@code
782 dl 1.7 * double} values, each between zero (inclusive) and one
783     * (exclusive).
784 dl 1.1 *
785     * @implNote This method is implemented to be equivalent to {@code
786     * doubles(Long.MAX_VALUE)}.
787     *
788     * @return a stream of pseudorandom {@code double} values
789     */
790     public DoubleStream doubles() {
791     return StreamSupport.doubleStream
792     (new RandomDoublesSpliterator
793     (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
794     false);
795     }
796    
797     /**
798 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
799 dl 1.1 * pseudorandom {@code double} values, each conforming to the
800     * given origin and bound.
801     *
802     * @param streamSize the number of values to generate
803     * @param randomNumberOrigin the origin of each random value
804     * @param randomNumberBound the bound of each random value
805     * @return a stream of pseudorandom {@code double} values,
806     * each with the given origin and bound.
807     * @throws IllegalArgumentException if {@code streamSize} is
808     * less than zero.
809     * @throws IllegalArgumentException if {@code randomNumberOrigin}
810     * is greater than or equal to {@code randomNumberBound}
811     */
812     public DoubleStream doubles(long streamSize, double randomNumberOrigin,
813     double randomNumberBound) {
814     if (streamSize < 0L)
815     throw new IllegalArgumentException("negative Stream size");
816 dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
817 dl 1.1 throw new IllegalArgumentException("bound must be greater than origin");
818     return StreamSupport.doubleStream
819     (new RandomDoublesSpliterator
820     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
821     false);
822     }
823    
824     /**
825     * Returns an effectively unlimited stream of pseudorandom {@code
826     * double} values, each conforming to the given origin and bound.
827     *
828     * @implNote This method is implemented to be equivalent to {@code
829     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
830     *
831     * @param randomNumberOrigin the origin of each random value
832     * @param randomNumberBound the bound of each random value
833     * @return a stream of pseudorandom {@code double} values,
834     * each with the given origin and bound.
835     * @throws IllegalArgumentException if {@code randomNumberOrigin}
836     * is greater than or equal to {@code randomNumberBound}
837     */
838     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
839 dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
840 dl 1.1 throw new IllegalArgumentException("bound must be greater than origin");
841     return StreamSupport.doubleStream
842     (new RandomDoublesSpliterator
843     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
844     false);
845     }
846    
847     /**
848     * Spliterator for int streams. We multiplex the four int
849 dl 1.7 * versions into one class by treating a bound less than origin as
850 dl 1.1 * unbounded, and also by treating "infinite" as equivalent to
851     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
852     * approach. The long and double versions of this class are
853     * identical except for types.
854     */
855     static class RandomIntsSpliterator implements Spliterator.OfInt {
856     final SplittableRandom rng;
857     long index;
858     final long fence;
859     final int origin;
860     final int bound;
861     RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
862     int origin, int bound) {
863     this.rng = rng; this.index = index; this.fence = fence;
864     this.origin = origin; this.bound = bound;
865     }
866    
867     public RandomIntsSpliterator trySplit() {
868     long i = index, m = (i + fence) >>> 1;
869     return (m <= i) ? null :
870     new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
871     }
872    
873     public long estimateSize() {
874     return fence - index;
875     }
876    
877     public int characteristics() {
878     return (Spliterator.SIZED | Spliterator.SUBSIZED |
879 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
880 dl 1.1 }
881    
882     public boolean tryAdvance(IntConsumer consumer) {
883     if (consumer == null) throw new NullPointerException();
884     long i = index, f = fence;
885     if (i < f) {
886     consumer.accept(rng.internalNextInt(origin, bound));
887     index = i + 1;
888     return true;
889     }
890     return false;
891     }
892    
893     public void forEachRemaining(IntConsumer consumer) {
894     if (consumer == null) throw new NullPointerException();
895     long i = index, f = fence;
896     if (i < f) {
897     index = f;
898     int o = origin, b = bound;
899     do {
900     consumer.accept(rng.internalNextInt(o, b));
901     } while (++i < f);
902     }
903     }
904     }
905    
906     /**
907     * Spliterator for long streams.
908     */
909     static class RandomLongsSpliterator implements Spliterator.OfLong {
910     final SplittableRandom rng;
911     long index;
912     final long fence;
913     final long origin;
914     final long bound;
915     RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
916     long origin, long bound) {
917     this.rng = rng; this.index = index; this.fence = fence;
918     this.origin = origin; this.bound = bound;
919     }
920    
921     public RandomLongsSpliterator trySplit() {
922     long i = index, m = (i + fence) >>> 1;
923     return (m <= i) ? null :
924     new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
925     }
926    
927     public long estimateSize() {
928     return fence - index;
929     }
930    
931     public int characteristics() {
932     return (Spliterator.SIZED | Spliterator.SUBSIZED |
933 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
934 dl 1.1 }
935    
936     public boolean tryAdvance(LongConsumer consumer) {
937     if (consumer == null) throw new NullPointerException();
938     long i = index, f = fence;
939     if (i < f) {
940     consumer.accept(rng.internalNextLong(origin, bound));
941     index = i + 1;
942     return true;
943     }
944     return false;
945     }
946    
947     public void forEachRemaining(LongConsumer consumer) {
948     if (consumer == null) throw new NullPointerException();
949     long i = index, f = fence;
950     if (i < f) {
951     index = f;
952     long o = origin, b = bound;
953     do {
954     consumer.accept(rng.internalNextLong(o, b));
955     } while (++i < f);
956     }
957     }
958    
959     }
960    
961     /**
962     * Spliterator for double streams.
963     */
964     static class RandomDoublesSpliterator implements Spliterator.OfDouble {
965     final SplittableRandom rng;
966     long index;
967     final long fence;
968     final double origin;
969     final double bound;
970     RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
971     double origin, double bound) {
972     this.rng = rng; this.index = index; this.fence = fence;
973     this.origin = origin; this.bound = bound;
974     }
975    
976     public RandomDoublesSpliterator trySplit() {
977     long i = index, m = (i + fence) >>> 1;
978     return (m <= i) ? null :
979     new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
980     }
981    
982     public long estimateSize() {
983     return fence - index;
984     }
985    
986     public int characteristics() {
987     return (Spliterator.SIZED | Spliterator.SUBSIZED |
988 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
989 dl 1.1 }
990    
991     public boolean tryAdvance(DoubleConsumer consumer) {
992     if (consumer == null) throw new NullPointerException();
993     long i = index, f = fence;
994     if (i < f) {
995     consumer.accept(rng.internalNextDouble(origin, bound));
996     index = i + 1;
997     return true;
998     }
999     return false;
1000     }
1001    
1002     public void forEachRemaining(DoubleConsumer consumer) {
1003     if (consumer == null) throw new NullPointerException();
1004     long i = index, f = fence;
1005     if (i < f) {
1006     index = f;
1007     double o = origin, b = bound;
1008     do {
1009     consumer.accept(rng.internalNextDouble(o, b));
1010     } while (++i < f);
1011     }
1012     }
1013     }
1014    
1015     }