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 }