ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.15
Committed: Fri Aug 9 12:12:10 2013 UTC (10 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.14: +129 -204 lines
Log Message:
Improved algorithm

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