ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/SplittableRandom.java
Revision: 1.22
Committed: Fri Sep 20 09:38:07 2013 UTC (10 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.21: +0 -6 lines
Log Message:
Remove unused method

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