ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.18
Committed: Thu Aug 22 23:36:06 2013 UTC (10 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.17: +75 -55 lines
Log Message:
Optional SecureRandom initial seed

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