ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.24
Committed: Mon Oct 7 10:54:27 2013 UTC (10 years, 6 months ago) by dl
Branch: MAIN
Changes since 1.23: +11 -11 lines
Log Message:
incorporate review comments; undo miscommit

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