1 /*
  2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  3  *
  4  * This code is free software; you can redistribute it and/or modify it
  5  * under the terms of the GNU General Public License version 2 only, as
  6  * published by the Free Software Foundation.  Oracle designates this
  7  * particular file as subject to the "Classpath" exception as provided
  8  * by Oracle in the LICENSE file that accompanied this code.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  */
 24 
 25 /*
 26  * This file is available under and governed by the GNU General Public
 27  * License version 2 only, as published by the Free Software Foundation.
 28  * However, the following notice accompanied the original version of this
 29  * file:
 30  *
 31  * Written by Doug Lea with assistance from members of JCP JSR-166
 32  * Expert Group and released to the public domain, as explained at
 33  * http://creativecommons.org/publicdomain/zero/1.0/
 34  *
 35  * Additional modifications by Guy Steele in 2019 to refactor the code
 36  * and to implement the {@link RandomGenerator} interface.
 37  */
 38 
 39 package java.util.concurrent;
 40 
 41 import java.io.ObjectStreamField;
 42 import java.math.BigInteger;
 43 import java.security.AccessControlContext;
 44 import java.util.Map;
 45 import java.util.Random;
 46 import java.util.Spliterator;
 47 import java.util.concurrent.atomic.AtomicInteger;
 48 import java.util.concurrent.atomic.AtomicLong;
 49 import java.util.random.RandomGenerator;
 50 import java.util.stream.DoubleStream;
 51 import java.util.stream.IntStream;
 52 import java.util.stream.LongStream;
 53 import jdk.internal.util.random.RandomSupport;
 54 import jdk.internal.util.random.RandomSupport.*;
 55 import jdk.internal.misc.Unsafe;
 56 import jdk.internal.misc.VM;
 57 
 58 /**
 59  * A random number generator (with period 2<sup>64</sup>) isolated
 60  * to the current thread.  Like the global {@link java.util.Random}
 61  * generator used by the {@link java.lang.Math} class,
 62  * a {@code ThreadLocalRandom} is initialized
 63  * with an internally generated seed that may not otherwise be
 64  * modified. When applicable, use of {@code ThreadLocalRandom} rather
 65  * than shared {@code Random} objects in concurrent programs will
 66  * typically encounter much less overhead and contention.  Use of
 67  * {@code ThreadLocalRandom} is particularly appropriate when multiple
 68  * tasks (for example, each a {@link ForkJoinTask}) use random numbers
 69  * in parallel in thread pools.
 70  *
 71  * <p>Usages of this class should typically be of the form:
 72  * {@code ThreadLocalRandom.current().nextX(...)} (where
 73  * {@code X} is {@code Int}, {@code Long}, etc).
 74  * When all usages are of this form, it is never possible to
 75  * accidentally share a {@code ThreadLocalRandom} across multiple threads.
 76  *
 77  * <p>This class also provides additional commonly used bounded random
 78  * generation methods.
 79  *
 80  * <p>Instances of {@code ThreadLocalRandom} 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  * @since 1.7
 88  * @author Doug Lea
 89  */
 90 
 91 @RandomGeneratorProperties(
 92         name = "ThreadLocalRandom",
 93         i = 64, j = 0, k = 0,
 94         equidistribution = 1
 95 )
 96 public class ThreadLocalRandom extends Random {
 97     /*
 98      * This class implements the java.util.Random API (and subclasses
 99      * Random) using a single static instance that accesses 64 bits of
100      * random number state held in class java.lang.Thread (field
101      * threadLocalRandomSeed). In doing so, it also provides a home
102      * for managing package-private utilities that rely on exactly the
103      * same state as needed to maintain the ThreadLocalRandom
104      * instances. We leverage the need for an initialization flag
105      * field to also use it as a "probe" -- a self-adjusting thread
106      * hash used for contention avoidance, as well as a secondary
107      * simpler (xorShift) random seed that is conservatively used to
108      * avoid otherwise surprising users by hijacking the
109      * ThreadLocalRandom sequence.  The dual use is a marriage of
110      * convenience, but is a simple and efficient way of reducing
111      * application-level overhead and footprint of most concurrent
112      * programs. Even more opportunistically, we also define here
113      * other package-private utilities that access Thread class
114      * fields.
115      *
116      * Even though this class subclasses java.util.Random, it uses the
117      * same basic algorithm as java.util.SplittableRandom.  (See its
118      * internal documentation for explanations, which are not repeated
119      * here.)  Note that ThreadLocalRandom is not a "splittable" generator
120      * (it does not support the split method), but it behaves as if
121      * one instance of the SplittableRandom algorithm had been
122      * created for each thread, each with a distinct gamma parameter
123      * (calculated from the thread id).
124      *
125      * Because this class is in a different package than class Thread,
126      * field access methods use Unsafe to bypass access control rules.
127      * To conform to the requirements of the Random superclass
128      * constructor, the common static ThreadLocalRandom maintains an
129      * "initialized" field for the sake of rejecting user calls to
130      * setSeed while still allowing a call from constructor.  Note
131      * that serialization is completely unnecessary because there is
132      * only a static singleton.  But we generate a serial form
133      * containing "rnd" and "initialized" fields to ensure
134      * compatibility across versions.
135      *
136      * Implementations of non-core methods are mostly the same as in
137      * SplittableRandom, that were in part derived from a previous
138      * version of this class.
139      *
140      * This implementation of ThreadLocalRandom overrides the
141      * definition of the nextGaussian() method in the class Random,
142      * and instead uses the ziggurat-based algorithm that is the
143      * default for the RandomGenerator interface.
144      */
145 
146     private static int mix32(long z) {
147         z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
148         return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
149     }
150 
151     /**
152      * Field used only during singleton initialization.
153      * True when constructor completes.
154      */
155     boolean initialized;
156 
157     /** Constructor used only for static singleton */
158     private ThreadLocalRandom() {
159         initialized = true; // false during super() call
160     }
161 
162     /**
163      * Initialize Thread fields for the current thread.  Called only
164      * when Thread.threadLocalRandomProbe is zero, indicating that a
165      * thread local seed value needs to be generated. Note that even
166      * though the initialization is purely thread-local, we need to
167      * rely on (static) atomic generators to initialize the values.
168      */
169     static final void localInit() {
170         int p = probeGenerator.addAndGet(PROBE_INCREMENT);
171         int probe = (p == 0) ? 1 : p; // skip 0
172         long seed = RandomSupport.mixMurmur64(seeder.getAndAdd(SEEDER_INCREMENT));
173         Thread t = Thread.currentThread();
174         U.putLong(t, SEED, seed);
175         U.putInt(t, PROBE, probe);
176     }
177 
178     /**
179      * Returns the current thread's {@code ThreadLocalRandom} object.
180      * Methods of this object should be called only by the current thread,
181      * not by other threads.
182      *
183      * @return the current thread's {@code ThreadLocalRandom}
184      */
185     public static ThreadLocalRandom current() {
186         if (U.getInt(Thread.currentThread(), PROBE) == 0)
187             localInit();
188         return instance;
189     }
190 
191     /**
192      * Throws {@code UnsupportedOperationException}.  Setting seeds in
193      * this generator is not supported.
194      *
195      * @throws UnsupportedOperationException always
196      */
197     public void setSeed(long seed) {
198         // only allow call from super() constructor
199         if (initialized)
200             throw new UnsupportedOperationException();
201     }
202 
203     /**
204      * Update the thread local seed value by adding to it the sum
205      * of {@code GOLDEN_GAMMA} (an odd value) and twice the thread id.
206      * This sum is always odd (to guarantee that the generator
207      * has maximum period) and is different for different threads.
208      * Because thread id values are allocated consecutively starting
209      * from 0, the high 32 bits of this sum will be the same as the
210      * high 32 bits of {@code GOLDEN_GAMMA} unless an extremely large
211      * number of threads have been created, and so the overall
212      * value added to the thread local seed value will have at least
213      * fourteen 01 and 10 transitions (see the documentation for the
214      * method {@code mixGamma} in class {@code SplittableRandom}),
215      * which should provide adequate statistical quality for
216      * applications likely to use {@code ThreadLocalRandom}.
217      */
218     final long nextSeed() {
219         Thread t; long r; // read and update per-thread seed
220         U.putLong(t = Thread.currentThread(), SEED,
221                   r = U.getLong(t, SEED) + (t.getId() << 1) + GOLDEN_GAMMA);
222         return r;
223     }
224 
225     /**
226      * Generates a pseudorandom number with the indicated number of
227      * low-order bits.  Because this class has no subclasses, this
228      * method cannot be invoked or overridden.
229      *
230      * @param  bits random bits
231      * @return the next pseudorandom value from this random number
232      *         generator's sequence
233      */
234     protected int next(int bits) {
235         return nextInt() >>> (32 - bits);
236     }
237 
238     // Within-package utilities
239 
240     /*
241      * Descriptions of the usages of the methods below can be found in
242      * the classes that use them. Briefly, a thread's "probe" value is
243      * a non-zero hash code that (probably) does not collide with
244      * other existing threads with respect to any power of two
245      * collision space. When it does collide, it is pseudo-randomly
246      * adjusted (using a Marsaglia XorShift). The nextSecondarySeed
247      * method is used in the same contexts as ThreadLocalRandom, but
248      * only for transient usages such as random adaptive spin/block
249      * sequences for which a cheap RNG suffices and for which it could
250      * in principle disrupt user-visible statistical properties of the
251      * main ThreadLocalRandom if we were to use it.
252      *
253      * Note: Because of package-protection issues, versions of some
254      * these methods also appear in some subpackage classes.
255      */
256 
257     /**
258      * Returns the probe value for the current thread without forcing
259      * initialization. Note that invoking ThreadLocalRandom.current()
260      * can be used to force initialization on zero return.
261      */
262     static final int getProbe() {
263         return U.getInt(Thread.currentThread(), PROBE);
264     }
265 
266     /**
267      * Pseudo-randomly advances and records the given probe value for the
268      * given thread.
269      */
270     static final int advanceProbe(int probe) {
271         probe ^= probe << 13;   // xorshift
272         probe ^= probe >>> 17;
273         probe ^= probe << 5;
274         U.putInt(Thread.currentThread(), PROBE, probe);
275         return probe;
276     }
277 
278     /**
279      * Returns the pseudo-randomly initialized or updated secondary seed.
280      */
281     static final int nextSecondarySeed() {
282         int r;
283         Thread t = Thread.currentThread();
284         if ((r = U.getInt(t, SECONDARY)) != 0) {
285             r ^= r << 13;   // xorshift
286             r ^= r >>> 17;
287             r ^= r << 5;
288         }
289         else if ((r = mix32(seeder.getAndAdd(SEEDER_INCREMENT))) == 0)
290             r = 1; // avoid zero
291         U.putInt(t, SECONDARY, r);
292         return r;
293     }
294 
295     // Support for other package-private ThreadLocal access
296 
297     /**
298      * Erases ThreadLocals by nulling out Thread maps.
299      */
300     static final void eraseThreadLocals(Thread thread) {
301         U.putReference(thread, THREADLOCALS, null);
302         U.putReference(thread, INHERITABLETHREADLOCALS, null);
303         // Ideally we should also clear the Thread's ScopedCache, but it is
304         // in the VM-internal JavaThread structure. This method is called so
305         // early in the lifetime of a ForkJoinPool thread that we don't expect
306         // any ScopeLocals to have yet been bound by this thread, so the
307         // ScopedCache should be empty at this point.
308         // U.putReference(thread, INHERITABLESCOPELOCALBINDINGS, null);
309     }
310 
311     static final void setInheritedAccessControlContext(Thread thread,
312                                                        @SuppressWarnings("removal") AccessControlContext acc) {
313         U.putReferenceRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
314     }
315 
316     // Serialization support
317 
318     private static final long serialVersionUID = -5851777807851030925L;
319 
320     /**
321      * @serialField rnd long
322      *              seed for random computations
323      * @serialField initialized boolean
324      *              always true
325      */
326     private static final ObjectStreamField[] serialPersistentFields = {
327         new ObjectStreamField("rnd", long.class),
328         new ObjectStreamField("initialized", boolean.class),
329     };
330 
331     /**
332      * Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it).
333      * @param s the stream
334      * @throws java.io.IOException if an I/O error occurs
335      */
336     private void writeObject(java.io.ObjectOutputStream s)
337         throws java.io.IOException {
338 
339         java.io.ObjectOutputStream.PutField fields = s.putFields();
340         fields.put("rnd", U.getLong(Thread.currentThread(), SEED));
341         fields.put("initialized", true);
342         s.writeFields();
343     }
344 
345     /**
346      * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
347      * @return the {@link #current() current} thread's {@code ThreadLocalRandom}
348      */
349     private Object readResolve() {
350         return current();
351     }
352 
353     // Static initialization
354 
355     /**
356      * The seed increment.  This must be an odd value for the generator to
357      * have the maximum period (2 to the 64th power).
358      *
359      * The value 0x9e3779b97f4a7c15L is odd, and moreover consists of the
360      * first 64 bits of the fractional part of the golden ratio,
361      * which is known to generate good Weyl sequences.
362      */
363     private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L;
364 
365     /**
366      * The increment for generating probe values.
367      */
368     private static final int PROBE_INCREMENT = 0x9e3779b9;
369 
370     /**
371      * The increment of seeder per new instance.
372      */
373     private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
374 
375     // IllegalArgumentException messages
376     static final String BAD_BOUND = "bound must be positive";
377     static final String BAD_RANGE = "bound must be greater than origin";
378     static final String BAD_SIZE  = "size must be non-negative";
379 
380     // Unsafe mechanics
381     private static final Unsafe U = Unsafe.getUnsafe();
382     private static final long SEED
383         = U.objectFieldOffset(Thread.class, "threadLocalRandomSeed");
384     private static final long PROBE
385         = U.objectFieldOffset(Thread.class, "threadLocalRandomProbe");
386     private static final long SECONDARY
387         = U.objectFieldOffset(Thread.class, "threadLocalRandomSecondarySeed");
388     private static final long THREADLOCALS
389         = U.objectFieldOffset(Thread.class, "threadLocals");
390     private static final long INHERITABLETHREADLOCALS
391         = U.objectFieldOffset(Thread.class, "inheritableThreadLocals");
392     private static final long INHERITEDACCESSCONTROLCONTEXT
393         = U.objectFieldOffset(Thread.class, "inheritedAccessControlContext");
394 
395     /** Generates per-thread initialization/probe field */
396     private static final AtomicInteger probeGenerator = new AtomicInteger();
397 
398     /** The common ThreadLocalRandom */
399     private static final ThreadLocalRandom instance = new ThreadLocalRandom();
400 
401     /**
402      * The next seed for default constructors.
403      */
404     private static final AtomicLong seeder
405         = new AtomicLong(RandomSupport.mixMurmur64(System.currentTimeMillis()) ^
406                          RandomSupport.mixMurmur64(System.nanoTime()));
407 
408     // at end of <clinit> to survive static initialization circularity
409     static {
410         String sec = VM.getSavedProperty("java.util.secureRandomSeed");
411         if (Boolean.parseBoolean(sec)) {
412             byte[] seedBytes = java.security.SecureRandom.getSeed(8);
413             long s = (long)seedBytes[0] & 0xffL;
414             for (int i = 1; i < 8; ++i)
415                 s = (s << 8) | ((long)seedBytes[i] & 0xffL);
416             seeder.set(s);
417         }
418     }
419 
420     @SuppressWarnings("serial")
421     private static final class ThreadLocalRandomProxy extends Random {
422         static final Random PROXY = new ThreadLocalRandomProxy();
423 
424         public int nextInt() {
425             return ThreadLocalRandom.current().nextInt();
426         }
427 
428         public long nextLong() {
429             return ThreadLocalRandom.current().nextLong();
430         }
431     }
432 
433     /**
434      * {@inheritDoc}
435      */
436     @Override
437     public boolean nextBoolean() {
438         return super.nextBoolean();
439     }
440 
441     /**
442      * {@inheritDoc}
443      */
444     @Override
445     public int nextInt() {
446         return mix32(nextSeed());
447     }
448 
449     /**
450      * {@inheritDoc}
451      * @throws IllegalArgumentException {@inheritDoc}
452      */
453     @Override
454     public int nextInt(int bound) {
455         return super.nextInt(bound);
456     }
457 
458     /**
459      * {@inheritDoc}
460      * @throws IllegalArgumentException {@inheritDoc}
461      */
462     @Override
463     public int nextInt(int origin, int bound) {
464         return super.nextInt(origin, bound);
465     }
466 
467     /**
468      * {@inheritDoc}
469      */
470     @Override
471     public long nextLong() {
472         return RandomSupport.mixMurmur64(nextSeed());
473     }
474 
475     /**
476      * {@inheritDoc}
477      * @throws IllegalArgumentException {@inheritDoc}
478      */
479     @Override
480     public long nextLong(long bound) {
481         return super.nextLong(bound);
482     }
483 
484     /**
485      * {@inheritDoc}
486      * @throws IllegalArgumentException {@inheritDoc}
487      */
488     @Override
489     public long nextLong(long origin, long bound) {
490         return super.nextLong(origin, bound);
491     }
492 
493     /**
494      * {@inheritDoc}
495      */
496     @Override
497     public float nextFloat() {
498         return super.nextFloat();
499     }
500 
501     /**
502      * {@inheritDoc}
503      * @throws IllegalArgumentException {@inheritDoc}
504      * @implNote {@inheritDoc}
505      */
506     @Override
507     public float nextFloat(float bound) {
508          return super.nextFloat(bound);
509     }
510 
511     /**
512      * {@inheritDoc}
513      * @throws IllegalArgumentException {@inheritDoc}
514      * @implNote {@inheritDoc}
515      */
516     @Override
517     public float nextFloat(float origin, float bound) {
518         return super.nextFloat(origin, bound);
519     }
520 
521     /**
522      * {@inheritDoc}
523      */
524     @Override
525     public double nextDouble() {
526         return super.nextDouble();
527     }
528 
529     /**
530      * {@inheritDoc}
531      * @throws IllegalArgumentException {@inheritDoc}
532      * @implNote {@inheritDoc}
533      */
534     @Override
535     public double nextDouble(double bound) {
536         return super.nextDouble(bound);
537     }
538 
539     /**
540      * {@inheritDoc}
541      * @throws IllegalArgumentException {@inheritDoc}
542      * @implNote {@inheritDoc}
543      */
544     @Override
545     public double nextDouble(double origin, double bound) {
546         return super.nextDouble(origin, bound);
547     }
548     /**
549      * {@inheritDoc}
550      * @throws IllegalArgumentException {@inheritDoc}
551      * @since 1.8
552      */
553     @Override
554     public IntStream ints(long streamSize) {
555         return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY, streamSize);
556     }
557 
558     /**
559      * {@inheritDoc}
560      * @implNote This method is implemented to be equivalent to
561      *           {@code ints(Long.MAX_VALUE)}.
562      * @since 1.8
563      */
564     @Override
565     public IntStream ints() {
566         return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY);
567     }
568 
569     /**
570      * {@inheritDoc}
571      * @throws IllegalArgumentException {@inheritDoc}
572      * @since 1.8
573      */
574     @Override
575     public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) {
576         return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY, streamSize, randomNumberOrigin, randomNumberBound);
577     }
578 
579     /**
580      * {@inheritDoc}
581      * @implNote This method is implemented to be equivalent to
582      *           {@code ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
583      * @throws IllegalArgumentException {@inheritDoc}
584      * @since 1.8
585      */
586     @Override
587     public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
588         return AbstractSpliteratorGenerator.ints(ThreadLocalRandomProxy.PROXY, randomNumberOrigin, randomNumberBound);
589     }
590 
591     /**
592      * {@inheritDoc}
593      * @throws IllegalArgumentException {@inheritDoc}
594      * @since 1.8
595      */
596     @Override
597     public LongStream longs(long streamSize) {
598         return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY, streamSize);
599     }
600 
601     /**
602      * {@inheritDoc}
603      * @implNote This method is implemented to be equivalent to
604      *           {@code longs(Long.MAX_VALUE)}.
605      * @since 1.8
606      */
607     @Override
608     public LongStream longs() {
609         return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY);
610     }
611 
612     /**
613      * {@inheritDoc}
614      * @throws IllegalArgumentException {@inheritDoc}
615      * @since 1.8
616      */
617     @Override
618     public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) {
619         return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY, streamSize, randomNumberOrigin, randomNumberBound);
620     }
621 
622     /**
623      * {@inheritDoc}
624      * @implNote This method is implemented to be equivalent to
625      *           {@code longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
626      * @throws IllegalArgumentException {@inheritDoc}
627      * @since 1.8
628      */
629     @Override
630     public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
631         return AbstractSpliteratorGenerator.longs(ThreadLocalRandomProxy.PROXY, randomNumberOrigin, randomNumberBound);
632     }
633 
634     /**
635      * {@inheritDoc}
636      * @throws IllegalArgumentException {@inheritDoc}
637      * @since 1.8
638      */
639     @Override
640     public DoubleStream doubles(long streamSize) {
641         return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY, streamSize);
642     }
643 
644     /**
645      * {@inheritDoc}
646      * @implNote This method is implemented to be equivalent to
647      *           {@code doubles(Long.MAX_VALUE)}.
648      * @since 1.8
649      */
650     @Override
651     public DoubleStream doubles() {
652         return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY);
653     }
654 
655     /**
656      * {@inheritDoc}
657      * @throws IllegalArgumentException {@inheritDoc}
658      * @since 1.8
659      */
660     @Override
661     public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
662         return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY, streamSize, randomNumberOrigin, randomNumberBound);
663     }
664 
665     /**
666      * {@inheritDoc}
667      * @implNote This method is implemented to be equivalent to
668      *           {@code doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
669      * @throws IllegalArgumentException {@inheritDoc}
670      * @since 1.8
671      */
672     @Override
673     public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
674         return AbstractSpliteratorGenerator.doubles(ThreadLocalRandomProxy.PROXY, randomNumberOrigin, randomNumberBound);
675     }
676 
677 }