ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ThreadLocalRandom.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ThreadLocalRandom.java (file contents):
Revision 1.18 by jsr166, Fri Jul 19 19:34:43 2013 UTC vs.
Revision 1.19 by dl, Fri Aug 9 12:13:14 2013 UTC

# Line 8 | Line 8 | package java.util.concurrent;
8  
9   import java.io.ObjectStreamField;
10   import java.util.Random;
11 + import java.util.Spliterator;
12   import java.util.concurrent.atomic.AtomicInteger;
13   import java.util.concurrent.atomic.AtomicLong;
14 + import java.util.function.DoubleConsumer;
15 + import java.util.function.IntConsumer;
16 + import java.util.function.LongConsumer;
17 + import java.util.stream.DoubleStream;
18 + import java.util.stream.IntStream;
19 + import java.util.stream.LongStream;
20 + import java.util.stream.StreamSupport;
21  
22   /**
23   * A random number generator isolated to the current thread.  Like the
# Line 53 | Line 61 | public class ThreadLocalRandom extends R
61       * application-level overhead and footprint of most concurrent
62       * programs.
63       *
64 +     * Even though this class subclasses java.util.Random, it uses the
65 +     * same basic algorithm as java.util.SplittableRandom.  (See its
66 +     * internal documentation for explanations, which are not repeated
67 +     * here.)  Because ThreadLocalRandoms are not splittable
68 +     * though, we use only a single 64bit gamma.
69 +     *
70       * Because this class is in a different package than class Thread,
71       * field access methods use Unsafe to bypass access control rules.
72 <     * The base functionality of Random methods is conveniently
73 <     * isolated in method next(bits), that just reads and writes the
74 <     * Thread field rather than its own field.  However, to conform to
75 <     * the requirements of the Random superclass constructor, the
76 <     * common static ThreadLocalRandom maintains an "initialized"
77 <     * field for the sake of rejecting user calls to setSeed while
78 <     * still allowing a call from constructor.  Note that
79 <     * serialization is completely unnecessary because there is only a
80 <     * static singleton.  But we generate a serial form containing
81 <     * "rnd" and "initialized" fields to ensure compatibility across
82 <     * versions.
83 <     *
70 <     * Per-thread initialization is similar to that in the no-arg
71 <     * Random constructor, but we avoid correlation among not only
72 <     * initial seeds of those created in different threads, but also
73 <     * those created using class Random itself; while at the same time
74 <     * not changing any statistical properties.  So we use the same
75 <     * underlying multiplicative sequence, but start the sequence far
76 <     * away from the base version, and then merge (xor) current time
77 <     * and per-thread probe bits to generate initial values.
72 >     * To conform to the requirements of the Random superclass
73 >     * constructor, the common static ThreadLocalRandom maintains an
74 >     * "initialized" field for the sake of rejecting user calls to
75 >     * setSeed while still allowing a call from constructor.  Note
76 >     * that serialization is completely unnecessary because there is
77 >     * only a static singleton.  But we generate a serial form
78 >     * containing "rnd" and "initialized" fields to ensure
79 >     * compatibility across versions.
80 >     *
81 >     * Implementations of non-core methods are mostly the same as in
82 >     * SplittableRandom, that were in part derived from a previous
83 >     * version of this class.
84       *
85       * The nextLocalGaussian ThreadLocal supports the very rarely used
86       * nextGaussian method by providing a holder for the second of a
# Line 83 | Line 89 | public class ThreadLocalRandom extends R
89       * but we provide identical statistical properties.
90       */
91  
92 <    // same constants as Random, but must be redeclared because private
93 <    private static final long multiplier = 0x5DEECE66DL;
94 <    private static final long addend = 0xBL;
89 <    private static final long mask = (1L << 48) - 1;
90 <    private static final int PROBE_INCREMENT = 0x61c88647;
92 >    /** Generates per-thread initialization/probe field */
93 >    private static final AtomicInteger probeGenerator =
94 >        new AtomicInteger();
95  
96 <    /** Generates the basis for per-thread initial seed values */
96 >    /**
97 >     * The next seed for default constructors.
98 >     */
99      private static final AtomicLong seedGenerator =
100 <        new AtomicLong(1269533684904616924L);
100 >        new AtomicLong(mix64(System.currentTimeMillis()) ^
101 >                       mix64(System.nanoTime()));
102  
103 <    /** Generates per-thread initialization/probe field */
104 <    private static final AtomicInteger probeGenerator =
105 <        new AtomicInteger(0xe80f8647);
103 >    /**
104 >     * The seed increment
105 >     */
106 >    private static final long GAMMA = 0x9e3779b97f4a7c15L;
107 >
108 >    /**
109 >     * The increment for generating probe values
110 >     */
111 >    private static final int PROBE_INCREMENT = 0x9e3779b9;
112 >
113 >    /**
114 >     * The increment of seedGenerator per new instance
115 >     */
116 >    private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
117 >
118 >    // Constants from SplittableRandom
119 >    private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
120 >    private static final float  FLOAT_UNIT  = 1.0f / (1 << 24);
121  
122      /** Rarely-used holder for the second of a pair of Gaussians */
123      private static final ThreadLocal<Double> nextLocalGaussian =
124          new ThreadLocal<Double>();
125  
126 +    private static long mix64(long z) {
127 +        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
128 +        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
129 +        return z ^ (z >>> 33);
130 +    }
131 +
132 +    private static int mix32(long z) {
133 +        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
134 +        return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
135 +    }
136 +
137      /**
138       * Field used only during singleton initialization.
139       * True when constructor completes.
# Line 123 | Line 156 | public class ThreadLocalRandom extends R
156       * rely on (static) atomic generators to initialize the values.
157       */
158      static final void localInit() {
159 <        int p = probeGenerator.getAndAdd(PROBE_INCREMENT);
159 >        int p = probeGenerator.addAndGet(PROBE_INCREMENT);
160          int probe = (p == 0) ? 1 : p; // skip 0
161 <        long current, next;
129 <        do { // same sequence as j.u.Random but different initial value
130 <            current = seedGenerator.get();
131 <            next = current * 181783497276652981L;
132 <        } while (!seedGenerator.compareAndSet(current, next));
133 <        long r = next ^ ((long)probe << 32) ^ System.nanoTime();
161 >        long seed = mix64(seedGenerator.getAndAdd(SEEDER_INCREMENT));
162          Thread t = Thread.currentThread();
163 <        UNSAFE.putLong(t, SEED, r);
163 >        UNSAFE.putLong(t, SEED, seed);
164          UNSAFE.putInt(t, PROBE, probe);
165      }
166  
# Line 159 | Line 187 | public class ThreadLocalRandom extends R
187              throw new UnsupportedOperationException();
188      }
189  
190 <    protected int next(int bits) {
190 >    final long nextSeed() {
191          Thread t; long r; // read and update per-thread seed
192 <        UNSAFE.putLong
193 <            (t = Thread.currentThread(), SEED,
194 <             r = (UNSAFE.getLong(t, SEED) * multiplier + addend) & mask);
195 <        return (int) (r >>> (48-bits));
192 >        UNSAFE.putLong(t = Thread.currentThread(), SEED,
193 >                       r = UNSAFE.getLong(t, SEED) + GAMMA);
194 >        return r;
195 >    }
196 >
197 >    // We must define this, but never use it.
198 >    protected int next(int bits) {
199 >        return (int)(mix64(nextSeed()) >>> (64 - bits));
200      }
201  
202 +    // IllegalArgumentException messages
203 +    static final String BadBound = "bound must be positive";
204 +    static final String BadRange = "bound must be greater than origin";
205 +    static final String BadSize  = "size must be non-negative";
206 +
207      /**
208 <     * Returns a pseudorandom, uniformly distributed value between the
209 <     * given least value (inclusive) and bound (exclusive).
208 >     * The form of nextLong used by LongStream Spliterators.  If
209 >     * origin is greater than bound, acts as unbounded form of
210 >     * nextLong, else as bounded form.
211       *
212 <     * @param least the least value returned
213 <     * @param bound the upper bound (exclusive)
214 <     * @return the next value
215 <     * @throws IllegalArgumentException if least greater than or equal
216 <     * to bound
212 >     * @param origin the least value, unless greater than bound
213 >     * @param bound the upper bound (exclusive), must not equal origin
214 >     * @return a pseudorandom value
215 >     */
216 >    final long internalNextLong(long origin, long bound) {
217 >        long r = mix64(nextSeed());
218 >        if (origin < bound) {
219 >            long n = bound - origin, m = n - 1;
220 >            if ((n & m) == 0L)  // power of two
221 >                r = (r & m) + origin;
222 >            else if (n > 0L) {  // reject over-represented candidates
223 >                for (long u = r >>> 1;            // ensure nonnegative
224 >                     u + m - (r = u % n) < 0L;    // rejection check
225 >                     u = mix64(nextSeed()) >>> 1) // retry
226 >                    ;
227 >                r += origin;
228 >            }
229 >            else {              // range not representable as long
230 >                while (r < origin || r >= bound)
231 >                    r = mix64(nextSeed());
232 >            }
233 >        }
234 >        return r;
235 >    }
236 >
237 >    /**
238 >     * The form of nextInt used by IntStream Spliterators.
239 >     * Exactly the same as long version, except for types.
240 >     *
241 >     * @param origin the least value, unless greater than bound
242 >     * @param bound the upper bound (exclusive), must not equal origin
243 >     * @return a pseudorandom value
244 >     */
245 >    final int internalNextInt(int origin, int bound) {
246 >        int r = mix32(nextSeed());
247 >        if (origin < bound) {
248 >            int n = bound - origin, m = n - 1;
249 >            if ((n & m) == 0)
250 >                r = (r & m) + origin;
251 >            else if (n > 0) {
252 >                for (int u = r >>> 1;
253 >                     u + m - (r = u % n) < 0;
254 >                     u = mix32(nextSeed()) >>> 1)
255 >                    ;
256 >                r += origin;
257 >            }
258 >            else {
259 >                while (r < origin || r >= bound)
260 >                    r = mix32(nextSeed());
261 >            }
262 >        }
263 >        return r;
264 >    }
265 >
266 >    /**
267 >     * The form of nextDouble used by DoubleStream Spliterators.
268 >     *
269 >     * @param origin the least value, unless greater than bound
270 >     * @param bound the upper bound (exclusive), must not equal origin
271 >     * @return a pseudorandom value
272 >     */
273 >    final double internalNextDouble(double origin, double bound) {
274 >        double r = (nextLong() >>> 11) * DOUBLE_UNIT;
275 >        if (origin < bound) {
276 >            r = r * (bound - origin) + origin;
277 >            if (r >= bound) // correct for rounding
278 >                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
279 >        }
280 >        return r;
281 >    }
282 >
283 >    /**
284 >     * Returns a pseudorandom {@code int} value.
285 >     *
286 >     * @return a pseudorandom {@code int} value
287       */
288 <    public int nextInt(int least, int bound) {
289 <        if (least >= bound)
182 <            throw new IllegalArgumentException();
183 <        return nextInt(bound - least) + least;
288 >    public int nextInt() {
289 >        return mix32(nextSeed());
290      }
291  
292      /**
293 <     * Returns a pseudorandom, uniformly distributed value
294 <     * between 0 (inclusive) and the specified value (exclusive).
293 >     * Returns a pseudorandom {@code int} value between zero (inclusive)
294 >     * and the specified bound (exclusive).
295       *
296 <     * @param n the bound on the random number to be returned.  Must be
296 >     * @param bound the bound on the random number to be returned.  Must be
297       *        positive.
298 <     * @return the next value
299 <     * @throws IllegalArgumentException if n is not positive
298 >     * @return a pseudorandom {@code int} value between zero
299 >     *         (inclusive) and the bound (exclusive)
300 >     * @throws IllegalArgumentException if the bound is less than zero
301       */
302 <    public long nextLong(long n) {
303 <        if (n <= 0)
304 <            throw new IllegalArgumentException("n must be positive");
305 <        // Divide n by two until small enough for nextInt. On each
306 <        // iteration (at most 31 of them but usually much less),
307 <        // randomly choose both whether to include high bit in result
308 <        // (offset) and whether to continue with the lower vs upper
309 <        // half (which makes a difference only if odd).
310 <        long offset = 0;
311 <        while (n >= Integer.MAX_VALUE) {
312 <            int bits = next(2);
313 <            long half = n >>> 1;
207 <            long nextn = ((bits & 2) == 0) ? half : n - half;
208 <            if ((bits & 1) == 0)
209 <                offset += n - nextn;
210 <            n = nextn;
302 >    public int nextInt(int bound) {
303 >        if (bound <= 0)
304 >            throw new IllegalArgumentException(BadBound);
305 >        int r = mix32(nextSeed());
306 >        int m = bound - 1;
307 >        if ((bound & m) == 0) // power of two
308 >            r &= m;
309 >        else { // reject over-represented candidates
310 >            for (int u = r >>> 1;
311 >                 u + m - (r = u % bound) < 0;
312 >                 u = mix32(nextSeed()) >>> 1)
313 >                ;
314          }
315 <        return offset + nextInt((int) n);
315 >        return r;
316      }
317  
318      /**
319 <     * Returns a pseudorandom, uniformly distributed value between the
320 <     * given least value (inclusive) and bound (exclusive).
319 >     * Returns a pseudorandom {@code int} value between the specified
320 >     * origin (inclusive) and the specified bound (exclusive).
321       *
322 <     * @param least the least value returned
322 >     * @param origin the least value returned
323       * @param bound the upper bound (exclusive)
324 <     * @return the next value
325 <     * @throws IllegalArgumentException if least greater than or equal
326 <     * to bound
324 >     * @return a pseudorandom {@code int} value between the origin
325 >     *         (inclusive) and the bound (exclusive)
326 >     * @throws IllegalArgumentException if {@code origin} is greater than
327 >     *         or equal to {@code bound}
328       */
329 <    public long nextLong(long least, long bound) {
330 <        if (least >= bound)
331 <            throw new IllegalArgumentException();
332 <        return nextLong(bound - least) + least;
329 >    public int nextInt(int origin, int bound) {
330 >        if (origin >= bound)
331 >            throw new IllegalArgumentException(BadRange);
332 >        return internalNextInt(origin, bound);
333      }
334  
335      /**
336 <     * Returns a pseudorandom, uniformly distributed {@code double} value
233 <     * between 0 (inclusive) and the specified value (exclusive).
336 >     * Returns a pseudorandom {@code long} value.
337       *
338 <     * @param n the bound on the random number to be returned.  Must be
338 >     * @return a pseudorandom {@code long} value
339 >     */
340 >    public long nextLong() {
341 >        return mix64(nextSeed());
342 >    }
343 >
344 >    /**
345 >     * Returns a pseudorandom {@code long} value between zero (inclusive)
346 >     * and the specified bound (exclusive).
347 >     *
348 >     * @param bound the bound on the random number to be returned.  Must be
349       *        positive.
350 <     * @return the next value
351 <     * @throws IllegalArgumentException if n is not positive
350 >     * @return a pseudorandom {@code long} value between zero
351 >     *         (inclusive) and the bound (exclusive)
352 >     * @throws IllegalArgumentException if {@code bound} is less than zero
353       */
354 <    public double nextDouble(double n) {
355 <        if (n <= 0)
356 <            throw new IllegalArgumentException("n must be positive");
357 <        return nextDouble() * n;
354 >    public long nextLong(long bound) {
355 >        if (bound <= 0)
356 >            throw new IllegalArgumentException(BadBound);
357 >        long r = mix64(nextSeed());
358 >        long m = bound - 1;
359 >        if ((bound & m) == 0L) // power of two
360 >            r &= m;
361 >        else { // reject over-represented candidates
362 >            for (long u = r >>> 1;
363 >                 u + m - (r = u % bound) < 0L;
364 >                 u = mix64(nextSeed()) >>> 1)
365 >                ;
366 >        }
367 >        return r;
368      }
369  
370      /**
371 <     * Returns a pseudorandom, uniformly distributed value between the
372 <     * given least value (inclusive) and bound (exclusive).
371 >     * Returns a pseudorandom {@code long} value between the specified
372 >     * origin (inclusive) and the specified bound (exclusive).
373       *
374 <     * @param least the least value returned
374 >     * @param origin the least value returned
375       * @param bound the upper bound (exclusive)
376 <     * @return the next value
377 <     * @throws IllegalArgumentException if least greater than or equal
378 <     * to bound
379 <     */
380 <    public double nextDouble(double least, double bound) {
381 <        if (least >= bound)
382 <            throw new IllegalArgumentException();
383 <        return nextDouble() * (bound - least) + least;
376 >     * @return a pseudorandom {@code long} value between the origin
377 >     *         (inclusive) and the bound (exclusive)
378 >     * @throws IllegalArgumentException if {@code origin} is greater than
379 >     *         or equal to {@code bound}
380 >     */
381 >    public long nextLong(long origin, long bound) {
382 >        if (origin >= bound)
383 >            throw new IllegalArgumentException(BadRange);
384 >        return internalNextLong(origin, bound);
385 >    }
386 >
387 >    /**
388 >     * Returns a pseudorandom {@code double} value between zero
389 >     * (inclusive) and one (exclusive).
390 >     *
391 >     * @return a pseudorandom {@code double} value between zero
392 >     * (inclusive) and one (exclusive)
393 >     */
394 >    public double nextDouble() {
395 >        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
396 >    }
397 >
398 >    /**
399 >     * Returns a pseudorandom {@code double} value between 0.0
400 >     * (inclusive) and the specified bound (exclusive).
401 >     *
402 >     * @param bound the bound on the random number to be returned.  Must be
403 >     *        positive.
404 >     * @return a pseudorandom {@code double} value between zero
405 >     *         (inclusive) and the bound (exclusive)
406 >     * @throws IllegalArgumentException if {@code bound} is less than zero
407 >     */
408 >    public double nextDouble(double bound) {
409 >        if (!(bound > 0.0))
410 >            throw new IllegalArgumentException(BadBound);
411 >        double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
412 >        return (result < bound) ?  result : // correct for rounding
413 >            Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
414 >    }
415 >
416 >    /**
417 >     * Returns a pseudorandom {@code double} value between the specified
418 >     * origin (inclusive) and bound (exclusive).
419 >     *
420 >     * @param origin the least value returned
421 >     * @param bound the upper bound
422 >     * @return a pseudorandom {@code double} value between the origin
423 >     *         (inclusive) and the bound (exclusive)
424 >     * @throws IllegalArgumentException if {@code origin} is greater than
425 >     *         or equal to {@code bound}
426 >     */
427 >    public double nextDouble(double origin, double bound) {
428 >        if (!(origin < bound))
429 >            throw new IllegalArgumentException(BadRange);
430 >        return internalNextDouble(origin, bound);
431 >    }
432 >
433 >    /**
434 >     * Returns a pseudorandom {@code boolean} value.
435 >     *
436 >     * @return a pseudorandom {@code boolean} value
437 >     */
438 >    public boolean nextBoolean() {
439 >        return mix32(nextSeed()) < 0;
440 >    }
441 >
442 >    /**
443 >     * Returns a pseudorandom {@code float} value between zero
444 >     * (inclusive) and one (exclusive).
445 >     *
446 >     * @return a pseudorandom {@code float} value between zero
447 >     * (inclusive) and one (exclusive)
448 >     */
449 >    public float nextFloat() {
450 >        return (mix32(nextSeed()) >>> 8) * FLOAT_UNIT;
451      }
452  
453      public double nextGaussian() {
# Line 277 | Line 468 | public class ThreadLocalRandom extends R
468          return v1 * multiplier;
469      }
470  
471 +    @Override
472 +    public DoubleStream gaussians() {
473 +        return DoubleStream.generate(() -> current().nextGaussian());
474 +    }
475 +
476 +    // stream methods, coded in a way intended to better isolate for
477 +    // maintenance purposes the small differences across forms.
478 +
479 +    /**
480 +     * Returns a stream producing the given {@code streamSize} number of
481 +     * pseudorandom {@code int} values.
482 +     *
483 +     * @param streamSize the number of values to generate
484 +     * @return a stream of pseudorandom {@code int} values
485 +     * @throws IllegalArgumentException if {@code streamSize} is
486 +     *         less than zero
487 +     */
488 +    public IntStream ints(long streamSize) {
489 +        if (streamSize < 0L)
490 +            throw new IllegalArgumentException(BadSize);
491 +        return StreamSupport.intStream
492 +            (new RandomIntsSpliterator
493 +             (0L, streamSize, Integer.MAX_VALUE, 0),
494 +             false);
495 +    }
496 +
497 +    /**
498 +     * Returns an effectively unlimited stream of pseudorandom {@code int}
499 +     * values.
500 +     *
501 +     * @implNote This method is implemented to be equivalent to {@code
502 +     * ints(Long.MAX_VALUE)}.
503 +     *
504 +     * @return a stream of pseudorandom {@code int} values
505 +     */
506 +    public IntStream ints() {
507 +        return StreamSupport.intStream
508 +            (new RandomIntsSpliterator
509 +             (0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
510 +             false);
511 +    }
512 +
513 +    /**
514 +     * Returns a stream producing the given {@code streamSize} number of
515 +     * pseudorandom {@code int} values, each conforming to the given
516 +     * origin and bound.
517 +     *
518 +     * @param streamSize the number of values to generate
519 +     * @param randomNumberOrigin the origin of each random value
520 +     * @param randomNumberBound the bound of each random value
521 +     * @return a stream of pseudorandom {@code int} values,
522 +     *         each with the given origin and bound
523 +     * @throws IllegalArgumentException if {@code streamSize} is
524 +     *         less than zero, or {@code randomNumberOrigin}
525 +     *         is greater than or equal to {@code randomNumberBound}
526 +     */
527 +    public IntStream ints(long streamSize, int randomNumberOrigin,
528 +                          int randomNumberBound) {
529 +        if (streamSize < 0L)
530 +            throw new IllegalArgumentException(BadSize);
531 +        if (randomNumberOrigin >= randomNumberBound)
532 +            throw new IllegalArgumentException(BadRange);
533 +        return StreamSupport.intStream
534 +            (new RandomIntsSpliterator
535 +             (0L, streamSize, randomNumberOrigin, randomNumberBound),
536 +             false);
537 +    }
538 +
539 +    /**
540 +     * Returns an effectively unlimited stream of pseudorandom {@code
541 +     * int} values, each conforming to the given origin and bound.
542 +     *
543 +     * @implNote This method is implemented to be equivalent to {@code
544 +     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
545 +     *
546 +     * @param randomNumberOrigin the origin of each random value
547 +     * @param randomNumberBound the bound of each random value
548 +     * @return a stream of pseudorandom {@code int} values,
549 +     *         each with the given origin and bound
550 +     * @throws IllegalArgumentException if {@code randomNumberOrigin}
551 +     *         is greater than or equal to {@code randomNumberBound}
552 +     */
553 +    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
554 +        if (randomNumberOrigin >= randomNumberBound)
555 +            throw new IllegalArgumentException(BadRange);
556 +        return StreamSupport.intStream
557 +            (new RandomIntsSpliterator
558 +             (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
559 +             false);
560 +    }
561 +
562 +    /**
563 +     * Returns a stream producing the given {@code streamSize} number of
564 +     * pseudorandom {@code long} values.
565 +     *
566 +     * @param streamSize the number of values to generate
567 +     * @return a stream of pseudorandom {@code long} values
568 +     * @throws IllegalArgumentException if {@code streamSize} is
569 +     *         less than zero
570 +     */
571 +    public LongStream longs(long streamSize) {
572 +        if (streamSize < 0L)
573 +            throw new IllegalArgumentException(BadSize);
574 +        return StreamSupport.longStream
575 +            (new RandomLongsSpliterator
576 +             (0L, streamSize, Long.MAX_VALUE, 0L),
577 +             false);
578 +    }
579 +
580 +    /**
581 +     * Returns an effectively unlimited stream of pseudorandom {@code long}
582 +     * values.
583 +     *
584 +     * @implNote This method is implemented to be equivalent to {@code
585 +     * longs(Long.MAX_VALUE)}.
586 +     *
587 +     * @return a stream of pseudorandom {@code long} values
588 +     */
589 +    public LongStream longs() {
590 +        return StreamSupport.longStream
591 +            (new RandomLongsSpliterator
592 +             (0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
593 +             false);
594 +    }
595 +
596 +    /**
597 +     * Returns a stream producing the given {@code streamSize} number of
598 +     * pseudorandom {@code long} values, each conforming to the
599 +     * given origin and bound.
600 +     *
601 +     * @param streamSize the number of values to generate
602 +     * @param randomNumberOrigin the origin of each random value
603 +     * @param randomNumberBound the bound of each random value
604 +     * @return a stream of pseudorandom {@code long} values,
605 +     *         each with the given origin and bound
606 +     * @throws IllegalArgumentException if {@code streamSize} is
607 +     *         less than zero, or {@code randomNumberOrigin}
608 +     *         is greater than or equal to {@code randomNumberBound}
609 +     */
610 +    public LongStream longs(long streamSize, long randomNumberOrigin,
611 +                            long randomNumberBound) {
612 +        if (streamSize < 0L)
613 +            throw new IllegalArgumentException(BadSize);
614 +        if (randomNumberOrigin >= randomNumberBound)
615 +            throw new IllegalArgumentException(BadRange);
616 +        return StreamSupport.longStream
617 +            (new RandomLongsSpliterator
618 +             (0L, streamSize, randomNumberOrigin, randomNumberBound),
619 +             false);
620 +    }
621 +
622 +    /**
623 +     * Returns an effectively unlimited stream of pseudorandom {@code
624 +     * long} values, each conforming to the given origin and bound.
625 +     *
626 +     * @implNote This method is implemented to be equivalent to {@code
627 +     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
628 +     *
629 +     * @param randomNumberOrigin the origin of each random value
630 +     * @param randomNumberBound the bound of each random value
631 +     * @return a stream of pseudorandom {@code long} values,
632 +     *         each with the given origin and bound
633 +     * @throws IllegalArgumentException if {@code randomNumberOrigin}
634 +     *         is greater than or equal to {@code randomNumberBound}
635 +     */
636 +    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
637 +        if (randomNumberOrigin >= randomNumberBound)
638 +            throw new IllegalArgumentException(BadRange);
639 +        return StreamSupport.longStream
640 +            (new RandomLongsSpliterator
641 +             (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
642 +             false);
643 +    }
644 +
645 +    /**
646 +     * Returns a stream producing the given {@code streamSize} number of
647 +     * pseudorandom {@code double} values, each between zero
648 +     * (inclusive) and one (exclusive).
649 +     *
650 +     * @param streamSize the number of values to generate
651 +     * @return a stream of {@code double} values
652 +     * @throws IllegalArgumentException if {@code streamSize} is
653 +     *         less than zero
654 +     */
655 +    public DoubleStream doubles(long streamSize) {
656 +        if (streamSize < 0L)
657 +            throw new IllegalArgumentException(BadSize);
658 +        return StreamSupport.doubleStream
659 +            (new RandomDoublesSpliterator
660 +             (0L, streamSize, Double.MAX_VALUE, 0.0),
661 +             false);
662 +    }
663 +
664 +    /**
665 +     * Returns an effectively unlimited stream of pseudorandom {@code
666 +     * double} values, each between zero (inclusive) and one
667 +     * (exclusive).
668 +     *
669 +     * @implNote This method is implemented to be equivalent to {@code
670 +     * doubles(Long.MAX_VALUE)}.
671 +     *
672 +     * @return a stream of pseudorandom {@code double} values
673 +     */
674 +    public DoubleStream doubles() {
675 +        return StreamSupport.doubleStream
676 +            (new RandomDoublesSpliterator
677 +             (0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
678 +             false);
679 +    }
680 +
681 +    /**
682 +     * Returns a stream producing the given {@code streamSize} number of
683 +     * pseudorandom {@code double} values, each conforming to the
684 +     * given origin and bound.
685 +     *
686 +     * @param streamSize the number of values to generate
687 +     * @param randomNumberOrigin the origin of each random value
688 +     * @param randomNumberBound the bound of each random value
689 +     * @return a stream of pseudorandom {@code double} values,
690 +     * each with the given origin and bound
691 +     * @throws IllegalArgumentException if {@code streamSize} is
692 +     * less than zero
693 +     * @throws IllegalArgumentException if {@code randomNumberOrigin}
694 +     *         is greater than or equal to {@code randomNumberBound}
695 +     */
696 +    public DoubleStream doubles(long streamSize, double randomNumberOrigin,
697 +                                double randomNumberBound) {
698 +        if (streamSize < 0L)
699 +            throw new IllegalArgumentException(BadSize);
700 +        if (!(randomNumberOrigin < randomNumberBound))
701 +            throw new IllegalArgumentException(BadRange);
702 +        return StreamSupport.doubleStream
703 +            (new RandomDoublesSpliterator
704 +             (0L, streamSize, randomNumberOrigin, randomNumberBound),
705 +             false);
706 +    }
707 +
708 +    /**
709 +     * Returns an effectively unlimited stream of pseudorandom {@code
710 +     * double} values, each conforming to the given origin and bound.
711 +     *
712 +     * @implNote This method is implemented to be equivalent to {@code
713 +     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
714 +     *
715 +     * @param randomNumberOrigin the origin of each random value
716 +     * @param randomNumberBound the bound of each random value
717 +     * @return a stream of pseudorandom {@code double} values,
718 +     * each with the given origin and bound
719 +     * @throws IllegalArgumentException if {@code randomNumberOrigin}
720 +     *         is greater than or equal to {@code randomNumberBound}
721 +     */
722 +    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
723 +        if (!(randomNumberOrigin < randomNumberBound))
724 +            throw new IllegalArgumentException(BadRange);
725 +        return StreamSupport.doubleStream
726 +            (new RandomDoublesSpliterator
727 +             (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
728 +             false);
729 +    }
730 +
731 +    /**
732 +     * Spliterator for int streams.  We multiplex the four int
733 +     * versions into one class by treating a bound less than origin as
734 +     * unbounded, and also by treating "infinite" as equivalent to
735 +     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
736 +     * approach. The long and double versions of this class are
737 +     * identical except for types.
738 +     */
739 +    static final class RandomIntsSpliterator implements Spliterator.OfInt {
740 +        long index;
741 +        final long fence;
742 +        final int origin;
743 +        final int bound;
744 +        RandomIntsSpliterator(long index, long fence,
745 +                              int origin, int bound) {
746 +            this.index = index; this.fence = fence;
747 +            this.origin = origin; this.bound = bound;
748 +        }
749 +
750 +        public RandomIntsSpliterator trySplit() {
751 +            long i = index, m = (i + fence) >>> 1;
752 +            return (m <= i) ? null :
753 +                new RandomIntsSpliterator(i, index = m, origin, bound);
754 +        }
755 +
756 +        public long estimateSize() {
757 +            return fence - index;
758 +        }
759 +
760 +        public int characteristics() {
761 +            return (Spliterator.SIZED | Spliterator.SUBSIZED |
762 +                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
763 +        }
764 +
765 +        public boolean tryAdvance(IntConsumer consumer) {
766 +            if (consumer == null) throw new NullPointerException();
767 +            long i = index, f = fence;
768 +            if (i < f) {
769 +                consumer.accept(ThreadLocalRandom.current().internalNextInt(origin, bound));
770 +                index = i + 1;
771 +                return true;
772 +            }
773 +            return false;
774 +        }
775 +
776 +        public void forEachRemaining(IntConsumer consumer) {
777 +            if (consumer == null) throw new NullPointerException();
778 +            long i = index, f = fence;
779 +            if (i < f) {
780 +                index = f;
781 +                int o = origin, b = bound;
782 +                ThreadLocalRandom rng = ThreadLocalRandom.current();
783 +                do {
784 +                    consumer.accept(rng.internalNextInt(o, b));
785 +                } while (++i < f);
786 +            }
787 +        }
788 +    }
789 +
790 +    /**
791 +     * Spliterator for long streams.
792 +     */
793 +    static final class RandomLongsSpliterator implements Spliterator.OfLong {
794 +        long index;
795 +        final long fence;
796 +        final long origin;
797 +        final long bound;
798 +        RandomLongsSpliterator(long index, long fence,
799 +                               long origin, long bound) {
800 +            this.index = index; this.fence = fence;
801 +            this.origin = origin; this.bound = bound;
802 +        }
803 +
804 +        public RandomLongsSpliterator trySplit() {
805 +            long i = index, m = (i + fence) >>> 1;
806 +            return (m <= i) ? null :
807 +                new RandomLongsSpliterator(i, index = m, origin, bound);
808 +        }
809 +
810 +        public long estimateSize() {
811 +            return fence - index;
812 +        }
813 +
814 +        public int characteristics() {
815 +            return (Spliterator.SIZED | Spliterator.SUBSIZED |
816 +                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
817 +        }
818 +
819 +        public boolean tryAdvance(LongConsumer consumer) {
820 +            if (consumer == null) throw new NullPointerException();
821 +            long i = index, f = fence;
822 +            if (i < f) {
823 +                consumer.accept(ThreadLocalRandom.current().internalNextLong(origin, bound));
824 +                index = i + 1;
825 +                return true;
826 +            }
827 +            return false;
828 +        }
829 +
830 +        public void forEachRemaining(LongConsumer consumer) {
831 +            if (consumer == null) throw new NullPointerException();
832 +            long i = index, f = fence;
833 +            if (i < f) {
834 +                index = f;
835 +                long o = origin, b = bound;
836 +                ThreadLocalRandom rng = ThreadLocalRandom.current();
837 +                do {
838 +                    consumer.accept(rng.internalNextLong(o, b));
839 +                } while (++i < f);
840 +            }
841 +        }
842 +
843 +    }
844 +
845 +    /**
846 +     * Spliterator for double streams.
847 +     */
848 +    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
849 +        long index;
850 +        final long fence;
851 +        final double origin;
852 +        final double bound;
853 +        RandomDoublesSpliterator(long index, long fence,
854 +                                 double origin, double bound) {
855 +            this.index = index; this.fence = fence;
856 +            this.origin = origin; this.bound = bound;
857 +        }
858 +
859 +        public RandomDoublesSpliterator trySplit() {
860 +            long i = index, m = (i + fence) >>> 1;
861 +            return (m <= i) ? null :
862 +                new RandomDoublesSpliterator(i, index = m, origin, bound);
863 +        }
864 +
865 +        public long estimateSize() {
866 +            return fence - index;
867 +        }
868 +
869 +        public int characteristics() {
870 +            return (Spliterator.SIZED | Spliterator.SUBSIZED |
871 +                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
872 +        }
873 +
874 +        public boolean tryAdvance(DoubleConsumer consumer) {
875 +            if (consumer == null) throw new NullPointerException();
876 +            long i = index, f = fence;
877 +            if (i < f) {
878 +                consumer.accept(ThreadLocalRandom.current().internalNextDouble(origin, bound));
879 +                index = i + 1;
880 +                return true;
881 +            }
882 +            return false;
883 +        }
884 +
885 +        public void forEachRemaining(DoubleConsumer consumer) {
886 +            if (consumer == null) throw new NullPointerException();
887 +            long i = index, f = fence;
888 +            if (i < f) {
889 +                index = f;
890 +                double o = origin, b = bound;
891 +                ThreadLocalRandom rng = ThreadLocalRandom.current();
892 +                do {
893 +                    consumer.accept(rng.internalNextDouble(o, b));
894 +                } while (++i < f);
895 +            }
896 +        }
897 +    }
898 +
899 +
900      // Within-package utilities
901  
902      /*

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines