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