ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.17
Committed: Tue Aug 13 23:34:47 2013 UTC (10 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.16: +5 -5 lines
Log Message:
untabify

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 jsr166 1.17 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.16 * @throws IllegalArgumentException if {@code bound} is not positive
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.16 * @throws IllegalArgumentException if {@code bound} is not positive
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.16 * @throws IllegalArgumentException if {@code bound} is not positive
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.16 * Returns a stream producing the given {@code streamSize} number
562     * of pseudorandom {@code int} values from this generator and/or
563     * one split from it.
564 dl 1.1 *
565     * @param streamSize the number of values to generate
566     * @return a stream of pseudorandom {@code int} values
567     * @throws IllegalArgumentException if {@code streamSize} is
568 dl 1.7 * less than zero
569 dl 1.1 */
570     public IntStream ints(long streamSize) {
571     if (streamSize < 0L)
572 dl 1.15 throw new IllegalArgumentException(BadSize);
573 dl 1.1 return StreamSupport.intStream
574     (new RandomIntsSpliterator
575     (this, 0L, streamSize, Integer.MAX_VALUE, 0),
576     false);
577     }
578    
579     /**
580     * Returns an effectively unlimited stream of pseudorandom {@code int}
581 dl 1.16 * values from this generator and/or one split from it.
582 dl 1.1 *
583     * @implNote This method is implemented to be equivalent to {@code
584     * ints(Long.MAX_VALUE)}.
585     *
586     * @return a stream of pseudorandom {@code int} values
587     */
588     public IntStream ints() {
589     return StreamSupport.intStream
590     (new RandomIntsSpliterator
591     (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
592     false);
593     }
594    
595     /**
596 dl 1.16 * Returns a stream producing the given {@code streamSize} number
597     * of pseudorandom {@code int} values, each conforming to the
598     * given origin and bound.
599 dl 1.1 *
600     * @param streamSize the number of values to generate
601     * @param randomNumberOrigin the origin of each random value
602     * @param randomNumberBound the bound of each random value
603     * @return a stream of pseudorandom {@code int} values,
604 jsr166 1.10 * each with the given origin and bound
605 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
606 dl 1.7 * less than zero, or {@code randomNumberOrigin}
607 dl 1.1 * is greater than or equal to {@code randomNumberBound}
608     */
609     public IntStream ints(long streamSize, int randomNumberOrigin,
610     int randomNumberBound) {
611     if (streamSize < 0L)
612 dl 1.15 throw new IllegalArgumentException(BadSize);
613 dl 1.1 if (randomNumberOrigin >= randomNumberBound)
614 dl 1.15 throw new IllegalArgumentException(BadRange);
615 dl 1.1 return StreamSupport.intStream
616     (new RandomIntsSpliterator
617     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
618     false);
619     }
620    
621     /**
622     * Returns an effectively unlimited stream of pseudorandom {@code
623     * int} values, each conforming to the given origin and bound.
624     *
625     * @implNote This method is implemented to be equivalent to {@code
626     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
627     *
628     * @param randomNumberOrigin the origin of each random value
629     * @param randomNumberBound the bound of each random value
630     * @return a stream of pseudorandom {@code int} values,
631 jsr166 1.10 * each with the given origin and bound
632 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
633     * is greater than or equal to {@code randomNumberBound}
634     */
635     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
636     if (randomNumberOrigin >= randomNumberBound)
637 dl 1.15 throw new IllegalArgumentException(BadRange);
638 dl 1.1 return StreamSupport.intStream
639     (new RandomIntsSpliterator
640     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
641     false);
642     }
643    
644     /**
645 dl 1.16 * Returns a stream producing the given {@code streamSize} number
646     * of pseudorandom {@code long} values from this generator and/or
647     * one split from it.
648 dl 1.1 *
649     * @param streamSize the number of values to generate
650 dl 1.7 * @return a stream of pseudorandom {@code long} values
651 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
652 dl 1.7 * less than zero
653 dl 1.1 */
654     public LongStream longs(long streamSize) {
655     if (streamSize < 0L)
656 dl 1.15 throw new IllegalArgumentException(BadSize);
657 dl 1.1 return StreamSupport.longStream
658     (new RandomLongsSpliterator
659     (this, 0L, streamSize, Long.MAX_VALUE, 0L),
660     false);
661     }
662    
663     /**
664 dl 1.16 * Returns an effectively unlimited stream of pseudorandom {@code
665     * long} values from this generator and/or one split from it.
666 dl 1.1 *
667     * @implNote This method is implemented to be equivalent to {@code
668     * longs(Long.MAX_VALUE)}.
669     *
670     * @return a stream of pseudorandom {@code long} values
671     */
672     public LongStream longs() {
673     return StreamSupport.longStream
674     (new RandomLongsSpliterator
675     (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
676     false);
677     }
678    
679     /**
680 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
681 dl 1.1 * pseudorandom {@code long} values, each conforming to the
682     * given origin and bound.
683     *
684     * @param streamSize the number of values to generate
685     * @param randomNumberOrigin the origin of each random value
686     * @param randomNumberBound the bound of each random value
687     * @return a stream of pseudorandom {@code long} values,
688 jsr166 1.10 * each with the given origin and bound
689 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
690 dl 1.7 * less than zero, or {@code randomNumberOrigin}
691 dl 1.1 * is greater than or equal to {@code randomNumberBound}
692     */
693     public LongStream longs(long streamSize, long randomNumberOrigin,
694     long randomNumberBound) {
695     if (streamSize < 0L)
696 dl 1.15 throw new IllegalArgumentException(BadSize);
697 dl 1.1 if (randomNumberOrigin >= randomNumberBound)
698 dl 1.15 throw new IllegalArgumentException(BadRange);
699 dl 1.1 return StreamSupport.longStream
700     (new RandomLongsSpliterator
701     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
702     false);
703     }
704    
705     /**
706     * Returns an effectively unlimited stream of pseudorandom {@code
707     * long} values, each conforming to the given origin and bound.
708     *
709     * @implNote This method is implemented to be equivalent to {@code
710     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
711     *
712     * @param randomNumberOrigin the origin of each random value
713     * @param randomNumberBound the bound of each random value
714     * @return a stream of pseudorandom {@code long} values,
715 jsr166 1.10 * each with the given origin and bound
716 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
717     * is greater than or equal to {@code randomNumberBound}
718     */
719     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
720     if (randomNumberOrigin >= randomNumberBound)
721 dl 1.15 throw new IllegalArgumentException(BadRange);
722 dl 1.1 return StreamSupport.longStream
723     (new RandomLongsSpliterator
724     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
725     false);
726     }
727    
728     /**
729 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
730     * pseudorandom {@code double} values, each between zero
731     * (inclusive) and one (exclusive).
732 dl 1.1 *
733     * @param streamSize the number of values to generate
734     * @return a stream of {@code double} values
735     * @throws IllegalArgumentException if {@code streamSize} is
736 dl 1.7 * less than zero
737 dl 1.1 */
738     public DoubleStream doubles(long streamSize) {
739     if (streamSize < 0L)
740 dl 1.15 throw new IllegalArgumentException(BadSize);
741 dl 1.1 return StreamSupport.doubleStream
742     (new RandomDoublesSpliterator
743     (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
744     false);
745     }
746    
747     /**
748     * Returns an effectively unlimited stream of pseudorandom {@code
749 dl 1.7 * double} values, each between zero (inclusive) and one
750     * (exclusive).
751 dl 1.1 *
752     * @implNote This method is implemented to be equivalent to {@code
753     * doubles(Long.MAX_VALUE)}.
754     *
755     * @return a stream of pseudorandom {@code double} values
756     */
757     public DoubleStream doubles() {
758     return StreamSupport.doubleStream
759     (new RandomDoublesSpliterator
760     (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
761     false);
762     }
763    
764     /**
765 dl 1.7 * Returns a stream producing the given {@code streamSize} number of
766 dl 1.1 * pseudorandom {@code double} values, each conforming to the
767     * given origin and bound.
768     *
769     * @param streamSize the number of values to generate
770     * @param randomNumberOrigin the origin of each random value
771     * @param randomNumberBound the bound of each random value
772     * @return a stream of pseudorandom {@code double} values,
773 jsr166 1.10 * each with the given origin and bound
774 dl 1.1 * @throws IllegalArgumentException if {@code streamSize} is
775 jsr166 1.10 * less than zero
776 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
777     * is greater than or equal to {@code randomNumberBound}
778     */
779     public DoubleStream doubles(long streamSize, double randomNumberOrigin,
780     double randomNumberBound) {
781     if (streamSize < 0L)
782 dl 1.15 throw new IllegalArgumentException(BadSize);
783 dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
784 dl 1.15 throw new IllegalArgumentException(BadRange);
785 dl 1.1 return StreamSupport.doubleStream
786     (new RandomDoublesSpliterator
787     (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
788     false);
789     }
790    
791     /**
792     * Returns an effectively unlimited stream of pseudorandom {@code
793     * double} values, each conforming to the given origin and bound.
794     *
795     * @implNote This method is implemented to be equivalent to {@code
796     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
797     *
798     * @param randomNumberOrigin the origin of each random value
799     * @param randomNumberBound the bound of each random value
800     * @return a stream of pseudorandom {@code double} values,
801 jsr166 1.10 * each with the given origin and bound
802 dl 1.1 * @throws IllegalArgumentException if {@code randomNumberOrigin}
803     * is greater than or equal to {@code randomNumberBound}
804     */
805     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
806 dl 1.7 if (!(randomNumberOrigin < randomNumberBound))
807 dl 1.15 throw new IllegalArgumentException(BadRange);
808 dl 1.1 return StreamSupport.doubleStream
809     (new RandomDoublesSpliterator
810     (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
811     false);
812     }
813    
814     /**
815     * Spliterator for int streams. We multiplex the four int
816 dl 1.7 * versions into one class by treating a bound less than origin as
817 dl 1.1 * unbounded, and also by treating "infinite" as equivalent to
818     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
819     * approach. The long and double versions of this class are
820     * identical except for types.
821     */
822 dl 1.11 static final class RandomIntsSpliterator implements Spliterator.OfInt {
823 dl 1.1 final SplittableRandom rng;
824     long index;
825     final long fence;
826     final int origin;
827     final int bound;
828     RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
829     int origin, int bound) {
830     this.rng = rng; this.index = index; this.fence = fence;
831     this.origin = origin; this.bound = bound;
832     }
833    
834     public RandomIntsSpliterator trySplit() {
835     long i = index, m = (i + fence) >>> 1;
836     return (m <= i) ? null :
837     new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
838     }
839    
840     public long estimateSize() {
841     return fence - index;
842     }
843    
844     public int characteristics() {
845     return (Spliterator.SIZED | Spliterator.SUBSIZED |
846 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
847 dl 1.1 }
848    
849     public boolean tryAdvance(IntConsumer consumer) {
850     if (consumer == null) throw new NullPointerException();
851     long i = index, f = fence;
852     if (i < f) {
853     consumer.accept(rng.internalNextInt(origin, bound));
854     index = i + 1;
855     return true;
856     }
857     return false;
858     }
859    
860     public void forEachRemaining(IntConsumer consumer) {
861     if (consumer == null) throw new NullPointerException();
862     long i = index, f = fence;
863     if (i < f) {
864     index = f;
865 dl 1.15 SplittableRandom r = rng;
866 dl 1.1 int o = origin, b = bound;
867     do {
868 dl 1.15 consumer.accept(r.internalNextInt(o, b));
869 dl 1.1 } while (++i < f);
870     }
871     }
872     }
873    
874     /**
875     * Spliterator for long streams.
876     */
877 dl 1.11 static final class RandomLongsSpliterator implements Spliterator.OfLong {
878 dl 1.1 final SplittableRandom rng;
879     long index;
880     final long fence;
881     final long origin;
882     final long bound;
883     RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
884     long origin, long bound) {
885     this.rng = rng; this.index = index; this.fence = fence;
886     this.origin = origin; this.bound = bound;
887     }
888    
889     public RandomLongsSpliterator trySplit() {
890     long i = index, m = (i + fence) >>> 1;
891     return (m <= i) ? null :
892     new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
893     }
894    
895     public long estimateSize() {
896     return fence - index;
897     }
898    
899     public int characteristics() {
900     return (Spliterator.SIZED | Spliterator.SUBSIZED |
901 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
902 dl 1.1 }
903    
904     public boolean tryAdvance(LongConsumer consumer) {
905     if (consumer == null) throw new NullPointerException();
906     long i = index, f = fence;
907     if (i < f) {
908     consumer.accept(rng.internalNextLong(origin, bound));
909     index = i + 1;
910     return true;
911     }
912     return false;
913     }
914    
915     public void forEachRemaining(LongConsumer consumer) {
916     if (consumer == null) throw new NullPointerException();
917     long i = index, f = fence;
918     if (i < f) {
919     index = f;
920 dl 1.15 SplittableRandom r = rng;
921 dl 1.1 long o = origin, b = bound;
922     do {
923 dl 1.15 consumer.accept(r.internalNextLong(o, b));
924 dl 1.1 } while (++i < f);
925     }
926     }
927    
928     }
929    
930     /**
931     * Spliterator for double streams.
932     */
933 dl 1.11 static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
934 dl 1.1 final SplittableRandom rng;
935     long index;
936     final long fence;
937     final double origin;
938     final double bound;
939     RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
940     double origin, double bound) {
941     this.rng = rng; this.index = index; this.fence = fence;
942     this.origin = origin; this.bound = bound;
943     }
944    
945     public RandomDoublesSpliterator trySplit() {
946     long i = index, m = (i + fence) >>> 1;
947     return (m <= i) ? null :
948     new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
949     }
950    
951     public long estimateSize() {
952     return fence - index;
953     }
954    
955     public int characteristics() {
956     return (Spliterator.SIZED | Spliterator.SUBSIZED |
957 dl 1.4 Spliterator.NONNULL | Spliterator.IMMUTABLE);
958 dl 1.1 }
959    
960     public boolean tryAdvance(DoubleConsumer consumer) {
961     if (consumer == null) throw new NullPointerException();
962     long i = index, f = fence;
963     if (i < f) {
964     consumer.accept(rng.internalNextDouble(origin, bound));
965     index = i + 1;
966     return true;
967     }
968     return false;
969     }
970    
971     public void forEachRemaining(DoubleConsumer consumer) {
972     if (consumer == null) throw new NullPointerException();
973     long i = index, f = fence;
974     if (i < f) {
975     index = f;
976 dl 1.15 SplittableRandom r = rng;
977 dl 1.1 double o = origin, b = bound;
978     do {
979 dl 1.15 consumer.accept(r.internalNextDouble(o, b));
980 dl 1.1 } while (++i < f);
981     }
982     }
983     }
984    
985     }