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 }