ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.1
Committed: Wed Jul 10 15:40:19 2013 UTC (10 years, 9 months ago) by dl
Branch: MAIN
Log Message:
Initial version

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