ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.20
Committed: Sat Aug 24 06:20:15 2013 UTC (10 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.19: +1 -1 lines
Log Message:
use actual name of system property in comment

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