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