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