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

File Contents

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