[mq]: refresh JDK-8193209-branch
authorjlaskey
Thu, 14 Nov 2019 12:39:49 -0400
branchJDK-8193209-branch
changeset 59086 214afc7a1e02
parent 59085 c660730af328
child 59087 effb66aab08b
[mq]: refresh
src/java.base/share/classes/java/security/SecureRandom.java
src/java.base/share/classes/java/util/Random.java
src/java.base/share/classes/java/util/SplittableRandom.java
src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
src/java.base/share/classes/module-info.java
--- a/src/java.base/share/classes/java/security/SecureRandom.java	Thu Nov 14 12:36:46 2019 -0400
+++ b/src/java.base/share/classes/java/security/SecureRandom.java	Thu Nov 14 12:39:49 2019 -0400
@@ -25,11 +25,11 @@
 
 package java.security;
 
+import java.math.BigInteger;
 import java.util.*;
+import java.util.random.RandomGenerator;
 import java.util.regex.*;
-
 import java.security.Provider.Service;
-
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
 import sun.security.provider.SunEntries;
@@ -1031,6 +1031,16 @@
         }
     }
 
+    /**
+     * Returns the period of this random number generator.
+     *
+     * @return the period of this random number generator.
+     */
+    @Override
+    public BigInteger period() {
+        return RandomGenerator.HUGE_PERIOD;
+    }
+
     // Declare serialVersionUID to be compatible with JDK1.1
     @java.io.Serial
     static final long serialVersionUID = 4940670005562187L;
--- a/src/java.base/share/classes/java/util/Random.java	Thu Nov 14 12:36:46 2019 -0400
+++ b/src/java.base/share/classes/java/util/Random.java	Thu Nov 14 12:39:49 2019 -0400
@@ -24,11 +24,18 @@
  */
 
 package java.util;
+
 import java.io.*;
+import java.math.BigInteger;
+import java.util.Spliterator;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.DoubleConsumer;
 import java.util.function.IntConsumer;
 import java.util.function.LongConsumer;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomSupport;
+import java.util.random.RandomSupport.AbstractSpliteratorGenerator;
+import java.util.random.RandomSupport.RandomSpliterator;
 import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
@@ -74,7 +81,7 @@
  * @since   1.0
  */
 public
-class Random implements java.io.Serializable {
+class Random extends AbstractSpliteratorGenerator implements java.io.Serializable {
     /** use serialVersionUID from JDK 1.1 for interoperability */
     @java.io.Serial
     static final long serialVersionUID = 3905348978240129619L;
@@ -206,6 +213,20 @@
         return (int)(nextseed >>> (48 - bits));
     }
 
+    /*
+     * Period of Random is 2**48
+     */
+    private static final BigInteger PERIOD = BigInteger.valueOf(1L<<48);
+
+    /**
+     * Returns the period of this random number generator.
+     *
+     * @return the period of this random number generator.
+     */
+    public BigInteger period() {
+        return PERIOD;
+    }
+
     /**
      * Generates random bytes and places them into a user-supplied
      * byte array.  The number of random bytes produced is equal to
@@ -234,82 +255,6 @@
     }
 
     /**
-     * The form of nextLong used by LongStream Spliterators.  If
-     * origin is greater than bound, acts as unbounded form of
-     * nextLong, else as bounded form.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final long internalNextLong(long origin, long bound) {
-        long r = nextLong();
-        if (origin < bound) {
-            long n = bound - origin, m = n - 1;
-            if ((n & m) == 0L)  // power of two
-                r = (r & m) + origin;
-            else if (n > 0L) {  // reject over-represented candidates
-                for (long u = r >>> 1;            // ensure nonnegative
-                     u + m - (r = u % n) < 0L;    // rejection check
-                     u = nextLong() >>> 1) // retry
-                    ;
-                r += origin;
-            }
-            else {              // range not representable as long
-                while (r < origin || r >= bound)
-                    r = nextLong();
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextInt used by IntStream Spliterators.
-     * For the unbounded case: uses nextInt().
-     * For the bounded case with representable range: uses nextInt(int bound)
-     * For the bounded case with unrepresentable range: uses nextInt()
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final int internalNextInt(int origin, int bound) {
-        if (origin < bound) {
-            int n = bound - origin;
-            if (n > 0) {
-                return nextInt(n) + origin;
-            }
-            else {  // range not representable as int
-                int r;
-                do {
-                    r = nextInt();
-                } while (r < origin || r >= bound);
-                return r;
-            }
-        }
-        else {
-            return nextInt();
-        }
-    }
-
-    /**
-     * The form of nextDouble used by DoubleStream Spliterators.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final double internalNextDouble(double origin, double bound) {
-        double r = nextDouble();
-        if (origin < bound) {
-            r = r * (bound - origin) + origin;
-            if (r >= bound) // correct for rounding
-                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-        }
-        return r;
-    }
-
-    /**
      * Returns the next pseudorandom, uniformly distributed {@code int}
      * value from this random number generator's sequence. The general
      * contract of {@code nextInt} is that one {@code int} value is
@@ -331,71 +276,26 @@
     }
 
     /**
-     * Returns a pseudorandom, uniformly distributed {@code int} value
-     * between 0 (inclusive) and the specified value (exclusive), drawn from
-     * this random number generator's sequence.  The general contract of
-     * {@code nextInt} is that one {@code int} value in the specified range
-     * is pseudorandomly generated and returned.  All {@code bound} possible
-     * {@code int} values are produced with (approximately) equal
-     * probability.  The method {@code nextInt(int bound)} is implemented by
-     * class {@code Random} as if by:
-     *  <pre> {@code
-     * public int nextInt(int bound) {
-     *   if (bound <= 0)
-     *     throw new IllegalArgumentException("bound must be positive");
-     *
-     *   if ((bound & -bound) == bound)  // i.e., bound is a power of 2
-     *     return (int)((bound * (long)next(31)) >> 31);
-     *
-     *   int bits, val;
-     *   do {
-     *       bits = next(31);
-     *       val = bits % bound;
-     *   } while (bits - val + (bound-1) < 0);
-     *   return val;
-     * }}</pre>
-     *
-     * <p>The hedge "approximately" is used in the foregoing description only
-     * because the next method is only approximately an unbiased source of
-     * independently chosen bits.  If it were a perfect source of randomly
-     * chosen bits, then the algorithm shown would choose {@code int}
-     * values from the stated range with perfect uniformity.
-     * <p>
-     * The algorithm is slightly tricky.  It rejects values that would result
-     * in an uneven distribution (due to the fact that 2^31 is not divisible
-     * by n). The probability of a value being rejected depends on n.  The
-     * worst case is n=2^30+1, for which the probability of a reject is 1/2,
-     * and the expected number of iterations before the loop terminates is 2.
-     * <p>
-     * The algorithm treats the case where n is a power of two specially: it
-     * returns the correct number of high-order bits from the underlying
-     * pseudo-random number generator.  In the absence of special treatment,
-     * the correct number of <i>low-order</i> bits would be returned.  Linear
-     * congruential pseudo-random number generators such as the one
-     * implemented by this class are known to have short periods in the
-     * sequence of values of their low-order bits.  Thus, this special case
-     * greatly increases the length of the sequence of values returned by
-     * successive calls to this method if n is a small power of two.
+     * Returns a pseudorandom {@code int} value between zero (inclusive)
+     * and the specified bound (exclusive).
      *
      * @param bound the upper bound (exclusive).  Must be positive.
-     * @return the next pseudorandom, uniformly distributed {@code int}
-     *         value between zero (inclusive) and {@code bound} (exclusive)
-     *         from this random number generator's sequence
-     * @throws IllegalArgumentException if bound is not positive
-     * @since 1.2
+     * @return a pseudorandom {@code int} value between zero
+     *         (inclusive) and the bound (exclusive)
+     * @throws IllegalArgumentException if {@code bound} is not positive
      */
     public int nextInt(int bound) {
         if (bound <= 0)
             throw new IllegalArgumentException(BadBound);
-
-        int r = next(31);
+        // Specialize internalNextInt for origin 0
+        int r = nextInt();
         int m = bound - 1;
-        if ((bound & m) == 0)  // i.e., bound is a power of 2
-            r = (int)((bound * (long)r) >> 31);
-        else {
-            for (int u = r;
-                 u - (r = u % bound) + m < 0;
-                 u = next(31))
+        if ((bound & m) == 0) // power of two
+            r &= m;
+        else { // reject over-represented candidates
+            for (int u = r >>> 1;
+                 u + m - (r = u % bound) < 0;
+                 u = nextInt() >>> 1)
                 ;
         }
         return r;
@@ -600,565 +500,6 @@
         }
     }
 
-    // stream methods, coded in a way intended to better isolate for
-    // maintenance purposes the small differences across forms.
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code int} values.
-     *
-     * <p>A pseudorandom {@code int} value is generated as if it's the result of
-     * calling the method {@link #nextInt()}.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code int} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @since 1.8
-     */
-    public IntStream ints(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
-        return StreamSupport.intStream
-                (new RandomIntsSpliterator
-                         (this, 0L, streamSize, Integer.MAX_VALUE, 0),
-                 false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code int}
-     * values.
-     *
-     * <p>A pseudorandom {@code int} value is generated as if it's the result of
-     * calling the method {@link #nextInt()}.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code int} values
-     * @since 1.8
-     */
-    public IntStream ints() {
-        return StreamSupport.intStream
-                (new RandomIntsSpliterator
-                         (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
-                 false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code int} values, each conforming to the given
-     * origin (inclusive) and bound (exclusive).
-     *
-     * <p>A pseudorandom {@code int} value is generated as if it's the result of
-     * calling the following method with the origin and bound:
-     * <pre> {@code
-     * int nextInt(int origin, int bound) {
-     *   int n = bound - origin;
-     *   if (n > 0) {
-     *     return nextInt(n) + origin;
-     *   }
-     *   else {  // range not representable as int
-     *     int r;
-     *     do {
-     *       r = nextInt();
-     *     } while (r < origin || r >= bound);
-     *     return r;
-     *   }
-     * }}</pre>
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public IntStream ints(long streamSize, int randomNumberOrigin,
-                          int randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
-        return StreamSupport.intStream
-                (new RandomIntsSpliterator
-                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-                 false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * int} values, each conforming to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * <p>A pseudorandom {@code int} value is generated as if it's the result of
-     * calling the following method with the origin and bound:
-     * <pre> {@code
-     * int nextInt(int origin, int bound) {
-     *   int n = bound - origin;
-     *   if (n > 0) {
-     *     return nextInt(n) + origin;
-     *   }
-     *   else {  // range not representable as int
-     *     int r;
-     *     do {
-     *       r = nextInt();
-     *     } while (r < origin || r >= bound);
-     *     return r;
-     *   }
-     * }}</pre>
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
-        return StreamSupport.intStream
-                (new RandomIntsSpliterator
-                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-                 false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code long} values.
-     *
-     * <p>A pseudorandom {@code long} value is generated as if it's the result
-     * of calling the method {@link #nextLong()}.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code long} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @since 1.8
-     */
-    public LongStream longs(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
-        return StreamSupport.longStream
-                (new RandomLongsSpliterator
-                         (this, 0L, streamSize, Long.MAX_VALUE, 0L),
-                 false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code long}
-     * values.
-     *
-     * <p>A pseudorandom {@code long} value is generated as if it's the result
-     * of calling the method {@link #nextLong()}.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code long} values
-     * @since 1.8
-     */
-    public LongStream longs() {
-        return StreamSupport.longStream
-                (new RandomLongsSpliterator
-                         (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
-                 false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code long}, each conforming to the given origin
-     * (inclusive) and bound (exclusive).
-     *
-     * <p>A pseudorandom {@code long} value is generated as if it's the result
-     * of calling the following method with the origin and bound:
-     * <pre> {@code
-     * long nextLong(long origin, long bound) {
-     *   long r = nextLong();
-     *   long n = bound - origin, m = n - 1;
-     *   if ((n & m) == 0L)  // power of two
-     *     r = (r & m) + origin;
-     *   else if (n > 0L) {  // reject over-represented candidates
-     *     for (long u = r >>> 1;            // ensure nonnegative
-     *          u + m - (r = u % n) < 0L;    // rejection check
-     *          u = nextLong() >>> 1) // retry
-     *         ;
-     *     r += origin;
-     *   }
-     *   else {              // range not representable as long
-     *     while (r < origin || r >= bound)
-     *       r = nextLong();
-     *   }
-     *   return r;
-     * }}</pre>
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public LongStream longs(long streamSize, long randomNumberOrigin,
-                            long randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
-        return StreamSupport.longStream
-                (new RandomLongsSpliterator
-                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-                 false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * long} values, each conforming to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * <p>A pseudorandom {@code long} value is generated as if it's the result
-     * of calling the following method with the origin and bound:
-     * <pre> {@code
-     * long nextLong(long origin, long bound) {
-     *   long r = nextLong();
-     *   long n = bound - origin, m = n - 1;
-     *   if ((n & m) == 0L)  // power of two
-     *     r = (r & m) + origin;
-     *   else if (n > 0L) {  // reject over-represented candidates
-     *     for (long u = r >>> 1;            // ensure nonnegative
-     *          u + m - (r = u % n) < 0L;    // rejection check
-     *          u = nextLong() >>> 1) // retry
-     *         ;
-     *     r += origin;
-     *   }
-     *   else {              // range not representable as long
-     *     while (r < origin || r >= bound)
-     *       r = nextLong();
-     *   }
-     *   return r;
-     * }}</pre>
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BadRange);
-        return StreamSupport.longStream
-                (new RandomLongsSpliterator
-                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-                 false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values, each between zero
-     * (inclusive) and one (exclusive).
-     *
-     * <p>A pseudorandom {@code double} value is generated as if it's the result
-     * of calling the method {@link #nextDouble()}.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of {@code double} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @since 1.8
-     */
-    public DoubleStream doubles(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
-        return StreamSupport.doubleStream
-                (new RandomDoublesSpliterator
-                         (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
-                 false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values, each between zero (inclusive) and one
-     * (exclusive).
-     *
-     * <p>A pseudorandom {@code double} value is generated as if it's the result
-     * of calling the method {@link #nextDouble()}.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code double} values
-     * @since 1.8
-     */
-    public DoubleStream doubles() {
-        return StreamSupport.doubleStream
-                (new RandomDoublesSpliterator
-                         (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
-                 false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values, each conforming to the given origin
-     * (inclusive) and bound (exclusive).
-     *
-     * <p>A pseudorandom {@code double} value is generated as if it's the result
-     * of calling the following method with the origin and bound:
-     * <pre> {@code
-     * double nextDouble(double origin, double bound) {
-     *   double r = nextDouble();
-     *   r = r * (bound - origin) + origin;
-     *   if (r >= bound) // correct for rounding
-     *     r = Math.nextDown(bound);
-     *   return r;
-     * }}</pre>
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public DoubleStream doubles(long streamSize, double randomNumberOrigin,
-                                double randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BadSize);
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BadRange);
-        return StreamSupport.doubleStream
-                (new RandomDoublesSpliterator
-                         (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-                 false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values, each conforming to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * <p>A pseudorandom {@code double} value is generated as if it's the result
-     * of calling the following method with the origin and bound:
-     * <pre> {@code
-     * double nextDouble(double origin, double bound) {
-     *   double r = nextDouble();
-     *   r = r * (bound - origin) + origin;
-     *   if (r >= bound) // correct for rounding
-     *     r = Math.nextDown(bound);
-     *   return r;
-     * }}</pre>
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BadRange);
-        return StreamSupport.doubleStream
-                (new RandomDoublesSpliterator
-                         (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-                 false);
-    }
-
-    /**
-     * Spliterator for int streams.  We multiplex the four int
-     * versions into one class by treating a bound less than origin as
-     * unbounded, and also by treating "infinite" as equivalent to
-     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
-     * approach. The long and double versions of this class are
-     * identical except for types.
-     */
-    static final class RandomIntsSpliterator implements Spliterator.OfInt {
-        final Random rng;
-        long index;
-        final long fence;
-        final int origin;
-        final int bound;
-        RandomIntsSpliterator(Random rng, long index, long fence,
-                              int origin, int bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomIntsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                   new RandomIntsSpliterator(rng, i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextInt(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                Random r = rng;
-                int o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextInt(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    static final class RandomLongsSpliterator implements Spliterator.OfLong {
-        final Random rng;
-        long index;
-        final long fence;
-        final long origin;
-        final long bound;
-        RandomLongsSpliterator(Random rng, long index, long fence,
-                               long origin, long bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomLongsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                   new RandomLongsSpliterator(rng, i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextLong(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                Random r = rng;
-                long o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextLong(o, b));
-                } while (++i < f);
-            }
-        }
-
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
-        final Random rng;
-        long index;
-        final long fence;
-        final double origin;
-        final double bound;
-        RandomDoublesSpliterator(Random rng, long index, long fence,
-                                 double origin, double bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomDoublesSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                   new RandomDoublesSpliterator(rng, i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextDouble(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                Random r = rng;
-                double o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextDouble(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
     /**
      * Serializable fields for Random.
      *
@@ -1228,4 +569,164 @@
     private void resetSeed(long seedVal) {
         unsafe.putReferenceVolatile(this, seedOffset, new AtomicLong(seedVal));
     }
+
+    // Methods required by class AbstractSpliteratorGenerator
+    public Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
+        return new RandomIntsSpliterator(this, index, fence, origin, bound);
+    }
+    public Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) {
+        return new RandomLongsSpliterator(this, index, fence, origin, bound);
+    }
+    public Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) {
+        return new RandomDoublesSpliterator(this, index, fence, origin, bound);
+    }
+
+    /**
+     * Spliterators for producing streams. These are based on abstract spliterator classes provided
+     * by class AbstractSpliteratorGenerator. Each one needs to define only a constructor and two
+     * methods.
+     */
+    static class RandomIntsSpliterator extends RandomSupport.RandomSpliterator
+                                       implements Spliterator.OfInt {
+        final AbstractSpliteratorGenerator generatingGenerator;
+        final int origin;
+        final int bound;
+
+        RandomIntsSpliterator(AbstractSpliteratorGenerator generatingGenerator,
+                              long index, long fence, int origin, int bound) {
+            super(index, fence);
+            this.generatingGenerator = generatingGenerator;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public Spliterator.OfInt trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            if (m <= i) return null;
+            index = m;
+            // The same generatingGenerator is used, with no splitting or copying.
+            return new RandomIntsSpliterator(generatingGenerator, i, m, origin, bound);
+        }
+
+        public boolean tryAdvance(IntConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(RandomSupport.boundedNextInt(generatingGenerator, origin, bound));
+                index = i + 1;
+                return true;
+            }
+            else return false;
+        }
+
+        public void forEachRemaining(IntConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                RandomGenerator r = generatingGenerator;
+                int o = origin, b = bound;
+                do {
+                    consumer.accept(RandomSupport.boundedNextInt(r, o, b));
+                } while (++i < f);
+            }
+        }
+    }
+
+    /**
+     * Spliterator for long streams.
+     */
+    static class RandomLongsSpliterator extends RandomSupport.RandomSpliterator
+                                        implements Spliterator.OfLong {
+        final AbstractSpliteratorGenerator generatingGenerator;
+        final long origin;
+        final long bound;
+
+        RandomLongsSpliterator(AbstractSpliteratorGenerator generatingGenerator,
+                               long index, long fence, long origin, long bound) {
+            super(index, fence);
+            this.generatingGenerator = generatingGenerator;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public Spliterator.OfLong trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            if (m <= i) return null;
+            index = m;
+            // The same generatingGenerator is used, with no splitting or copying.
+            return new RandomLongsSpliterator(generatingGenerator, i, m, origin, bound);
+        }
+
+        public boolean tryAdvance(LongConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(RandomSupport.boundedNextLong(generatingGenerator, origin, bound));
+                index = i + 1;
+                return true;
+            }
+            else return false;
+        }
+
+        public void forEachRemaining(LongConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                RandomGenerator r = generatingGenerator;
+                long o = origin, b = bound;
+                do {
+                    consumer.accept(RandomSupport.boundedNextLong(r, o, b));
+                } while (++i < f);
+            }
+        }
+    }
+
+    /**
+     * Spliterator for double streams.
+     */
+    static class RandomDoublesSpliterator extends RandomSupport.RandomSpliterator
+                                          implements Spliterator.OfDouble {
+        final AbstractSpliteratorGenerator generatingGenerator;
+        final double origin;
+        final double bound;
+
+        RandomDoublesSpliterator(AbstractSpliteratorGenerator generatingGenerator,
+                                 long index, long fence, double origin, double bound) {
+            super(index, fence);
+            this.generatingGenerator = generatingGenerator;
+            this.origin = origin; this.bound = bound;
+        }
+
+        public Spliterator.OfDouble trySplit() {
+            long i = index, m = (i + fence) >>> 1;
+            if (m <= i) return null;
+            index = m;
+            // The same generatingGenerator is used, with no splitting or copying.
+            return new RandomDoublesSpliterator(generatingGenerator, i, m, origin, bound);
+        }
+
+        public boolean tryAdvance(DoubleConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                consumer.accept(RandomSupport.boundedNextDouble(generatingGenerator, origin, bound));
+                index = i + 1;
+                return true;
+            }
+            else return false;
+        }
+
+        public void forEachRemaining(DoubleConsumer consumer) {
+            if (consumer == null) throw new NullPointerException();
+            long i = index, f = fence;
+            if (i < f) {
+                index = f;
+                RandomGenerator r = generatingGenerator;
+                double o = origin, b = bound;
+                do {
+                    consumer.accept(RandomSupport.boundedNextDouble(r, o, b));
+                } while (++i < f);
+            }
+        }
+    }
 }
--- a/src/java.base/share/classes/java/util/SplittableRandom.java	Thu Nov 14 12:36:46 2019 -0400
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java	Thu Nov 14 12:39:49 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,17 +22,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package java.util;
 
+import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.DoubleConsumer;
-import java.util.function.IntConsumer;
-import java.util.function.LongConsumer;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-import java.util.stream.StreamSupport;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
@@ -52,15 +48,15 @@
  * types and ranges, but similar properties are expected to hold, at
  * least approximately, for others as well. The <em>period</em>
  * (length of any series of generated values before it repeats) is at
- * least 2<sup>64</sup>.
+ * least 2<sup>64</sup>. </li>
  *
- * <li>Method {@link #split} constructs and returns a new
+ * <li> Method {@link #split} constructs and returns a new
  * SplittableRandom instance that shares no mutable state with the
  * current instance. However, with very high probability, the
  * values collectively generated by the two objects have the same
  * statistical properties as if the same quantity of values were
  * generated by a single thread using a single {@code
- * SplittableRandom} object.
+ * SplittableRandom} object.  </li>
  *
  * <li>Instances of SplittableRandom are <em>not</em> thread-safe.
  * They are designed to be split, not shared, across threads. For
@@ -71,7 +67,7 @@
  *
  * <li>This class provides additional methods for generating random
  * streams, that employ the above techniques when used in {@code
- * stream.parallel()} mode.
+ * stream.parallel()} mode.</li>
  *
  * </ul>
  *
@@ -80,13 +76,13 @@
  * in security-sensitive applications. Additionally,
  * default-constructed instances do not use a cryptographically random
  * seed unless the {@linkplain System#getProperty system property}
- * {@systemProperty java.util.secureRandomSeed} is set to {@code true}.
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
  *
  * @author  Guy Steele
  * @author  Doug Lea
  * @since   1.8
  */
-public final class SplittableRandom {
+public final class SplittableRandom extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -161,12 +157,6 @@
     private static final long GOLDEN_GAMMA = 0x9e3779b97f4a7c15L;
 
     /**
-     * The least non-zero value returned by nextDouble(). This value
-     * is scaled by a random value of 53 bits to produce a result.
-     */
-    private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53);
-
-    /**
      * The seed. Updated only via method nextSeed.
      */
     private long seed;
@@ -186,6 +176,7 @@
 
     /**
      * Computes Stafford variant 13 of 64bit mix function.
+     * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
      */
     private static long mix64(long z) {
         z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
@@ -195,6 +186,7 @@
 
     /**
      * Returns the 32 high bits of Stafford variant 4 mix64 function as int.
+     * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
      */
     private static int mix32(long z) {
         z = (z ^ (z >>> 33)) * 0x62a9d9ed799705f5L;
@@ -203,6 +195,8 @@
 
     /**
      * Returns the gamma value to use for a new split instance.
+     * Uses the 64bit mix function from MurmurHash3.
+     * https://github.com/aappleby/smhasher/wiki/MurmurHash3
      */
     private static long mixGamma(long z) {
         z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; // MurmurHash3 mix constants
@@ -219,141 +213,10 @@
         return seed += gamma;
     }
 
-    // IllegalArgumentException messages
-    static final String BAD_BOUND = "bound must be positive";
-    static final String BAD_RANGE = "bound must be greater than origin";
-    static final String BAD_SIZE  = "size must be non-negative";
-
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen
-        = new AtomicLong(mix64(System.currentTimeMillis()) ^
-                         mix64(System.nanoTime()));
-
-    // at end of <clinit> to survive static initialization circularity
-    static {
-        if (java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Boolean>() {
-                public Boolean run() {
-                    return Boolean.getBoolean("java.util.secureRandomSeed");
-                }})) {
-            byte[] seedBytes = java.security.SecureRandom.getSeed(8);
-            long s = (long)seedBytes[0] & 0xffL;
-            for (int i = 1; i < 8; ++i)
-                s = (s << 8) | ((long)seedBytes[i] & 0xffL);
-            defaultGen.set(s);
-        }
-    }
-
-    /*
-     * Internal versions of nextX methods used by streams, as well as
-     * the public nextX(origin, bound) methods.  These exist mainly to
-     * avoid the need for multiple versions of stream spliterators
-     * across the different exported forms of streams.
-     */
-
-    /**
-     * The form of nextLong used by LongStream Spliterators.  If
-     * origin is greater than bound, acts as unbounded form of
-     * nextLong, else as bounded form.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final long internalNextLong(long origin, long bound) {
-        /*
-         * Four Cases:
-         *
-         * 1. If the arguments indicate unbounded form, act as
-         * nextLong().
-         *
-         * 2. If the range is an exact power of two, apply the
-         * associated bit mask.
-         *
-         * 3. If the range is positive, loop to avoid potential bias
-         * when the implicit nextLong() bound (2<sup>64</sup>) is not
-         * evenly divisible by the range. The loop rejects candidates
-         * computed from otherwise over-represented values.  The
-         * expected number of iterations under an ideal generator
-         * varies from 1 to 2, depending on the bound. The loop itself
-         * takes an unlovable form. Because the first candidate is
-         * already available, we need a break-in-the-middle
-         * construction, which is concisely but cryptically performed
-         * within the while-condition of a body-less for loop.
-         *
-         * 4. Otherwise, the range cannot be represented as a positive
-         * long.  The loop repeatedly generates unbounded longs until
-         * obtaining a candidate meeting constraints (with an expected
-         * number of iterations of less than two).
-         */
-
-        long r = mix64(nextSeed());
-        if (origin < bound) {
-            long n = bound - origin, m = n - 1;
-            if ((n & m) == 0L)  // power of two
-                r = (r & m) + origin;
-            else if (n > 0L) {  // reject over-represented candidates
-                for (long u = r >>> 1;            // ensure nonnegative
-                     u + m - (r = u % n) < 0L;    // rejection check
-                     u = mix64(nextSeed()) >>> 1) // retry
-                    ;
-                r += origin;
-            }
-            else {              // range not representable as long
-                while (r < origin || r >= bound)
-                    r = mix64(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextInt used by IntStream Spliterators.
-     * Exactly the same as long version, except for types.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final int internalNextInt(int origin, int bound) {
-        int r = mix32(nextSeed());
-        if (origin < bound) {
-            int n = bound - origin, m = n - 1;
-            if ((n & m) == 0)
-                r = (r & m) + origin;
-            else if (n > 0) {
-                for (int u = r >>> 1;
-                     u + m - (r = u % n) < 0;
-                     u = mix32(nextSeed()) >>> 1)
-                    ;
-                r += origin;
-            }
-            else {
-                while (r < origin || r >= bound)
-                    r = mix32(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextDouble used by DoubleStream Spliterators.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final double internalNextDouble(double origin, double bound) {
-        double r = (nextLong() >>> 11) * DOUBLE_UNIT;
-        if (origin < bound) {
-            r = r * (bound - origin) + origin;
-            if (r >= bound) // correct for rounding
-                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-        }
-        return r;
-    }
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /* ---------------- public methods ---------------- */
 
@@ -375,11 +238,13 @@
      * may, and typically does, vary across program invocations.
      */
     public SplittableRandom() { // emulate defaultGen.split()
-        long s = defaultGen.getAndAdd(GOLDEN_GAMMA << 1);
+        long s = defaultGen.getAndAdd(2 * GOLDEN_GAMMA);
         this.seed = mix64(s);
         this.gamma = mixGamma(s + GOLDEN_GAMMA);
     }
 
+    //    public SplittableRandom copy() { return new SplittableRandom(seed, gamma); }
+
     /**
      * Constructs and returns a new SplittableRandom instance that
      * shares no mutable state with this instance. However, with very
@@ -398,24 +263,8 @@
         return new SplittableRandom(nextLong(), mixGamma(nextSeed()));
     }
 
-    /**
-     * Fills a user-supplied byte array with generated pseudorandom bytes.
-     *
-     * @param  bytes the byte array to fill with pseudorandom bytes
-     * @throws NullPointerException if bytes is null
-     * @since  10
-     */
-    public void nextBytes(byte[] bytes) {
-        int i = 0;
-        int len = bytes.length;
-        for (int words = len >> 3; words--> 0; ) {
-            long rnd = nextLong();
-            for (int n = 8; n--> 0; rnd >>>= Byte.SIZE)
-                bytes[i++] = (byte)rnd;
-        }
-        if (i < len)
-            for (long rnd = nextLong(); i < len; rnd >>>= Byte.SIZE)
-                bytes[i++] = (byte)rnd;
+    public SplittableRandom split(SplittableGenerator source) {
+        return new SplittableRandom(source.nextLong(), mixGamma(source.nextLong()));
     }
 
     /**
@@ -428,49 +277,6 @@
     }
 
     /**
-     * Returns a pseudorandom {@code int} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code int} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public int nextInt(int bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        // Specialize internalNextInt for origin 0
-        int r = mix32(nextSeed());
-        int m = bound - 1;
-        if ((bound & m) == 0) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (int u = r >>> 1;
-                 u + m - (r = u % bound) < 0;
-                 u = mix32(nextSeed()) >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code int} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public int nextInt(int origin, int bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextInt(origin, bound);
-    }
-
-    /**
      * Returns a pseudorandom {@code long} value.
      *
      * @return a pseudorandom {@code long} value
@@ -479,537 +285,10 @@
         return mix64(nextSeed());
     }
 
-    /**
-     * Returns a pseudorandom {@code long} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code long} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public long nextLong(long bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        // Specialize internalNextLong for origin 0
-        long r = mix64(nextSeed());
-        long m = bound - 1;
-        if ((bound & m) == 0L) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (long u = r >>> 1;
-                 u + m - (r = u % bound) < 0L;
-                 u = mix64(nextSeed()) >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code long} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code long} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public long nextLong(long origin, long bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextLong(origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between zero
-     * (inclusive) and one (exclusive).
-     *
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and one (exclusive)
-     */
-    public double nextDouble() {
-        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between 0.0
-     * (inclusive) and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public double nextDouble(double bound) {
-        if (!(bound > 0.0))
-            throw new IllegalArgumentException(BAD_BOUND);
-        double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
-        return (result < bound) ?  result : // correct for rounding
-            Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between the specified
-     * origin (inclusive) and bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code double} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public double nextDouble(double origin, double bound) {
-        if (!(origin < bound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextDouble(origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code boolean} value.
-     *
-     * @return a pseudorandom {@code boolean} value
-     */
-    public boolean nextBoolean() {
-        return mix32(nextSeed()) < 0;
-    }
-
-    // stream methods, coded in a way intended to better isolate for
-    // maintenance purposes the small differences across forms.
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code int} values from this generator and/or
-     * one split from it.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code int} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    public IntStream ints(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, streamSize, Integer.MAX_VALUE, 0),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code int}
-     * values from this generator and/or one split from it.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code int} values
-     */
-    public IntStream ints() {
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code int} values from this generator and/or one split
-     * from it; each value conforms to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public IntStream ints(long streamSize, int randomNumberOrigin,
-                          int randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * int} values from this generator and/or one split from it; each value
-     * conforms to the given origin (inclusive) and bound (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code long} values from this generator and/or
-     * one split from it.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code long} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    public LongStream longs(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, streamSize, Long.MAX_VALUE, 0L),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * long} values from this generator and/or one split from it.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code long} values
-     */
-    public LongStream longs() {
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code long} values from this generator and/or one split
-     * from it; each value conforms to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public LongStream longs(long streamSize, long randomNumberOrigin,
-                            long randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
+    static final BigInteger PERIOD = BigInteger.ONE.shiftLeft(64);  // Period is 2**64
 
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * long} values from this generator and/or one split from it; each value
-     * conforms to the given origin (inclusive) and bound (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values from this generator and/or one split
-     * from it; each value is between zero (inclusive) and one (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of {@code double} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    public DoubleStream doubles(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, streamSize, Double.MAX_VALUE, 0.0),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values from this generator and/or one split from it; each value
-     * is between zero (inclusive) and one (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code double} values
-     */
-    public DoubleStream doubles() {
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values from this generator and/or one split
-     * from it; each value conforms to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public DoubleStream doubles(long streamSize, double randomNumberOrigin,
-                                double randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values from this generator and/or one split from it; each value
-     * conforms to the given origin (inclusive) and bound (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     */
-    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Spliterator for int streams.  We multiplex the four int
-     * versions into one class by treating a bound less than origin as
-     * unbounded, and also by treating "infinite" as equivalent to
-     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
-     * approach. The long and double versions of this class are
-     * identical except for types.
-     */
-    private static final class RandomIntsSpliterator
-            implements Spliterator.OfInt {
-        final SplittableRandom rng;
-        long index;
-        final long fence;
-        final int origin;
-        final int bound;
-        RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
-                              int origin, int bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomIntsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextInt(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                SplittableRandom r = rng;
-                int o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextInt(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    private static final class RandomLongsSpliterator
-            implements Spliterator.OfLong {
-        final SplittableRandom rng;
-        long index;
-        final long fence;
-        final long origin;
-        final long bound;
-        RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
-                               long origin, long bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomLongsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextLong(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                SplittableRandom r = rng;
-                long o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextLong(o, b));
-                } while (++i < f);
-            }
-        }
-
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    private static final class RandomDoublesSpliterator
-            implements Spliterator.OfDouble {
-        final SplittableRandom rng;
-        long index;
-        final long fence;
-        final double origin;
-        final double bound;
-        RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
-                                 double origin, double bound) {
-            this.rng = rng; this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomDoublesSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(rng.internalNextDouble(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                SplittableRandom r = rng;
-                double o = origin, b = bound;
-                do {
-                    consumer.accept(r.internalNextDouble(o, b));
-                } while (++i < f);
-            }
-        }
+    public BigInteger period() {
+        return PERIOD;
     }
 
 }
--- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Thu Nov 14 12:36:46 2019 -0400
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Thu Nov 14 12:39:49 2019 -0400
@@ -31,6 +31,9 @@
  * Written by Doug Lea with assistance from members of JCP JSR-166
  * Expert Group and released to the public domain, as explained at
  * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Additional modifications by Guy Steele in 2019 to refactor the code
+ * and to implement the {@link RandomGenerator} interface.
  */
 
 package java.util.concurrent;
@@ -41,13 +44,7 @@
 import java.util.Spliterator;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.DoubleConsumer;
-import java.util.function.IntConsumer;
-import java.util.function.LongConsumer;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-import java.util.stream.StreamSupport;
+import java.util.random.RandomSupport;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
 
@@ -123,19 +120,12 @@
      * SplittableRandom, that were in part derived from a previous
      * version of this class.
      *
-     * The nextLocalGaussian ThreadLocal supports the very rarely used
-     * nextGaussian method by providing a holder for the second of a
-     * pair of them. As is true for the base class version of this
-     * method, this time/space tradeoff is probably never worthwhile,
-     * but we provide identical statistical properties.
+     * This implementation of ThreadLocalRandom overrides the
+     * definition of the nextGaussian() method in the class Random,
+     * and instead uses the ziggurat-based algorithm that is the
+     * default for the RandomGenerator interface.
      */
 
-    private static long mix64(long z) {
-        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
-        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
-        return z ^ (z >>> 33);
-    }
-
     private static int mix32(long z) {
         z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
         return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
@@ -162,7 +152,7 @@
     static final void localInit() {
         int p = probeGenerator.addAndGet(PROBE_INCREMENT);
         int probe = (p == 0) ? 1 : p; // skip 0
-        long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
+        long seed = RandomSupport.mixMurmur64(seeder.getAndAdd(SEEDER_INCREMENT));
         Thread t = Thread.currentThread();
         U.putLong(t, SEED, seed);
         U.putInt(t, PROBE, probe);
@@ -212,82 +202,6 @@
     }
 
     /**
-     * The form of nextLong used by LongStream Spliterators.  If
-     * origin is greater than bound, acts as unbounded form of
-     * nextLong, else as bounded form.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final long internalNextLong(long origin, long bound) {
-        long r = mix64(nextSeed());
-        if (origin < bound) {
-            long n = bound - origin, m = n - 1;
-            if ((n & m) == 0L)  // power of two
-                r = (r & m) + origin;
-            else if (n > 0L) {  // reject over-represented candidates
-                for (long u = r >>> 1;            // ensure nonnegative
-                     u + m - (r = u % n) < 0L;    // rejection check
-                     u = mix64(nextSeed()) >>> 1) // retry
-                    ;
-                r += origin;
-            }
-            else {              // range not representable as long
-                while (r < origin || r >= bound)
-                    r = mix64(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextInt used by IntStream Spliterators.
-     * Exactly the same as long version, except for types.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final int internalNextInt(int origin, int bound) {
-        int r = mix32(nextSeed());
-        if (origin < bound) {
-            int n = bound - origin, m = n - 1;
-            if ((n & m) == 0)
-                r = (r & m) + origin;
-            else if (n > 0) {
-                for (int u = r >>> 1;
-                     u + m - (r = u % n) < 0;
-                     u = mix32(nextSeed()) >>> 1)
-                    ;
-                r += origin;
-            }
-            else {
-                while (r < origin || r >= bound)
-                    r = mix32(nextSeed());
-            }
-        }
-        return r;
-    }
-
-    /**
-     * The form of nextDouble used by DoubleStream Spliterators.
-     *
-     * @param origin the least value, unless greater than bound
-     * @param bound the upper bound (exclusive), must not equal origin
-     * @return a pseudorandom value
-     */
-    final double internalNextDouble(double origin, double bound) {
-        double r = (nextLong() >>> 11) * DOUBLE_UNIT;
-        if (origin < bound) {
-            r = r * (bound - origin) + origin;
-            if (r >= bound) // correct for rounding
-                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-        }
-        return r;
-    }
-
-    /**
      * Returns a pseudorandom {@code int} value.
      *
      * @return a pseudorandom {@code int} value
@@ -297,622 +211,14 @@
     }
 
     /**
-     * Returns a pseudorandom {@code int} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code int} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public int nextInt(int bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        int r = mix32(nextSeed());
-        int m = bound - 1;
-        if ((bound & m) == 0) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (int u = r >>> 1;
-                 u + m - (r = u % bound) < 0;
-                 u = mix32(nextSeed()) >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code int} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code int} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public int nextInt(int origin, int bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextInt(origin, bound);
-    }
-
-    /**
      * Returns a pseudorandom {@code long} value.
      *
      * @return a pseudorandom {@code long} value
      */
     public long nextLong() {
-        return mix64(nextSeed());
-    }
-
-    /**
-     * Returns a pseudorandom {@code long} value between zero (inclusive)
-     * and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code long} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public long nextLong(long bound) {
-        if (bound <= 0)
-            throw new IllegalArgumentException(BAD_BOUND);
-        long r = mix64(nextSeed());
-        long m = bound - 1;
-        if ((bound & m) == 0L) // power of two
-            r &= m;
-        else { // reject over-represented candidates
-            for (long u = r >>> 1;
-                 u + m - (r = u % bound) < 0L;
-                 u = mix64(nextSeed()) >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * Returns a pseudorandom {@code long} value between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code long} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public long nextLong(long origin, long bound) {
-        if (origin >= bound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextLong(origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between zero
-     * (inclusive) and one (exclusive).
-     *
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and one (exclusive)
-     */
-    public double nextDouble() {
-        return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between 0.0
-     * (inclusive) and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive).  Must be positive.
-     * @return a pseudorandom {@code double} value between zero
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public double nextDouble(double bound) {
-        if (!(bound > 0.0))
-            throw new IllegalArgumentException(BAD_BOUND);
-        double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
-        return (result < bound) ? result : // correct for rounding
-            Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between the specified
-     * origin (inclusive) and bound (exclusive).
-     *
-     * @param origin the least value returned
-     * @param bound the upper bound (exclusive)
-     * @return a pseudorandom {@code double} value between the origin
-     *         (inclusive) and the bound (exclusive)
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     */
-    public double nextDouble(double origin, double bound) {
-        if (!(origin < bound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return internalNextDouble(origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code boolean} value.
-     *
-     * @return a pseudorandom {@code boolean} value
-     */
-    public boolean nextBoolean() {
-        return mix32(nextSeed()) < 0;
-    }
-
-    /**
-     * Returns a pseudorandom {@code float} value between zero
-     * (inclusive) and one (exclusive).
-     *
-     * @return a pseudorandom {@code float} value between zero
-     *         (inclusive) and one (exclusive)
-     */
-    public float nextFloat() {
-        return (mix32(nextSeed()) >>> 8) * FLOAT_UNIT;
-    }
-
-    public double nextGaussian() {
-        // Use nextLocalGaussian instead of nextGaussian field
-        Double d = nextLocalGaussian.get();
-        if (d != null) {
-            nextLocalGaussian.set(null);
-            return d.doubleValue();
-        }
-        double v1, v2, s;
-        do {
-            v1 = 2 * nextDouble() - 1; // between -1 and 1
-            v2 = 2 * nextDouble() - 1; // between -1 and 1
-            s = v1 * v1 + v2 * v2;
-        } while (s >= 1 || s == 0);
-        double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
-        nextLocalGaussian.set(Double.valueOf(v2 * multiplier));
-        return v1 * multiplier;
-    }
-
-    // stream methods, coded in a way intended to better isolate for
-    // maintenance purposes the small differences across forms.
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code int} values.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code int} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @since 1.8
-     */
-    public IntStream ints(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (0L, streamSize, Integer.MAX_VALUE, 0),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code int}
-     * values.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code int} values
-     * @since 1.8
-     */
-    public IntStream ints() {
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number
-     * of pseudorandom {@code int} values, each conforming to the given
-     * origin (inclusive) and bound (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public IntStream ints(long streamSize, int randomNumberOrigin,
-                          int randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * int} values, each conforming to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code int} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.intStream
-            (new RandomIntsSpliterator
-             (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code long} values.
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of pseudorandom {@code long} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @since 1.8
-     */
-    public LongStream longs(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (0L, streamSize, Long.MAX_VALUE, 0L),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code long}
-     * values.
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code long} values
-     * @since 1.8
-     */
-    public LongStream longs() {
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code long}, each conforming to the given origin
-     * (inclusive) and bound (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public LongStream longs(long streamSize, long randomNumberOrigin,
-                            long randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
+        return RandomSupport.mixMurmur64(nextSeed());
     }
 
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * long} values, each conforming to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code long} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
-        if (randomNumberOrigin >= randomNumberBound)
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.longStream
-            (new RandomLongsSpliterator
-             (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values, each between zero
-     * (inclusive) and one (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @return a stream of {@code double} values
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @since 1.8
-     */
-    public DoubleStream doubles(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (0L, streamSize, Double.MAX_VALUE, 0.0),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values, each between zero (inclusive) and one
-     * (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandom {@code double} values
-     * @since 1.8
-     */
-    public DoubleStream doubles() {
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
-             false);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandom {@code double} values, each conforming to the given origin
-     * (inclusive) and bound (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public DoubleStream doubles(long streamSize, double randomNumberOrigin,
-                                double randomNumberBound) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (0L, streamSize, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code
-     * double} values, each conforming to the given origin (inclusive) and bound
-     * (exclusive).
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     *
-     * @param randomNumberOrigin the origin (inclusive) of each random value
-     * @param randomNumberBound the bound (exclusive) of each random value
-     * @return a stream of pseudorandom {@code double} values,
-     *         each with the given origin (inclusive) and bound (exclusive)
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     * @since 1.8
-     */
-    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
-        if (!(randomNumberOrigin < randomNumberBound))
-            throw new IllegalArgumentException(BAD_RANGE);
-        return StreamSupport.doubleStream
-            (new RandomDoublesSpliterator
-             (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
-             false);
-    }
-
-    /**
-     * Spliterator for int streams.  We multiplex the four int
-     * versions into one class by treating a bound less than origin as
-     * unbounded, and also by treating "infinite" as equivalent to
-     * Long.MAX_VALUE. For splits, it uses the standard divide-by-two
-     * approach. The long and double versions of this class are
-     * identical except for types.
-     */
-    private static final class RandomIntsSpliterator
-            implements Spliterator.OfInt {
-        long index;
-        final long fence;
-        final int origin;
-        final int bound;
-        RandomIntsSpliterator(long index, long fence,
-                              int origin, int bound) {
-            this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomIntsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomIntsSpliterator(i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(ThreadLocalRandom.current().internalNextInt(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(IntConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                int o = origin, b = bound;
-                ThreadLocalRandom rng = ThreadLocalRandom.current();
-                do {
-                    consumer.accept(rng.internalNextInt(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    private static final class RandomLongsSpliterator
-            implements Spliterator.OfLong {
-        long index;
-        final long fence;
-        final long origin;
-        final long bound;
-        RandomLongsSpliterator(long index, long fence,
-                               long origin, long bound) {
-            this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomLongsSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomLongsSpliterator(i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(ThreadLocalRandom.current().internalNextLong(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(LongConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                long o = origin, b = bound;
-                ThreadLocalRandom rng = ThreadLocalRandom.current();
-                do {
-                    consumer.accept(rng.internalNextLong(o, b));
-                } while (++i < f);
-            }
-        }
-
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    private static final class RandomDoublesSpliterator
-            implements Spliterator.OfDouble {
-        long index;
-        final long fence;
-        final double origin;
-        final double bound;
-        RandomDoublesSpliterator(long index, long fence,
-                                 double origin, double bound) {
-            this.index = index; this.fence = fence;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public RandomDoublesSpliterator trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            return (m <= i) ? null :
-                new RandomDoublesSpliterator(i, index = m, origin, bound);
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-
-        public boolean tryAdvance(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(ThreadLocalRandom.current().internalNextDouble(origin, bound));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(DoubleConsumer consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                double o = origin, b = bound;
-                ThreadLocalRandom rng = ThreadLocalRandom.current();
-                do {
-                    consumer.accept(rng.internalNextDouble(o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-
     // Within-package utilities
 
     /*
@@ -1039,13 +345,6 @@
      */
     private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
 
-    /**
-     * The least non-zero value returned by nextDouble(). This value
-     * is scaled by a random value of 53 bits to produce a result.
-     */
-    private static final double DOUBLE_UNIT = 0x1.0p-53;  // 1.0  / (1L << 53)
-    private static final float  FLOAT_UNIT  = 0x1.0p-24f; // 1.0f / (1 << 24)
-
     // IllegalArgumentException messages
     static final String BAD_BOUND = "bound must be positive";
     static final String BAD_RANGE = "bound must be greater than origin";
@@ -1066,10 +365,6 @@
     private static final long INHERITEDACCESSCONTROLCONTEXT
         = U.objectFieldOffset(Thread.class, "inheritedAccessControlContext");
 
-    /** Rarely-used holder for the second of a pair of Gaussians */
-    private static final ThreadLocal<Double> nextLocalGaussian =
-        new ThreadLocal<>();
-
     /** Generates per-thread initialization/probe field */
     private static final AtomicInteger probeGenerator = new AtomicInteger();
 
@@ -1080,8 +375,8 @@
      * The next seed for default constructors.
      */
     private static final AtomicLong seeder
-        = new AtomicLong(mix64(System.currentTimeMillis()) ^
-                         mix64(System.nanoTime()));
+        = new AtomicLong(RandomSupport.mixMurmur64(System.currentTimeMillis()) ^
+                         RandomSupport.mixMurmur64(System.nanoTime()));
 
     // at end of <clinit> to survive static initialization circularity
     static {
--- a/src/java.base/share/classes/module-info.java	Thu Nov 14 12:36:46 2019 -0400
+++ b/src/java.base/share/classes/module-info.java	Thu Nov 14 12:39:49 2019 -0400
@@ -112,6 +112,7 @@
     exports java.util.concurrent.locks;
     exports java.util.function;
     exports java.util.jar;
+    exports java.util.random;
     exports java.util.regex;
     exports java.util.spi;
     exports java.util.stream;
@@ -350,6 +351,7 @@
     uses java.time.chrono.AbstractChronology;
     uses java.time.chrono.Chronology;
     uses java.time.zone.ZoneRulesProvider;
+    uses java.util.random.RandomGenerator;
     uses java.util.spi.CalendarDataProvider;
     uses java.util.spi.CalendarNameProvider;
     uses java.util.spi.CurrencyNameProvider;
@@ -373,4 +375,16 @@
 
     provides java.nio.file.spi.FileSystemProvider with
         jdk.internal.jrtfs.JrtFileSystemProvider;
+
+    provides java.util.random.RandomGenerator with
+        java.security.SecureRandom,
+        java.util.Random,
+        java.util.random.L128X256MixRandom,
+        java.util.random.L64X1024MixRandom,
+        java.util.random.L64X128MixRandom,
+        java.util.random.L64X256MixRandom,
+        java.util.random.MRG32k3a,
+        java.util.random.Xoroshiro128StarStar,
+        java.util.random.Xoshiro256StarStar;
+
 }