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