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