Reorganize the abstract and interface classes. JDK-8193209-branch
authorjlaskey
Fri, 26 Jul 2019 15:37:05 -0300
branchJDK-8193209-branch
changeset 57547 56cbdc3ea079
parent 57546 1ca1cfdcb451
child 57671 6a4be8bf8990
Reorganize the abstract and interface classes.
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/java/util/random/AbstractArbitrarilyJumpableRNG.java
src/java.base/share/classes/java/util/random/AbstractSharedRNG.java
src/java.base/share/classes/java/util/random/AbstractSpliteratorRNG.java
src/java.base/share/classes/java/util/random/AbstractSplittableRNG.java
src/java.base/share/classes/java/util/random/ArbitrarilyJumpableRNG.java
src/java.base/share/classes/java/util/random/JumpableRNG.java
src/java.base/share/classes/java/util/random/L128X256MixRandom.java
src/java.base/share/classes/java/util/random/L32X64MixRandom.java
src/java.base/share/classes/java/util/random/L64X1024MixRandom.java
src/java.base/share/classes/java/util/random/L64X1024Random.java
src/java.base/share/classes/java/util/random/L64X128MixRandom.java
src/java.base/share/classes/java/util/random/L64X128Random.java
src/java.base/share/classes/java/util/random/L64X256MixRandom.java
src/java.base/share/classes/java/util/random/L64X256Random.java
src/java.base/share/classes/java/util/random/LeapableRNG.java
src/java.base/share/classes/java/util/random/MRG32k3a.java
src/java.base/share/classes/java/util/random/RNGSupport.java
src/java.base/share/classes/java/util/random/RandomGenerator.java
src/java.base/share/classes/java/util/random/RandomNumberGenerator.java
src/java.base/share/classes/java/util/random/RandomSupport.java
src/java.base/share/classes/java/util/random/SplittableRNG.java
src/java.base/share/classes/java/util/random/StreamableRNG.java
src/java.base/share/classes/java/util/random/Xoroshiro128Plus.java
src/java.base/share/classes/java/util/random/Xoroshiro128StarStar.java
src/java.base/share/classes/java/util/random/Xoshiro256StarStar.java
src/java.base/share/classes/module-info.java
--- a/src/java.base/share/classes/java/security/SecureRandom.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/security/SecureRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,7 +27,7 @@
 
 import java.math.BigInteger;
 import java.util.*;
-import java.util.random.RandomNumberGenerator;
+import java.util.random.RandomGenerator;
 import java.util.regex.*;
 import java.security.Provider.Service;
 import sun.security.jca.*;
@@ -1030,7 +1030,7 @@
      */
     @Override
     public BigInteger period() {
-        return RandomNumberGenerator.HUGE_PERIOD;
+        return RandomGenerator.HUGE_PERIOD;
     }
 
     // Declare serialVersionUID to be compatible with JDK1.1
--- a/src/java.base/share/classes/java/util/Random.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/Random.java	Fri Jul 26 15:37:05 2019 -0300
@@ -29,13 +29,19 @@
 
 import java.io.*;
 import java.math.BigInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.DoubleConsumer;
+import java.util.function.Function;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
 import java.util.Objects;
+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.ServiceLoader;
 import java.util.ServiceLoader.Provider;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Function;
-import java.util.random.AbstractSharedRNG;
-import java.util.random.RandomNumberGenerator;
+import java.util.Spliterator;
 import java.util.stream.Collectors;
 
 /**
@@ -76,7 +82,7 @@
  * @since   1.0
  */
 public
-class Random extends AbstractSharedRNG implements java.io.Serializable {
+class Random extends AbstractSpliteratorGenerator implements java.io.Serializable {
     /** use serialVersionUID from JDK 1.1 for interoperability */
     static final long serialVersionUID = 3905348978240129619L;
 
@@ -507,24 +513,24 @@
      *
      * @since 14
      */
-    public static RandomNumberGenerator byName(String name) throws IllegalArgumentException {
+    public static RandomGenerator byName(String name) throws IllegalArgumentException {
         Objects.requireNonNull(name);
-        Map<String, Provider<RandomNumberGenerator>> rngs = getRNGMap();
-        Provider<RandomNumberGenerator> provider = rngs.get(name.toUpperCase());
+        Map<String, Provider<RandomGenerator>> rngs = getGeneratorMap();
+        Provider<RandomGenerator> provider = rngs.get(name.toUpperCase());
         if (provider == null) {
             throw new IllegalArgumentException(name + " is an unknown random number generator");
         }
         return provider.get();
     }
 
-    private static Map<String, Provider<RandomNumberGenerator>> rngMap;
+    private static Map<String, Provider<RandomGenerator>> rngMap;
 
-    private static Map<String, Provider<RandomNumberGenerator>> getRNGMap() {
+    private static Map<String, Provider<RandomGenerator>> getGeneratorMap() {
         if (rngMap == null) {
             synchronized (Random.class) {
                 if (rngMap == null) {
                     rngMap = ServiceLoader
-                            .load(RandomNumberGenerator.class)
+                            .load(RandomGenerator.class)
                             .stream()
                             .filter(p -> !p.type().isInterface())
                             .collect(Collectors.toMap(p -> p.type().getSimpleName().toUpperCase(),
@@ -601,4 +607,158 @@
     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	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/SplittableRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -26,9 +26,9 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.random.AbstractSplittableRNG;
-import java.util.random.RNGSupport;
-import java.util.random.SplittableRNG;
+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
@@ -82,7 +82,7 @@
  * @author  Doug Lea
  * @since   1.8
  */
-public final class SplittableRandom extends AbstractSplittableRNG {
+public final class SplittableRandom extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -216,7 +216,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /* ---------------- public methods ---------------- */
 
@@ -263,7 +263,7 @@
         return new SplittableRandom(nextLong(), mixGamma(nextSeed()));
     }
 
-    public SplittableRandom split(SplittableRNG source) {
+    public SplittableRandom split(SplittableGenerator source) {
         return new SplittableRandom(source.nextLong(), mixGamma(source.nextLong()));
     }
 
--- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -33,7 +33,7 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  *
  * Additional modifications by Guy Steele in 2019 to refactor the code
- * and to implement the {@link RandomNumberGenerator} interface.
+ * and to implement the {@link RandomGenerator} interface.
  */
 
 package java.util.concurrent;
@@ -44,7 +44,7 @@
 import java.util.Spliterator;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.random.RNGSupport;
+import java.util.random.RandomSupport;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
 
@@ -123,7 +123,7 @@
      * 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 RandomNumberGenerator interface.
+     * default for the RandomGenerator interface.
      */
 
     private static int mix32(long z) {
@@ -152,7 +152,7 @@
     static final void localInit() {
         int p = probeGenerator.addAndGet(PROBE_INCREMENT);
         int probe = (p == 0) ? 1 : p; // skip 0
-        long seed = RNGSupport.mixMurmur64(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);
@@ -216,7 +216,7 @@
      * @return a pseudorandom {@code long} value
      */
     public long nextLong() {
-        return RNGSupport.mixMurmur64(nextSeed());
+        return RandomSupport.mixMurmur64(nextSeed());
     }
 
     // Within-package utilities
@@ -375,8 +375,8 @@
      * The next seed for default constructors.
      */
     private static final AtomicLong seeder
-        = new AtomicLong(RNGSupport.mixMurmur64(System.currentTimeMillis()) ^
-                         RNGSupport.mixMurmur64(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/java/util/random/AbstractArbitrarilyJumpableRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,534 +0,0 @@
-/*
- * Copyright (c) 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.Spliterator;
-import java.util.function.Consumer;
-import java.util.function.DoubleConsumer;
-import java.util.function.IntConsumer;
-import java.util.function.LongConsumer;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-/**
- * This class provides much of the implementation of the
- * {@link ArbitrarilyJumpableRNG} interface, to minimize the effort
- * required to implement that interface.
- *
- * To implement a pseudorandom number generator, the programmer needs
- * only to extend this class and provide implementations for the
- * methods {@code nextInt()}, {@code nextLong()}, {@code copy()},
- * {@code jump(distance)}, {@code jumpPowerOfTwo(distance)},
- * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
- *
- * (If the pseudorandom number generator also has the ability to split,
- * then the programmer may wish to consider instead extending
- * {@link AbstractSplittableRNG}.)
- *
- * The programmer should generally provide at least three constructors:
- * one that takes no arguments, one that accepts a {@code long}
- * seed value, and one that accepts an array of seed {@code byte} values.
- * This class provides a public {@code initialSeed()} method that may
- * be useful in initializing some static state from which to derive
- * defaults seeds for use by the no-argument constructor.
- *
- * For the stream methods (such as {@code ints()} and {@code splits()}),
- * this class provides {@link Spliterator}-based implementations that
- * allow parallel execution when appropriate.  In this respect
- * {@link ArbitrarilyJumpableRNG} differs from {@link JumpableRNG},
- * which provides very simple implementations that produce
- * sequential streams only.
- *
- * <p>An implementation of the {@link AbstractArbitrarilyJumpableRNG} class
- * must provide concrete definitions for the methods {@code nextInt()},
- * {@code nextLong}, {@code period()}, {@code copy()}, {@code jump(double)},
- * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
- * Default implementations are provided for all other methods.
- *
- * The documentation for each non-abstract method in this class
- * describes its implementation in detail. Each of these methods may
- * be overridden if the pseudorandom number generator being
- * implemented admits a more efficient implementation.
- *
- * @since 14
- */
-public abstract class AbstractArbitrarilyJumpableRNG
-    extends AbstractSpliteratorRNG implements ArbitrarilyJumpableRNG {
-
-    /*
-     * Implementation Overview.
-     *
-     * This class provides most of the "user API" methods needed to satisfy
-     * the interface ArbitrarilyJumpableRNG.  Most of these methods
-     * are in turn inherited from AbstractRNG and the non-public class
-     * AbstractSpliteratorRNG; this file implements four versions of the
-     * jumps method and defines the spliterators necessary to support them.
-     *
-     * File organization: First the non-public methods needed by the class
-     * AbstractSpliteratorRNG, then the main public methods, followed by some
-     * custom spliterator classes needed for stream methods.
-     */
-
-    // IllegalArgumentException messages
-    static final String BadLogDistance  = "logDistance must be non-negative";
-
-    // Methods required by class AbstractSpliteratorRNG
-    Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
-        return new RandomIntsSpliterator(this, index, fence, origin, bound);
-    }
-    Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) {
-        return new RandomLongsSpliterator(this, index, fence, origin, bound);
-    }
-    Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) {
-        return new RandomDoublesSpliterator(this, index, fence, origin, bound);
-    }
-
-    // Similar methods used by this class
-    Spliterator<RandomNumberGenerator> makeJumpsSpliterator(long index, long fence, double distance) {
-        return new RandomJumpsSpliterator(this, index, fence, distance);
-    }
-    Spliterator<JumpableRNG> makeLeapsSpliterator(long index, long fence, double distance) {
-        return new RandomLeapsSpliterator(this, index, fence, distance);
-    }
-    Spliterator<ArbitrarilyJumpableRNG> makeArbitraryJumpsSpliterator(long index, long fence, double distance) {
-        return new RandomArbitraryJumpsSpliterator(this, index, fence, distance);
-    }
-
-    /* ---------------- public methods ---------------- */
-
-    /**
-     * Returns a new generator whose internal state is an exact copy
-     * of this generator (therefore their future behavior should be
-     * identical if subjected to the same series of operations).
-     *
-     * @return a new object that is a copy of this generator
-     */
-    public abstract AbstractArbitrarilyJumpableRNG copy();
-
-    // Stream methods for jumping
-
-    private static <T> Stream<T> stream(Spliterator<T> srng) {
-        return StreamSupport.stream(srng, false);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link RandomNumberGenerator} interface, produced by jumping copies of this
-     * generator by different integer multiples of the default jump distance.
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     *         jumps(Long.MAX_VALUE)}.
-     */
-    public Stream<RandomNumberGenerator> jumps() {
-        return stream(makeJumpsSpliterator(0L, Long.MAX_VALUE, defaultJumpDistance()));
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * new pseudorandom number generators, each of which implements the
-     * {@link RandomNumberGenerator} interface, produced by jumping copies of this generator
-     * by different integer multiples of the default jump distance.
-     *
-     * @param streamSize the number of generators to generate
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     */
-    public Stream<RandomNumberGenerator> jumps(long streamSize) {
-        RNGSupport.checkStreamSize(streamSize);
-        return stream(makeJumpsSpliterator(0L, streamSize, defaultJumpDistance()));
-    }
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link RandomNumberGenerator} interface, produced by jumping copies of this
-     * generator by different integer multiples of the specified jump distance.
-     *
-     * @param distance a distance to jump forward within the state cycle
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     *         jumps(Long.MAX_VALUE)}.
-     */
-    public Stream<ArbitrarilyJumpableRNG> jumps(double distance) {
-        return stream(makeArbitraryJumpsSpliterator(0L, Long.MAX_VALUE, distance));
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link RandomNumberGenerator} interface, produced by
-     * jumping copies of this generator by different integer multiples of the specified jump
-     * distance.
-     *
-     * @param streamSize the number of generators to generate
-     * @param distance   a distance to jump forward within the state cycle
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     */
-    public Stream<ArbitrarilyJumpableRNG> jumps(long streamSize, double distance) {
-        RNGSupport.checkStreamSize(streamSize);
-        return stream(makeArbitraryJumpsSpliterator(0L, streamSize, distance));
-    }
-
-    /**
-     * Alter the state of this pseudorandom number generator so as to
-     * jump forward a very large, fixed distance (typically 2<sup>128</sup>
-     * or more) within its state cycle.  The distance used is that
-     * returned by method {@code defaultLeapDistance()}.
-     */
-    public void leap() {
-        jump(defaultLeapDistance());
-    }
-
-    // Stream methods for leaping
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link RandomNumberGenerator} interface, produced by jumping copies of this
-     * generator by different integer multiples of the default leap distance.
-     *
-     * @implNote This method is implemented to be equivalent to {@code leaps(Long.MAX_VALUE)}.
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     */
-    public Stream<JumpableRNG> leaps() {
-        return stream(makeLeapsSpliterator(0L, Long.MAX_VALUE, defaultLeapDistance()));
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link RandomNumberGenerator} interface, produced by
-     * jumping copies of this generator by different integer multiples of the default leap
-     * distance.
-     *
-     * @param streamSize the number of generators to generate
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     */
-    public Stream<JumpableRNG> leaps(long streamSize) {
-        return stream(makeLeapsSpliterator(0L, streamSize, defaultLeapDistance()));
-    }
-
-
-    /**
-     * 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
-     * {@code Long.MAX_VALUE}. For splits, we choose to override the method {@code trySplit()} to
-     * try to optimize execution speed: instead of dividing a range in half, it breaks off the
-     * largest possible chunk whose size is a power of two such that the remaining chunk is not
-     * empty. In this way, the necessary jump distances will tend to be powers of two.  The long
-     * and double versions of this class are identical except for types.
-     */
-    static class RandomIntsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfInt {
-        final ArbitrarilyJumpableRNG generatingRNG;
-        final int origin;
-        final int bound;
-
-        RandomIntsSpliterator(ArbitrarilyJumpableRNG generatingRNG, long index, long fence, int origin, int bound) {
-            super(index, fence);
-            this.origin = origin; this.bound = bound;
-            this.generatingRNG = generatingRNG;
-        }
-
-        public Spliterator.OfInt trySplit() {
-            long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
-            if (m <= i) return null;
-            index = m;
-            ArbitrarilyJumpableRNG r = generatingRNG;
-            return new RandomIntsSpliterator(r.copyAndJump((double)delta), 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(RNGSupport.boundedNextInt(generatingRNG, 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;
-                ArbitrarilyJumpableRNG r = generatingRNG;
-                int o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextInt(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    static class RandomLongsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfLong {
-        final ArbitrarilyJumpableRNG generatingRNG;
-        final long origin;
-        final long bound;
-
-        RandomLongsSpliterator(ArbitrarilyJumpableRNG generatingRNG, long index, long fence, long origin, long bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public Spliterator.OfLong trySplit() {
-            long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
-            if (m <= i) return null;
-            index = m;
-            ArbitrarilyJumpableRNG r = generatingRNG;
-            return new RandomLongsSpliterator(r.copyAndJump((double)delta), 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(RNGSupport.boundedNextLong(generatingRNG, 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;
-                ArbitrarilyJumpableRNG r = generatingRNG;
-                long o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextLong(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    static class RandomDoublesSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfDouble {
-        final ArbitrarilyJumpableRNG generatingRNG;
-        final double origin;
-        final double bound;
-
-        RandomDoublesSpliterator(ArbitrarilyJumpableRNG generatingRNG, long index, long fence, double origin, double bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public Spliterator.OfDouble trySplit() {
-
-            long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
-            if (m <= i) return null;
-            index = m;
-            ArbitrarilyJumpableRNG r = generatingRNG;
-            return new RandomDoublesSpliterator(r.copyAndJump((double)delta), 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(RNGSupport.boundedNextDouble(generatingRNG, 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;
-                ArbitrarilyJumpableRNG r = generatingRNG;
-                double o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextDouble(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    // Spliterators for producing new generators by jumping or leaping.  The
-    // complete implementation of each of these spliterators is right here.
-    // In the same manner as for the preceding spliterators, the method trySplit() is
-    // coded to optimize execution speed: instead of dividing a range
-    // in half, it breaks off the largest possible chunk whose
-    // size is a power of two such that the remaining chunk is not
-    // empty.  In this way, the necessary jump distances will tend to be
-    // powers of two.
-
-    /**
-     * Spliterator for stream of generators of type RandomNumberGenerator produced by jumps.
-     */
-    static class RandomJumpsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator<RandomNumberGenerator> {
-        ArbitrarilyJumpableRNG generatingRNG;
-        final double distance;
-
-        RandomJumpsSpliterator(ArbitrarilyJumpableRNG generatingRNG, long index, long fence, double distance) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG; this.distance = distance;
-        }
-
-        public Spliterator<RandomNumberGenerator> trySplit() {
-            long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
-            if (m <= i) return null;
-            index = m;
-            ArbitrarilyJumpableRNG r = generatingRNG;
-            // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
-            return new RandomJumpsSpliterator(r.copyAndJump(distance * (double)delta), i, m, distance);
-        }
-
-        public boolean tryAdvance(Consumer<? super RandomNumberGenerator> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(generatingRNG.copyAndJump(distance));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(Consumer<? super RandomNumberGenerator> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                ArbitrarilyJumpableRNG r = generatingRNG;
-                do {
-                    consumer.accept(r.copyAndJump(distance));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for stream of generators of type RandomNumberGenerator produced by leaps.
-     */
-    static class RandomLeapsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator<JumpableRNG> {
-        ArbitrarilyJumpableRNG generatingRNG;
-        final double distance;
-
-        RandomLeapsSpliterator(ArbitrarilyJumpableRNG generatingRNG, long index, long fence, double distance) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG; this.distance = distance;
-        }
-
-        public Spliterator<JumpableRNG> trySplit() {
-            long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
-            if (m <= i) return null;
-            index = m;
-            // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
-            return new RandomLeapsSpliterator(generatingRNG.copyAndJump(distance * (double)delta), i, m, distance);
-        }
-
-        public boolean tryAdvance(Consumer<? super JumpableRNG> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(generatingRNG.copyAndJump(distance));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(Consumer<? super JumpableRNG> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                ArbitrarilyJumpableRNG r = generatingRNG;
-                do {
-                    consumer.accept(r.copyAndJump(distance));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for stream of generators of type RandomNumberGenerator produced by arbitrary jumps.
-     */
-    static class RandomArbitraryJumpsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator<ArbitrarilyJumpableRNG> {
-        ArbitrarilyJumpableRNG generatingRNG;
-        final double distance;
-
-        RandomArbitraryJumpsSpliterator(ArbitrarilyJumpableRNG generatingRNG, long index, long fence, double distance) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG; this.distance = distance;
-        }
-
-        public Spliterator<ArbitrarilyJumpableRNG> trySplit() {
-            long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
-            if (m <= i) return null;
-            index = m;
-            // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
-            return new RandomArbitraryJumpsSpliterator(generatingRNG.copyAndJump(distance * (double)delta), i, m, distance);
-        }
-
-        public boolean tryAdvance(Consumer<? super ArbitrarilyJumpableRNG> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(generatingRNG.copyAndJump(distance));
-                index = i + 1;
-                return true;
-            }
-            return false;
-        }
-
-        public void forEachRemaining(Consumer<? super ArbitrarilyJumpableRNG> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                ArbitrarilyJumpableRNG r = generatingRNG;
-                do {
-                    consumer.accept(r.copyAndJump(distance));
-                } while (++i < f);
-            }
-        }
-    }
-
-}
--- a/src/java.base/share/classes/java/util/random/AbstractSharedRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.Spliterator;
-import java.util.function.DoubleConsumer;
-import java.util.function.IntConsumer;
-import java.util.function.LongConsumer;
-
-/**
- * This class provides much of the implementation of the {@link RandomNumberGenerator}
- * interface, to minimize the effort required to implement that interface.
- *
- * To implement a pseudorandom number generator, the programmer needs
- * only to extend this class and provide implementations for the
- * {@code nextInt()} and {@code nextLong()} methods.  In order for
- * the implementations of other methods in this class to operate
- * correctly, it must be safe for multiple threads to call these
- * methods on that same object.  The principal purpose of this class
- * is to support the implementations of {@link java.util.Random}
- * and {@code java.util.concurrent.ThreadLocalRandom}, but it could
- * in principle be used to implement others as well.
- *
- * (If the pseudorandom number generator has the ability to split or
- * jump, then the programmer may wish to consider instead extending
- * another abstract class, such as {@link AbstractSplittableRNG},
- * {@link ArbitrarilyJumpableRNG}, or {@link AbstractArbitrarilyJumpableRNG}.)
- *
- * The programmer should generally provide at least three constructors:
- * one that takes no arguments, one that accepts a {@code long}
- * seed value, and one that accepts an array of seed {@code byte} values.
- * This class provides a public {@code initialSeed()} method that may
- * be useful in initializing some static state from which to derive
- * defaults seeds for use by the no-argument constructor.
- *
- * For the stream methods (such as {@code ints()} and {@code splits()}),
- * this class provides {@link Spliterator}-based implementations that
- * allow parallel execution when appropriate.
- *
- * The documentation for each non-abstract method in this class
- * describes its implementation in detail. Each of these methods may
- * be overridden if the pseudorandom number generator being
- * implemented admits a more efficient implementation.
- *
- * @since 14
- */
-public abstract class AbstractSharedRNG extends AbstractSpliteratorRNG {
-    /*
-     * Implementation Overview.
-     *
-     * This class provides most of the "user API" methods needed to
-     * satisfy the interface RandomNumberGenerator.  Most of these methods
-     * are in turn inherited from AbstractRNG and the non-public class
-     * AbstractSpliteratorRNG; this file implements methods and spliterators
-     * necessary to support the latter.
-     *
-     * File organization: First some non-public methods, followed by
-     * some custom spliterator classes needed for stream methods.
-     */
-
-    // Methods required by class AbstractSpliteratorRNG
-    Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
-        return new RandomIntsSpliterator(this, index, fence, origin, bound);
-    }
-    Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) {
-        return new RandomLongsSpliterator(this, index, fence, origin, bound);
-    }
-    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 AbstractSpliteratorRNG. Each one needs to define only a constructor and two
-     * methods.
-     */
-    static class RandomIntsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfInt {
-        final AbstractSharedRNG generatingRNG;
-        final int origin;
-        final int bound;
-
-        RandomIntsSpliterator(AbstractSharedRNG generatingRNG, long index, long fence, int origin, int bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            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 generatingRNG is used, with no splitting or copying.
-            return new RandomIntsSpliterator(generatingRNG, 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(RNGSupport.boundedNextInt(generatingRNG, 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;
-                RandomNumberGenerator r = generatingRNG;
-                int o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextInt(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    static class RandomLongsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfLong {
-        final AbstractSharedRNG generatingRNG;
-        final long origin;
-        final long bound;
-
-        RandomLongsSpliterator(AbstractSharedRNG generatingRNG, long index, long fence, long origin, long bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            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 generatingRNG is used, with no splitting or copying.
-            return new RandomLongsSpliterator(generatingRNG, 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(RNGSupport.boundedNextLong(generatingRNG, 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;
-                RandomNumberGenerator r = generatingRNG;
-                long o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextLong(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    static class RandomDoublesSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfDouble {
-        final AbstractSharedRNG generatingRNG;
-        final double origin;
-        final double bound;
-
-        RandomDoublesSpliterator(AbstractSharedRNG generatingRNG, long index, long fence, double origin, double bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            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 generatingRNG is used, with no splitting or copying.
-            return new RandomDoublesSpliterator(generatingRNG, 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(RNGSupport.boundedNextDouble(generatingRNG, 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;
-                RandomNumberGenerator r = generatingRNG;
-                double o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextDouble(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-}
--- a/src/java.base/share/classes/java/util/random/AbstractSpliteratorRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oraclea 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.Spliterator;
-import java.util.stream.Stream;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-import java.util.stream.StreamSupport;
-
-/**
- * This class overrides the stream-producing methods (such as {@code ints()})
- * in class {@link AbstractRNG} to provide {@link Spliterator}-based
- * implmentations that support potentially parallel execution.
- *
- * To implement a pseudorandom number generator, the programmer needs
- * only to extend this class and provide implementations for the methods
- * {@code nextInt()}, {@code nextLong()}, {@code makeIntsSpliterator},
- * {@code makeLongsSpliterator}, and {@code makeDoublesSpliterator}.
- *
- * This class is not public; it provides shared code to the public
- * classes {@link AbstractSplittableRNG}, {@link AbstractSharedRNG},
- * and {@link AbstractArbitrarilyJumpableRNG}.
- *
- * @since 14
- */
-
-abstract class AbstractSpliteratorRNG implements RandomNumberGenerator {
-    /*
-     * Implementation Overview.
-     *
-     * This class provides most of the "user API" methods needed to
-     * satisfy the interface RandomNumberGenerator.  An implementation of this
-     * interface need only extend this class and provide implementations
-     * of six methods: nextInt, nextLong, and nextDouble (the versions
-     * that take no arguments) and makeIntsSpliterator,
-     * makeLongsSpliterator, and makeDoublesSpliterator.
-     *
-     * File organization: First the non-public abstract methods needed
-     * to create spliterators, then the main public methods.
-     */
-
-    abstract Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound);
-    abstract Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound);
-    abstract Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound);
-
-    /* ---------------- public methods ---------------- */
-
-    // stream methods, coded in a way intended to better isolate for
-    // maintenance purposes the small differences across forms.
-
-    private static IntStream intStream(Spliterator.OfInt srng) {
-        return StreamSupport.intStream(srng, false);
-    }
-
-    private static LongStream longStream(Spliterator.OfLong srng) {
-        return StreamSupport.longStream(srng, false);
-    }
-
-    private static DoubleStream doubleStream(Spliterator.OfDouble srng) {
-        return StreamSupport.doubleStream(srng, false);
-    }
-
-    /**
-     * 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) {
-        RNGSupport.checkStreamSize(streamSize);
-        return intStream(makeIntsSpliterator(0L, streamSize, Integer.MAX_VALUE, 0));
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandomly chosen
-     * {@code int} values.
-     *
-     * @implNote The implementation of this method is effectively
-     * equivalent to {@code ints(Long.MAX_VALUE)}.
-     *
-     * @return a stream of pseudorandomly chosen {@code int} values
-     */
-
-    public IntStream ints() {
-        return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0));
-    }
-
-    /**
-     * 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) {
-        RNGSupport.checkStreamSize(streamSize);
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return intStream(makeIntsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
-    }
-
-    /**
-     * 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).
-     *
-     * @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}
-     *
-     * @implNote This method is implemented to be equivalent to {@code ints(Long.MAX_VALUE,
-     *         randomNumberOrigin, randomNumberBound)}.
-     */
-    public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound));
-    }
-
-    /**
-     * 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) {
-        RNGSupport.checkStreamSize(streamSize);
-        return longStream(makeLongsSpliterator(0L, streamSize, Long.MAX_VALUE, 0L));
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandom {@code long} values from this
-     * generator and/or one split from it.
-     *
-     * @return a stream of pseudorandom {@code long} values
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     *         longs(Long.MAX_VALUE)}.
-     */
-    public LongStream longs() {
-        return longStream(makeLongsSpliterator(0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L));
-    }
-
-    /**
-     * 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) {
-        RNGSupport.checkStreamSize(streamSize);
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return longStream(makeLongsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
-    }
-
-    /**
-     * 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).
-     *
-     * @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}
-     *
-     * @implNote This method is implemented to be equivalent to {@code longs(Long.MAX_VALUE,
-     *         randomNumberOrigin, randomNumberBound)}.
-     */
-    public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return StreamSupport.longStream
-            (makeLongsSpliterator(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) {
-        RNGSupport.checkStreamSize(streamSize);
-        return doubleStream(makeDoublesSpliterator(0L, streamSize, Double.MAX_VALUE, 0.0));
-    }
-
-    /**
-     * 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).
-     *
-     * @return a stream of pseudorandom {@code double} values
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     *         doubles(Long.MAX_VALUE)}.
-     */
-    public DoubleStream doubles() {
-        return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0));
-    }
-
-    /**
-     * 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
-     * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to
-     *                                  {@code randomNumberBound}
-     */
-    public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
-        RNGSupport.checkStreamSize(streamSize);
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return doubleStream(makeDoublesSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
-    }
-
-    /**
-     * 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).
-     *
-     * @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}
-     *
-     * @implNote This method is implemented to be equivalent to {@code
-     *         doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     */
-    public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound));
-    }
-
-}
--- a/src/java.base/share/classes/java/util/random/AbstractSplittableRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.Spliterator;
-import java.util.function.Consumer;
-import java.util.function.DoubleConsumer;
-import java.util.function.IntConsumer;
-import java.util.function.LongConsumer;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-/**
- * This class provides much of the implementation of the {@link SplittableRNG} interface, to
- * minimize the effort required to implement this interface.
- * <p>
- * To implement a pseudorandom number generator, the programmer needs only to extend this class and
- * provide implementations for the methods {@code nextInt()}, {@code nextLong()}, {@code period()},
- * and {@code split(SplittableRNG)}.
- * <p>
- * (If the pseudorandom number generator also has the ability to jump, then the programmer may wish
- * to consider instead extending the class {@link ArbitrarilyJumpableRNG}.  But if the pseudorandom
- * number generator furthermore has the ability to jump an arbitrary specified distance, then the
- * programmer may wish to consider instead extending the class {@link
- * AbstractArbitrarilyJumpableRNG}.)
- * <p>
- * The programmer should generally provide at least three constructors: one that takes no arguments,
- * one that accepts a {@code long} seed value, and one that accepts an array of seed {@code byte}
- * values. This class provides a public {@code initialSeed()} method that may be useful in
- * initializing some static state from which to derive defaults seeds for use by the no-argument
- * constructor.
- * <p>
- * For the stream methods (such as {@code ints()} and {@code splits()}), this class provides {@link
- * Spliterator} based implementations that allow parallel execution when appropriate.
- * <p>
- * The documentation for each non-abstract method in this class describes its implementation in
- * detail. Each of these methods may be overridden if the pseudorandom number generator being
- * implemented admits a more efficient implementation.
- *
- * @since 14
- */
-public abstract class AbstractSplittableRNG extends AbstractSpliteratorRNG implements SplittableRNG {
-
-    /*
-     * Implementation Overview.
-     *
-     * This class provides most of the "user API" methods needed to
-     * satisfy the interface JumpableRNG.  Most of these methods
-     * are in turn inherited from AbstractRNG and the non-public class
-     * AbstractSpliteratorRNG; this file implements two versions of the
-     * splits method and defines the spliterators necessary to support
-     * them.
-     *
-     * The abstract split() method from interface SplittableRNG is redeclared
-     * here so as to narrow the return type to AbstractSplittableRNG.
-     *
-     * File organization: First the non-public methods needed by the class
-     * AbstractSpliteratorRNG, then the main public methods, followed by some
-     * custom spliterator classes.
-     */
-
-    Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
-        return new RandomIntsSpliterator(this, index, fence, origin, bound);
-    }
-
-    Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) {
-        return new RandomLongsSpliterator(this, index, fence, origin, bound);
-    }
-
-    Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) {
-        return new RandomDoublesSpliterator(this, index, fence, origin, bound);
-    }
-
-    Spliterator<SplittableRNG> makeSplitsSpliterator(long index, long fence, SplittableRNG source) {
-        return new RandomSplitsSpliterator(source, index, fence, this);
-    }
-
-    /* ---------------- public methods ---------------- */
-
-    /**
-     * Implements the @code{split()} method as {@code this.split(this) }.
-     *
-     * @return the new {@link AbstractSplittableRNG} instance
-     */
-    public SplittableRNG split() {
-        return this.split(this);
-    }
-
-    // Stream methods for splittings
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link SplittableRNG} interface.
-     * <p>
-     * This pseudorandom number generator provides the entropy used to seed the new ones.
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     *
-     * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}.
-     */
-    public Stream<SplittableRNG> splits() {
-        return this.splits(Long.MAX_VALUE, this);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link SplittableRNG} interface.
-     * <p>
-     * This pseudorandom number generator provides the entropy used to seed the new ones.
-     *
-     * @param streamSize the number of values to generate
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     */
-    public Stream<SplittableRNG> splits(long streamSize) {
-        return this.splits(streamSize, this);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link SplittableRNG} interface.
-     *
-     * @param source a {@link SplittableRNG} instance to be used instead of this one as a source of
-     *               pseudorandom bits used to initialize the state of the new ones.
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     *
-     * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}.
-     */
-    public Stream<SplittableRNG> splits(SplittableRNG source) {
-        return this.splits(Long.MAX_VALUE, source);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link SplittableRNG} interface.
-     *
-     * @param streamSize the number of values to generate
-     * @param source     a {@link SplittableRNG} instance to be used instead of this one as a source
-     *                   of pseudorandom bits used to initialize the state of the new ones.
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     */
-    public Stream<SplittableRNG> splits(long streamSize, SplittableRNG source) {
-        RNGSupport.checkStreamSize(streamSize);
-        return StreamSupport.stream(makeSplitsSpliterator(0L, streamSize, source), 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
-     * {@code 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 class RandomIntsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfInt {
-        final SplittableRNG generatingRNG;
-        final int origin;
-        final int bound;
-
-        RandomIntsSpliterator(SplittableRNG generatingRNG, long index, long fence, int origin, int bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public Spliterator.OfInt trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            if (m <= i) return null;
-            index = m;
-            return new RandomIntsSpliterator(generatingRNG.split(), 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(RNGSupport.boundedNextInt(generatingRNG, 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;
-                RandomNumberGenerator r = generatingRNG;
-                int o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextInt(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for long streams.
-     */
-    static class RandomLongsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfLong {
-        final SplittableRNG generatingRNG;
-        final long origin;
-        final long bound;
-
-        RandomLongsSpliterator(SplittableRNG generatingRNG, long index, long fence, long origin, long bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public Spliterator.OfLong trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            if (m <= i) return null;
-            index = m;
-            return new RandomLongsSpliterator(generatingRNG.split(), 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(RNGSupport.boundedNextLong(generatingRNG, 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;
-                RandomNumberGenerator r = generatingRNG;
-                long o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextLong(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for double streams.
-     */
-    static class RandomDoublesSpliterator extends RNGSupport.RandomSpliterator implements Spliterator.OfDouble {
-        final SplittableRNG generatingRNG;
-        final double origin;
-        final double bound;
-
-        RandomDoublesSpliterator(SplittableRNG generatingRNG, long index, long fence, double origin, double bound) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            this.origin = origin; this.bound = bound;
-        }
-
-        public Spliterator.OfDouble trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            if (m <= i) return null;
-            index = m;
-            return new RandomDoublesSpliterator(generatingRNG.split(), 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(RNGSupport.boundedNextDouble(generatingRNG, 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;
-                RandomNumberGenerator r = generatingRNG;
-                double o = origin, b = bound;
-                do {
-                    consumer.accept(RNGSupport.boundedNextDouble(r, o, b));
-                } while (++i < f);
-            }
-        }
-    }
-
-    /**
-     * Spliterator for stream of generators of type SplittableRNG.  We multiplex the two
-     * versions into one class by treating "infinite" as equivalent to Long.MAX_VALUE.
-     * For splits, it uses the standard divide-by-two approach.
-     */
-    static class RandomSplitsSpliterator extends RNGSupport.RandomSpliterator implements Spliterator<SplittableRNG> {
-        final SplittableRNG generatingRNG;
-        final SplittableRNG constructingRNG;
-
-        RandomSplitsSpliterator(SplittableRNG generatingRNG, long index, long fence, SplittableRNG constructingRNG) {
-            super(index, fence);
-            this.generatingRNG = generatingRNG;
-            this.constructingRNG = constructingRNG;
-        }
-
-        public Spliterator<SplittableRNG> trySplit() {
-            long i = index, m = (i + fence) >>> 1;
-            if (m <= i) return null;
-            index = m;
-            return new RandomSplitsSpliterator(generatingRNG.split(), i, m, constructingRNG);
-        }
-
-        public boolean tryAdvance(Consumer<? super SplittableRNG> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                consumer.accept(constructingRNG.split(generatingRNG));
-                index = i + 1;
-                return true;
-            }
-            else return false;
-        }
-
-        public void forEachRemaining(Consumer<? super SplittableRNG> consumer) {
-            if (consumer == null) throw new NullPointerException();
-            long i = index, f = fence;
-            if (i < f) {
-                index = f;
-                SplittableRNG c = constructingRNG;
-                SplittableRNG r = generatingRNG;
-                do {
-                    consumer.accept(c.split(r));
-                } while (++i < f);
-            }
-        }
-    }
-
-}
--- a/src/java.base/share/classes/java/util/random/ArbitrarilyJumpableRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2012, 2018, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.stream.Stream;
-
-/**
- * This interface is designed to provide a common protocol for objects that generate sequences of
- * pseudorandom numbers (or Boolean values) and furthermore can easily <i>jump</i> to an arbitrarily
- * specified distant point in the state cycle.
- * <p>
- * Ideally, all {@link ArbitrarilyJumpableRNG} objects produced by iterative jumping from a single
- * original {@link ArbitrarilyJumpableRNG} object are statistically independent of one another and
- * individually uniform, provided that they do not traverse overlapping portions of the state cycle.
- *  In practice, one must settle for some approximation to independence and uniformity.  In
- * particular, a specific implementation may assume that each generator in a stream produced by the
- * {@code jumps} method is used to produce a number of values no larger than the jump distance
- * specified.  Implementors are advised to use algorithms whose period is at least 2<sup>127</sup>.
- * <p>
- * For many applications, it suffices to jump forward by a power of two or some small multiple of a
- * power of two, but this power of two may not be representable as a {@code long} value.  To avoid
- * the use of {@link java.math.BigInteger} values as jump distances, {@code double} values are used
- * instead.
- * <p>
- * Methods are provided to perform a single jump operation and also to produce a stream of
- * generators produced from the original by iterative copying and jumping of internal state.  A
- * typical strategy for a multithreaded application is to create a single {@link
- * ArbitrarilyJumpableRNG} object, call its {@code jumps} method exactly once, and then parcel out
- * generators from the resulting stream, one to each thread.  However, each generator produced also
- * has type {@link ArbitrarilyJumpableRNG}; with care, different jump distances can be used to
- * traverse the entire state cycle in various ways.
- * <p>
- * An implementation of the {@link ArbitrarilyJumpableRNG} interface must provide concrete
- * definitions for the methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code
- * copy()}, {@code jump(double)}, {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
- * Default implementations are provided for all other methods. Perhaps the most convenient way to
- * implement this interface is to extend the abstract class {@link ArbitrarilyJumpableRNG}, which
- * provides spliterator-based implementations of the methods {@code ints}, {@code longs}, {@code
- * doubles}, {@code rngs}, {@code jumps}, and {@code leaps}.
- * <p>
- * Objects that implement {@link ArbitrarilyJumpableRNG} are typically not cryptographically secure.
- * Consider instead using {@link java.security.SecureRandom} to get a cryptographically secure
- * pseudo-random number generator for use by security-sensitive applications.
- *
- * @since 14
- */
-public interface ArbitrarilyJumpableRNG extends LeapableRNG {
-    /**
-     * Returns a new generator whose internal state is an exact copy of this generator (therefore
-     * their future behavior should be identical if subjected to the same series of operations).
-     *
-     * @return a new object that is a copy of this generator
-     */
-    ArbitrarilyJumpableRNG copy();
-
-    /**
-     * Alter the state of this pseudorandom number generator so as to jump forward a distance equal
-     * to 2<sup>{@code logDistance}</sup> within its state cycle.
-     *
-     * @param logDistance the base-2 logarithm of the distance to jump forward within the state
-     *                    cycle
-     *
-     * @throws IllegalArgumentException if {@code logDistance} is NaN or negative, or if
-     *                                  2<sup>{@code logDistance}</sup> is greater than the period
-     *                                  of this generator
-     */
-    void jumpPowerOfTwo(int logDistance);
-
-    /**
-     * Alter the state of this pseudorandom number generator so as to jump forward a specified
-     * distance within its state cycle.
-     *
-     * @param distance the distance to jump forward within the state cycle
-     *
-     * @throws IllegalArgumentException if {@code distance} is Nan, negative, or greater than the
-     *                                  period of this generator
-     */
-    void jump(double distance);
-
-    /**
-     * Alter the state of this pseudorandom number generator so as to jump forward a large, fixed
-     * distance (typically 2<sup>64</sup> or more) within its state cycle.  The distance used is
-     * that returned by method {@code defaultJumpDistance()}.
-     */
-    default void jump() { jump(defaultJumpDistance()); }
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link ArbitrarilyJumpableRNG} interface, produced by jumping copies of this
-     * generator by different integer multiples of the specified jump distance.
-     *
-     * @param distance a distance to jump forward within the state cycle
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @implNote This method is implemented to be equivalent to {@code jumps(Long.MAX_VALUE)}.
-     */
-    default Stream<ArbitrarilyJumpableRNG> jumps(double distance) {
-        return Stream.generate(() -> copyAndJump(distance)).sequential();
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link ArbitrarilyJumpableRNG} interface, produced
-     * by jumping copies of this generator by different integer multiples of the specified jump
-     * distance.
-     *
-     * @param streamSize the number of generators to generate
-     * @param distance   a distance to jump forward within the state cycle
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     */
-    default Stream<ArbitrarilyJumpableRNG> jumps(long streamSize, double distance) {
-        return jumps(distance).limit(streamSize);
-    }
-
-    /**
-     * Alter the state of this pseudorandom number generator so as to jump forward a very large,
-     * fixed distance (typically 2<sup>128</sup> or more) within its state cycle.  The distance used
-     * is that returned by method {@code defaultJLeapDistance()}.
-     */
-    default void leap() { jump(defaultLeapDistance()); }
-
-    /**
-     * Copy this generator, jump this generator forward, then return the copy.
-     *
-     * @param distance a distance to jump forward within the state cycle
-     *
-     * @return a copy of this generator object before the jump occurred
-     */
-    default ArbitrarilyJumpableRNG copyAndJump(double distance) {
-        ArbitrarilyJumpableRNG result = copy();
-        jump(distance);
-        return result;
-    }
-
-}
--- a/src/java.base/share/classes/java/util/random/JumpableRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.stream.Stream;
-
-/**
- * This interface is designed to provide a common protocol for objects that generate pseudorandom
- * sequences of numbers (or Boolean values) and furthermore can easily <i>jump</i> forward (by a
- * fixed amount) to a distant point in the state cycle.
- * <p>
- * Ideally, all {@link JumpableRNG} objects produced by iterative jumping from a single original
- * {@link JumpableRNG} object are statistically independent of one another and individually uniform.
- * In practice, one must settle for some approximation to independence and uniformity.  In
- * particular, a specific implementation may assume that each generator in a stream produced by the
- * {@code jumps} method is used to produce a number of values no larger than either 2<sup>64</sup>
- * or the square root of its period.  Implementors are advised to use algorithms whose period is at
- * least 2<sup>127</sup>.
- * <p>
- * Methods are provided to perform a single jump operation and also to produce a stream of
- * generators produced from the original by iterative copying and jumping of internal state.  A
- * typical strategy for a multithreaded application is to create a single {@link JumpableRNG}
- * object, calls its {@code jumps} method exactly once, and then parcel out generators from the
- * resulting stream, one to each thread.  It is generally not a good idea to call {@code jump} on a
- * generator that was itself produced by the {@code jumps} method, because the result may be a
- * generator identical to another generator already produce by that call to the {@code jumps}
- * method. For this reason, the return type of the {@code jumps} method is {@code
- * Stream<RandomNumberGenerator>} rather than {@code Stream<JumpableRNG>}, even though the actual
- * generator objects in that stream likely do also implement the {@link JumpableRNG} interface.
- * <p>
- * An implementation of the {@link JumpableRNG} interface must provide concrete definitions for the
- * methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code copy()}, {@code jump()},
- * and {@code defaultJumpDistance()}. Default implementations are provided for all other methods.
- * <p>
- * Objects that implement {@link JumpableRNG} are typically not cryptographically secure.  Consider
- * instead using {@link java.security.SecureRandom} to get a cryptographically secure pseudo-random
- * number generator for use by security-sensitive applications.
- *
- * @since 14
- */
-public interface JumpableRNG extends StreamableRNG {
-    /**
-     * Returns a new generator whose internal state is an exact copy of this generator (therefore
-     * their future behavior should be identical if subjected to the same series of operations).
-     *
-     * @return a new object that is a copy of this generator
-     */
-    JumpableRNG copy();
-
-    /**
-     * Alter the state of this pseudorandom number generator so as to jump forward a large, fixed
-     * distance (typically 2<sup>64</sup> or more) within its state cycle.
-     */
-    void jump();
-
-    /**
-     * Returns the distance by which the {@code jump()} method will jump forward within the state
-     * cycle of this generator object.
-     *
-     * @return the default jump distance (as a {@code double} value)
-     */
-    double defaultJumpDistance();
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link RandomNumberGenerator} interface.
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @implNote It is permitted to implement this method in a manner equivalent to
-     *         {@code jumps(Long.MAX_VALUE)}.
-     * @implNote The default implementation produces a sequential stream that  repeatedly
-     *         calls {@code copy()} and {@code jump()} on this generator, and the copies become the
-     *         generators produced by the stream.
-     */
-    default Stream<RandomNumberGenerator> jumps() {
-        return Stream.generate(this::copyAndJump).sequential();
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link RandomNumberGenerator} interface.
-     *
-     * @param streamSize the number of generators to generate
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     * @implNote The default implementation produces a sequential stream that  repeatedly
-     *         calls {@code copy()} and {@code jump()} on this generator, and the copies become the
-     *         generators produced by the stream.
-     */
-    default Stream<RandomNumberGenerator> jumps(long streamSize) {
-        return jumps().limit(streamSize);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link RandomNumberGenerator} interface.  Ideally the generators in the stream
-     * will appear to be statistically independent.
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @implNote The default implementation calls {@code jumps()}.
-     */
-    default Stream<RandomNumberGenerator> rngs() {
-        return this.jumps();
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link RandomNumberGenerator} interface.  Ideally
-     * the generators in the stream will appear to be statistically independent.
-     *
-     * @param streamSize the number of generators to generate
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     * @implNote The default implementation calls {@code jumps(streamSize)}.
-     */
-    default Stream<RandomNumberGenerator> rngs(long streamSize) {
-        return this.jumps(streamSize);
-    }
-
-    /**
-     * Copy this generator, jump this generator forward, then return the copy.
-     *
-     * @return a copy of this generator object before the jump occurred
-     */
-    default RandomNumberGenerator copyAndJump() {
-        RandomNumberGenerator result = copy();
-        jump();
-        return result;
-    }
-
-}
--- a/src/java.base/share/classes/java/util/random/L128X256MixRandom.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L128X256MixRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,15 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
+
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L128X256MixRandom} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L128X256MixRandom} objects,
@@ -143,7 +146,7 @@
  *
  * @since 14
  */
-public final class L128X256MixRandom extends AbstractSplittableRNG {
+public final class L128X256MixRandom extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -181,7 +184,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**256 - 1) * 2**128.
@@ -250,10 +253,10 @@
         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
         if ((x0 | x1 | x2 | x3) == 0) {
             // At least three of the four values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(sh += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = RNGSupport.mixStafford13(sh += RNGSupport.GOLDEN_RATIO_64);
-            this.x2 = RNGSupport.mixStafford13(sh += RNGSupport.GOLDEN_RATIO_64);
-            this.x3 = RNGSupport.mixStafford13(sh + RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(sh += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = RandomSupport.mixStafford13(sh += RandomSupport.GOLDEN_RATIO_64);
+            this.x2 = RandomSupport.mixStafford13(sh += RandomSupport.GOLDEN_RATIO_64);
+            this.x3 = RandomSupport.mixStafford13(sh + RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -275,14 +278,14 @@
         // which will then be used to produce the first generated value.
         // The other x values are filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
-             RNGSupport.mixMurmur64(seed += RNGSupport.GOLDEN_RATIO_64),
+        this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+             RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64),
              0,
              1,
-             RNGSupport.mixStafford13(seed),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+             RandomSupport.mixStafford13(seed),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -293,7 +296,7 @@
      */
     public L128X256MixRandom() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -305,7 +308,7 @@
      */
     public L128X256MixRandom(byte[] seed) {
         // Convert the seed to 6 long values, of which the last 4 are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 6, 4);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4);
         long ah = data[0], al = data[1], sh = data[2], sl = data[3], x0 = data[4], x1 = data[5], x2 = data[6], x3 = data[7];
         // Force a to be odd.
         this.ah = ah;
@@ -331,12 +334,12 @@
      * and the same expected statistical properties apply to the
      * entire set of generators constructed by such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead
+     * @param source a {@link SplittableGenerator} instance to be used instead
      *               of this one as a source of pseudorandom bits used to
      *               initialize the state of the new ones.
      * @return a new instance of {@link L128X256MixRandom}
      */
-    public L128X256MixRandom split(SplittableRNG source) {
+    public L128X256MixRandom split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L128X256MixRandom(source.nextLong(), source.nextLong(),
                                      source.nextLong(), source.nextLong(),
@@ -359,7 +362,7 @@
         long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
         { long t = q1 << 17; q2 ^= q0; q3 ^= q1; q1 ^= q2; q0 ^= q3; q2 ^= t; q3 = Long.rotateLeft(q3, 45); }  // xoshiro256 1.0
         x0 = q0; x1 = q1; x2 = q2; x3 = q3;
-        return RNGSupport.mixLea64(z);  // mixing function
+        return RandomSupport.mixLea64(z);  // mixing function
     }
 
     public BigInteger period() {
--- a/src/java.base/share/classes/java/util/random/L32X64MixRandom.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L32X64MixRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L32X64MixRandom} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L32X64MixRandom} objects,
@@ -134,7 +136,7 @@
  *
   * @since 14
  */
-public final class L32X64MixRandom extends AbstractSplittableRNG {
+public final class L32X64MixRandom extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -168,7 +170,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**64 - 1) * 2**32.
@@ -219,8 +221,8 @@
         // If x0 and x1 are both zero, we must choose nonzero values.
         if ((x0 | x1) == 0) {
             // At least one of the two values generated here will be nonzero.
-            this.x0 = RNGSupport.mixMurmur32(s += RNGSupport.GOLDEN_RATIO_32);
-            this.x1 = RNGSupport.mixMurmur32(s + RNGSupport.GOLDEN_RATIO_32);
+            this.x0 = RandomSupport.mixMurmur32(s += RandomSupport.GOLDEN_RATIO_32);
+            this.x1 = RandomSupport.mixMurmur32(s + RandomSupport.GOLDEN_RATIO_32);
         }
     }
 
@@ -242,10 +244,10 @@
         // which will then be used to produce the first generated value.
         // Then x1 is filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_32 as the gamma value and Murmur32 as the mixer.
-        this(RNGSupport.mixMurmur32((int)((seed ^= RNGSupport.SILVER_RATIO_64) >>> 32)),
+        this(RandomSupport.mixMurmur32((int)((seed ^= RandomSupport.SILVER_RATIO_64) >>> 32)),
              1,
-             RNGSupport.mixLea32((int)(seed)),
-             RNGSupport.mixLea32((int)(seed) + RNGSupport.GOLDEN_RATIO_32));
+             RandomSupport.mixLea32((int)(seed)),
+             RandomSupport.mixLea32((int)(seed) + RandomSupport.GOLDEN_RATIO_32));
     }
 
     /**
@@ -256,7 +258,7 @@
      */
     public L32X64MixRandom() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -268,7 +270,7 @@
      */
     public L32X64MixRandom(byte[] seed) {
         // Convert the seed to 4 int values, of which the last 2 are not all zero.
-        int[] data = RNGSupport.convertSeedBytesToInts(seed, 4, 2);
+        int[] data = RandomSupport.convertSeedBytesToInts(seed, 4, 2);
         int a = data[0], s = data[1], x0 = data[2], x1 = data[3];
         // Force a to be odd.
         this.a = a | 1;
@@ -288,12 +290,12 @@
      * the same expected statistical properties apply to the entire set of generators constructed by
      * such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead of this one as a source of
+     * @param source a {@link SplittableGenerator} instance to be used instead of this one as a source of
      *               pseudorandom bits used to initialize the state of the new ones.
      *
      * @return a new instance of {@link L32X64MixRandom}
      */
-    public L32X64MixRandom split(SplittableRNG source) {
+    public L32X64MixRandom split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L32X64MixRandom(source.nextInt(), source.nextInt(),
                                    source.nextInt(), source.nextInt());
--- a/src/java.base/share/classes/java/util/random/L64X1024MixRandom.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L64X1024MixRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L64X1024MixRandom} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L64X1024MixRandom} objects,
@@ -134,7 +136,7 @@
  *
  * @since 14
  */
-public final class L64X1024MixRandom extends AbstractSplittableRNG {
+public final class L64X1024MixRandom extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -174,7 +176,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**1024 - 1) * 2**64.
@@ -264,7 +266,7 @@
         if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) {
             // At least fifteen of the sixteen values generated here will be nonzero.
             for (int j = 0; j < N; j++) {
-                this.x[j] = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
+                this.x[j] = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
             }
         }
     }
@@ -287,24 +289,24 @@
         // which will then be used to produce the first generated value.
         // The other x values are filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
+        this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
              1,
-             RNGSupport.mixStafford13(seed),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+             RandomSupport.mixStafford13(seed),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -315,7 +317,7 @@
      */
     public L64X1024MixRandom() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -327,7 +329,7 @@
      */
     public L64X1024MixRandom(byte[] seed) {
         // Convert the seed to 18 long values, of which the last 16 are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 18, 16);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 18, 16);
         long a = data[0], s = data[1];
         // Force a to be odd.
         this.a = a | 1;
@@ -351,12 +353,12 @@
      * and the same expected statistical properties apply to the
      * entire set of generators constructed by such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead
+     * @param source a {@link SplittableGenerator} instance to be used instead
      *               of this one as a source of pseudorandom bits used to
      *               initialize the state of the new ones.
      * @return a new instance of {@link L64X1024MixRandom}
      */
-    public L64X1024MixRandom split(SplittableRNG source) {
+    public L64X1024MixRandom split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L64X1024MixRandom(source.nextLong(), source.nextLong(),
                                      source.nextLong(), source.nextLong(),
@@ -388,7 +390,7 @@
         x[q] = Long.rotateLeft(s0, 25) ^ s15 ^ (s15 << 27);
         x[p] = Long.rotateLeft(s15, 36);
 
-        return RNGSupport.mixLea64(z);  // mixing function
+        return RandomSupport.mixLea64(z);  // mixing function
     }
 
     public BigInteger period() {
--- a/src/java.base/share/classes/java/util/random/L64X1024Random.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L64X1024Random.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L64X1024Random} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L64X1024Random} objects,
@@ -132,7 +134,7 @@
  *
  * @since 14
  */
-public final class L64X1024Random extends AbstractSplittableRNG {
+public final class L64X1024Random extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -172,7 +174,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**1024 - 1) * 2**64.
@@ -261,7 +263,7 @@
         // If x0, x1, ..., x15 are all zero (very unlikely), we must choose nonzero values.
         if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) {
             for (int j = 0; j < N; j++) {
-                this.x[j] = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
+                this.x[j] = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
             }
         }
     }
@@ -284,24 +286,24 @@
         // which will then be used to produce the first generated value.
         // The other x values are filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
+        this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
              1,
-             RNGSupport.mixStafford13(seed),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+             RandomSupport.mixStafford13(seed),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -312,7 +314,7 @@
      */
     public L64X1024Random() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -324,7 +326,7 @@
      */
     public L64X1024Random(byte[] seed) {
         // Convert the seed to 18 long values, of which the last 16 are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 18, 16);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 18, 16);
         long a = data[0], s = data[1];
         // Force a to be odd.
         this.a = a | 1;
@@ -348,12 +350,12 @@
      * and the same expected statistical properties apply to the
      * entire set of generators constructed by such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead
+     * @param source a {@link SplittableGenerator} instance to be used instead
      *               of this one as a source of pseudorandom bits used to
      *               initialize the state of the new ones.
      * @return a new instance of {@link L64X1024Random}
      */
-    public L64X1024Random split(SplittableRNG source) {
+    public L64X1024Random split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L64X1024Random(source.nextLong(), source.nextLong(),
                                   source.nextLong(), source.nextLong(),
--- a/src/java.base/share/classes/java/util/random/L64X128MixRandom.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L64X128MixRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L64X128MixRandom} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L64X128MixRandom} objects,
@@ -134,7 +136,7 @@
  *
  * @since 14
  */
-public final class L64X128MixRandom extends AbstractSplittableRNG {
+public final class L64X128MixRandom extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -168,7 +170,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**128 - 1) * 2**64.
@@ -221,8 +223,8 @@
         // If x0 and x1 are both zero, we must choose nonzero values.
         if ((x0 | x1) == 0) {
             // At least one of the two values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = RNGSupport.mixStafford13(s + RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = RandomSupport.mixStafford13(s + RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -244,10 +246,10 @@
         // which will then be used to produce the first generated value.
         // Then x1 is filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
+        this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
              1,
-             RNGSupport.mixStafford13(seed),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+             RandomSupport.mixStafford13(seed),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -258,7 +260,7 @@
      */
     public L64X128MixRandom() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -270,7 +272,7 @@
      */
     public L64X128MixRandom(byte[] seed) {
         // Convert the seed to 4 long values, of which the last 2 are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 4, 2);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 4, 2);
         long a = data[0], s = data[1], x0 = data[2], x1 = data[3];
         // Force a to be odd.
         this.a = a | 1;
@@ -292,13 +294,13 @@
      * and the same expected statistical properties apply to the
      * entire set of generators constructed by such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead
+     * @param source a {@link SplittableGenerator} instance to be used instead
      *               of this one as a source of pseudorandom bits used to
      *               initialize the state of the new ones.
      *
      * @return a new instance of {@link L64X128MixRandom}
      */
-    public L64X128MixRandom split(SplittableRNG source) {
+    public L64X128MixRandom split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L64X128MixRandom(source.nextLong(), source.nextLong(),
                                     source.nextLong(), source.nextLong());
--- a/src/java.base/share/classes/java/util/random/L64X128Random.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L64X128Random.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L64X128Random} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L64X128Random} objects,
@@ -132,7 +134,7 @@
  *
  * @since 14
  */
-public final class L64X128Random extends AbstractSplittableRNG {
+public final class L64X128Random extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -166,7 +168,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**128 - 1) * 2**64.
@@ -217,8 +219,8 @@
         // If x0 and x1 are both zero, we must choose nonzero values.
         if ((x0 | x1) == 0) {
             // At least one of the two values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = RNGSupport.mixStafford13(s + RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = RandomSupport.mixStafford13(s + RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -240,10 +242,10 @@
         // which will then be used to produce the first generated value.
         // Then x1 is filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
+        this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
              1,
-             RNGSupport.mixStafford13(seed),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+             RandomSupport.mixStafford13(seed),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -254,7 +256,7 @@
      */
     public L64X128Random() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -266,7 +268,7 @@
      */
     public L64X128Random(byte[] seed) {
         // Convert the seed to 4 long values, of which the last 2 are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 4, 2);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 4, 2);
         long a = data[0], s = data[1], x0 = data[2], x1 = data[3];
         // Force a to be odd.
         this.a = a | 1;
@@ -288,13 +290,13 @@
      * and the same expected statistical properties apply to the
      * entire set of generators constructed by such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead
+     * @param source a {@link SplittableGenerator} instance to be used instead
      *               of this one as a source of pseudorandom bits used to
      *               initialize the state of the new ones.
      *
      * @return a new instance of {@link L64X128Random}
      */
-    public L64X128Random split(SplittableRNG source) {
+    public L64X128Random split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L64X128Random(source.nextLong(), source.nextLong(),
                                  source.nextLong(), source.nextLong());
--- a/src/java.base/share/classes/java/util/random/L64X256MixRandom.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L64X256MixRandom.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L64X256MixRandom} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L64X256MixRandom} objects,
@@ -134,7 +136,7 @@
  *
  * @since 14
  */
-public final class L64X256MixRandom extends AbstractSplittableRNG {
+public final class L64X256MixRandom extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -169,7 +171,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**256 - 1) * 2**64.
@@ -226,10 +228,10 @@
         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
         if ((x0 | x1 | x2 | x3) == 0) {
             // At least three of the four values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x2 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x3 = RNGSupport.mixStafford13(s + RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x2 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x3 = RandomSupport.mixStafford13(s + RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -251,12 +253,12 @@
         // which will then be used to produce the first generated value.
         // The other x values are filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
+        this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
              1,
-             RNGSupport.mixStafford13(seed),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+             RandomSupport.mixStafford13(seed),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -267,7 +269,7 @@
      */
     public L64X256MixRandom() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -279,7 +281,7 @@
      */
     public L64X256MixRandom(byte[] seed) {
         // Convert the seed to 6 long values, of which the last 4 are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 6, 4);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4);
         long a = data[0], s = data[1], x0 = data[2], x1 = data[3], x2 = data[4], x3 = data[5];
         // Force a to be odd.
         this.a = a | 1;
@@ -303,13 +305,13 @@
      * and the same expected statistical properties apply to the
      * entire set of generators constructed by such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead
+     * @param source a {@link SplittableGenerator} instance to be used instead
      *               of this one as a source of pseudorandom bits used to
      *               initialize the state of the new ones.
      *
      * @return a new instance of {@link L64X256MixRandom}
      */
-    public L64X256MixRandom split(SplittableRNG source) {
+    public L64X256MixRandom split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L64X256MixRandom(source.nextLong(), source.nextLong(),
                                     source.nextLong(), source.nextLong(),
@@ -327,7 +329,7 @@
         long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
         { long t = q1 << 17; q2 ^= q0; q3 ^= q1; q1 ^= q2; q0 ^= q3; q2 ^= t; q3 = Long.rotateLeft(q3, 45); }  // xoshiro256 1.0
         x0 = q0; x1 = q1; x2 = q2; x3 = q3;
-        return RNGSupport.mixLea64(z);  // mixing function
+        return RandomSupport.mixLea64(z);  // mixing function
     }
 
     public BigInteger period() {
--- a/src/java.base/share/classes/java/util/random/L64X256Random.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/L64X256Random.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.random.RandomSupport.AbstractSplittableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link L64X256Random} implements
- * interfaces {@link RandomNumberGenerator} and {@link SplittableRNG},
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new split-off {@link L64X256Random} objects,
@@ -132,7 +134,7 @@
  *
  * @since 14
  */
-public final class L64X256Random extends AbstractSplittableRNG {
+public final class L64X256Random extends AbstractSplittableGenerator {
 
     /*
      * Implementation Overview.
@@ -167,7 +169,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is (2**256 - 1) * 2**64.
@@ -224,10 +226,10 @@
         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
         if ((x0 | x1 | x2 | x3) == 0) {
             // At least three of the four values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x2 = RNGSupport.mixStafford13(s += RNGSupport.GOLDEN_RATIO_64);
-            this.x3 = RNGSupport.mixStafford13(s + RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x2 = RandomSupport.mixStafford13(s += RandomSupport.GOLDEN_RATIO_64);
+            this.x3 = RandomSupport.mixStafford13(s + RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -249,12 +251,12 @@
         // which will then be used to produce the first generated value.
         // The other x values are filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixMurmur64(seed ^= RNGSupport.SILVER_RATIO_64),
+        this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
              1,
-             RNGSupport.mixStafford13(seed),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+             RandomSupport.mixStafford13(seed),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -265,7 +267,7 @@
      */
     public L64X256Random() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -277,7 +279,7 @@
      */
     public L64X256Random(byte[] seed) {
         // Convert the seed to 6 long values, of which the last 4 are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 6, 4);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 4);
         long a = data[0], s = data[1], x0 = data[2], x1 = data[3], x2 = data[4], x3 = data[5];
         // Force a to be odd.
         this.a = a | 1;
@@ -301,13 +303,13 @@
      * and the same expected statistical properties apply to the
      * entire set of generators constructed by such recursive splitting.
      *
-     * @param source a {@link SplittableRNG} instance to be used instead
+     * @param source a {@link SplittableGenerator} instance to be used instead
      *               of this one as a source of pseudorandom bits used to
      *               initialize the state of the new ones.
      *
      * @return a new instance of {@link L64X256Random}
      */
-    public L64X256Random split(SplittableRNG source) {
+    public L64X256Random split(SplittableGenerator source) {
         // Literally pick a new instance "at random".
         return new L64X256Random(source.nextLong(), source.nextLong(),
                                  source.nextLong(), source.nextLong(),
--- a/src/java.base/share/classes/java/util/random/LeapableRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.stream.Stream;
-
-/**
- * This interface is designed to provide a common protocol for objects that generate sequences of
- * pseudorandom numbers (or Boolean values) and furthermore can easily not only jump but also
- * <i>leap</i> to a very distant point in the state cycle.
- * <p>
- * Typically one will construct a series of {@link LeapableRNG} objects by iterative leaping from a
- * single original {@link LeapableRNG} object, and then for each such object produce a subseries of
- * objects by iterative jumping.  There is little conceptual difference between leaping and jumping,
- * but typically a leap will be a very long jump in the state cycle (perhaps distance
- * 2<sup>128</sup> or so).
- * <p>
- * Ideally, all {@link LeapableRNG} objects produced by iterative leaping and jumping from a single
- * original {@link LeapableRNG} object are statistically independent of one another and individually
- * uniform. In practice, one must settle for some approximation to independence and uniformity.  In
- * particular, a specific implementation may assume that each generator in a stream produced by the
- * {@code leaps} method is used to produce (by jumping) a number of objects no larger than
- * 2<sup>64</sup>.  Implementors are advised to use algorithms whose period is at least
- * 2<sup>191</sup>.
- * <p>
- * Methods are provided to perform a single leap operation and also to produce a stream of
- * generators produced from the original by iterative copying and leaping of internal state.  The
- * generators produced must implement the {@link JumpableRNG} interface but need not also implement
- * the {@link LeapableRNG} interface.  A typical strategy for a multithreaded application is to
- * create a single {@link LeapableRNG} object, calls its {@code leaps} method exactly once, and then
- * parcel out generators from the resulting stream, one to each thread.  Then the {@code jumps}
- * method of each such generator be called to produce a substream of generator objects.
- * <p>
- * An implementation of the {@link LeapableRNG} interface must provide concrete definitions for the
- * methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code copy()}, {@code jump()},
- * {@code defaultJumpDistance()}, {@code leap()}, and {@code defaultLeapDistance()}. Default
- * implementations are provided for all other methods.
- * <p>
- * Objects that implement {@link LeapableRNG} are typically not cryptographically secure.  Consider
- * instead using {@link java.security.SecureRandom} to get a cryptographically secure pseudo-random
- * number generator for use by security-sensitive applications.
- *
- * @since 14
- */
-public interface LeapableRNG extends JumpableRNG {
-    /**
-     * Returns a new generator whose internal state is an exact copy of this generator (therefore
-     * their future behavior should be identical if subjected to the same series of operations).
-     *
-     * @return a new object that is a copy of this generator
-     */
-    LeapableRNG copy();
-
-    /**
-     * Alter the state of this pseudorandom number generator so as to leap forward a large, fixed
-     * distance (typically 2<sup>96</sup> or more) within its state cycle.
-     */
-    void leap();
-
-    /**
-     * Returns the distance by which the {@code leap()} method will leap forward within the state
-     * cycle of this generator object.
-     *
-     * @return the default leap distance (as a {@code double} value)
-     */
-    double defaultLeapDistance();
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
-     * implements the {@link JumpableRNG} interface.
-     *
-     * @return a stream of objects that implement the {@link JumpableRNG} interface
-     *
-     * @implNote It is permitted to implement this method in a manner equivalent to {@code
-     *         leaps(Long.MAX_VALUE)}.
-     * @implNote The default implementation produces a sequential stream that  repeatedly
-     *         calls {@code copy()} and {@code leap()} on this generator, and the copies become the
-     *         generators produced by the stream.
-     */
-    default Stream<JumpableRNG> leaps() {
-        return Stream.generate(this::copyAndLeap).sequential();
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
-     * generators, each of which implements the {@link JumpableRNG} interface.
-     *
-     * @param streamSize the number of generators to generate
-     *
-     * @return a stream of objects that implement the {@link JumpableRNG} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is less than zero
-     * @implNote The default implementation produces a sequential stream that  repeatedly
-     *         calls {@code copy()} and {@code leap()} on this generator, and the copies become the
-     *         generators produced by the stream.
-     */
-    default Stream<JumpableRNG> leaps(long streamSize) {
-        return leaps().limit(streamSize);
-    }
-
-    /**
-     * Copy this generator, leap this generator forward, then return the copy.
-     *
-     * @return a copy of this generator object before the leap occurred
-     */
-    default JumpableRNG copyAndLeap() {
-        JumpableRNG result = copy();
-        leap();
-        return result;
-    }
-
-}
--- a/src/java.base/share/classes/java/util/random/MRG32k3a.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/MRG32k3a.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,14 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.LeapableGenerator;
+import java.util.random.RandomSupport.AbstractArbitrarilyJumpableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link MRG32k3a} implements
- * interfaces {@link RandomNumberGenerator} and {@link AbstractArbitrarilyJumpableRNG},
+ * interfaces {@link RandomGenerator} and {@link AbstractArbitrarilyJumpableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new {@link Xoroshiro128PlusMRG32k3a} objects
@@ -53,7 +55,7 @@
  *
  * @since 14
  */
-public final class MRG32k3a extends AbstractArbitrarilyJumpableRNG {
+public final class MRG32k3a extends AbstractArbitrarilyJumpableGenerator {
 
     /*
      * Implementation Overview.
@@ -87,7 +89,7 @@
      * The seed generator for default constructors.
      */
     private static final AtomicLong DEFAULT_GEN =
-        new AtomicLong(RNGSupport.initialSeed());
+        new AtomicLong(RandomSupport.initialSeed());
 
     /*
       32-bits Random number generator U(0,1): MRG32k3a
@@ -132,7 +134,7 @@
                     ;
                 return (r + origin);
             } else {
-                return RNGSupport.boundedNextInt(this, origin, bound);
+                return RandomSupport.boundedNextInt(this, origin, bound);
             }
         } else {
             return nextInt();
@@ -219,7 +221,7 @@
      * may, and typically does, vary across program invocations.
      */
     public MRG32k3a() {
-        this(DEFAULT_GEN.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -231,7 +233,7 @@
      */
     public MRG32k3a(byte[] seed) {
         // Convert the seed to 6 int values.
-        int[] data = RNGSupport.convertSeedBytesToInts(seed, 6, 0);
+        int[] data = RandomSupport.convertSeedBytesToInts(seed, 6, 0);
         int s10 = data[0], s11 = data[1], s12 = data[2];
         int s20 = data[3], s21 = data[4], s22 = data[5];
         this.s10 = ((double)(((long)s10) & 0x00000000ffffffffL)) % M1;
--- a/src/java.base/share/classes/java/util/random/RNGSupport.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1085 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.Spliterator;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-
-/**
- * Low-level utility methods helpful for implementing pseudorandom number generators.
- *
- * This class is mostly for library writers creating specific implementations of the
- * interface {@link RandomNumberGenerator}.
- *
- * @since 14
- */
-public class RNGSupport {
-
-    /*
-     * Implementation Overview.
-     *
-     * This class provides utility methods and constants frequently
-     * useful in the implentation of pseudorandom number generators
-     * that satisfy the interface {@link RandomNumberGenerator}.
-     *
-     * File organization: First some message strings, then the main
-     * public methods, followed by a non-public base spliterator class.
-     */
-
-    // IllegalArgumentException messages
-    static final String BAD_SIZE = "size must be non-negative";
-    static final String BAD_DISTANCE = "jump distance must be finite, positive, and an exact integer";
-    static final String BAD_BOUND = "bound must be positive";
-    static final String BAD_FLOATING_BOUND = "bound must be finite and positive";
-    static final String BAD_RANGE = "bound must be greater than origin";
-
-    /* ---------------- public methods ---------------- */
-
-    /**
-     * Check a {@code long} proposed stream size for validity.
-     *
-     * @param streamSize the proposed stream size
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is negative
-     */
-    public static void checkStreamSize(long streamSize) {
-        if (streamSize < 0L)
-            throw new IllegalArgumentException(BAD_SIZE);
-    }
-
-    /**
-     * Check a {@code double} proposed jump distance for validity.
-     *
-     * @param distance the proposed jump distance
-     *
-     * @throws IllegalArgumentException if {@code size} not positive, finite, and an exact integer
-     */
-    public static void checkJumpDistance(double distance) {
-        if (!(distance > 0.0 && distance < Float.POSITIVE_INFINITY
-                             && distance == Math.floor(distance))) {
-            throw new IllegalArgumentException(BAD_DISTANCE);
-        }
-    }
-
-    /**
-     * Checks a {@code float} upper bound value for validity.
-     *
-     * @param bound the upper bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not positive and finite
-     */
-    public static void checkBound(float bound) {
-        if (!(bound > 0.0 && bound < Float.POSITIVE_INFINITY)) {
-            throw new IllegalArgumentException(BAD_FLOATING_BOUND);
-        }
-    }
-
-    /**
-     * Checks a {@code double} upper bound value for validity.
-     *
-     * @param bound the upper bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not positive and finite
-     */
-    public static void checkBound(double bound) {
-        if (!(bound > 0.0 && bound < Double.POSITIVE_INFINITY)) {
-            throw new IllegalArgumentException(BAD_FLOATING_BOUND);
-        }
-    }
-
-    /**
-     * Checks an {@code int} upper bound value for validity.
-     *
-     * @param bound the upper bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public static void checkBound(int bound) {
-        if (bound <= 0) {
-            throw new IllegalArgumentException(BAD_BOUND);
-        }
-    }
-
-    /**
-     * Checks a {@code long} upper bound value for validity.
-     *
-     * @param bound the upper bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     */
-    public static void checkBound(long bound) {
-        if (bound <= 0) {
-            throw new IllegalArgumentException(BAD_BOUND);
-        }
-    }
-
-    /**
-     * Checks a {@code float} range for validity.
-     *
-     * @param origin the least value (inclusive) in the range
-     * @param bound  the upper bound (exclusive) of the range
-     *
-     * @throws IllegalArgumentException unless {@code origin} is finite, {@code bound} is finite,
-     *                                  and {@code bound - origin} is finite
-     */
-    public static void checkRange(float origin, float bound) {
-        if (!(origin < bound && (bound - origin) < Float.POSITIVE_INFINITY)) {
-            throw new IllegalArgumentException(BAD_RANGE);
-        }
-    }
-
-    /**
-     * Checks a {@code double} range for validity.
-     *
-     * @param origin the least value (inclusive) in the range
-     * @param bound  the upper bound (exclusive) of the range
-     *
-     * @throws IllegalArgumentException unless {@code origin} is finite, {@code bound} is finite,
-     *                                  and {@code bound - origin} is finite
-     */
-    public static void checkRange(double origin, double bound) {
-        if (!(origin < bound && (bound - origin) < Double.POSITIVE_INFINITY)) {
-            throw new IllegalArgumentException(BAD_RANGE);
-        }
-    }
-
-    /**
-     * Checks an {@code int} range for validity.
-     *
-     * @param origin the least value that can be returned
-     * @param bound  the upper bound (exclusive) for the returned value
-     *
-     * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound}
-     */
-    public static void checkRange(int origin, int bound) {
-        if (origin >= bound) {
-            throw new IllegalArgumentException(BAD_RANGE);
-        }
-    }
-
-    /**
-     * Checks a {@code long} range for validity.
-     *
-     * @param origin the least value that can be returned
-     * @param bound  the upper bound (exclusive) for the returned value
-     *
-     * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound}
-     */
-    public static void checkRange(long origin, long bound) {
-        if (origin >= bound) {
-            throw new IllegalArgumentException(BAD_RANGE);
-        }
-    }
-
-    /**
-     * Given an array of seed bytes of any length, construct an array
-     * of {@code long} seed values of length {@code n}, such that the
-     * last {@code z} values are not all zero.
-     *
-     * @param seed an array of {@code byte} values
-     * @param n the length of the result array (should be nonnegative)
-     * @param z the number of trailing result elements that are required
-     *        to be not all zero (should be nonnegative but not larger
-     *        than {@code n})
-     *
-     * @return an array of length {@code n} containing {@code long} seed values
-     */
-    public static long[] convertSeedBytesToLongs(byte[] seed, int n, int z) {
-        final long[] result = new long[n];
-        final int m = Math.min(seed.length, n << 3);
-        // Distribute seed bytes into the words to be formed.
-        for (int j = 0; j < m; j++) {
-            result[j>>3] = (result[j>>3] << 8) | seed[j];
-        }
-        // If there aren't enough seed bytes for all the words we need,
-        // use a SplitMix-style PRNG to fill in the rest.
-        long v = result[0];
-        for (int j = (m + 7) >> 3; j < n; j++) {
-            result[j] = mixMurmur64(v += SILVER_RATIO_64);
-        }
-        // Finally, we need to make sure the last z words are not all zero.
-        search: {
-            for (int j = n - z; j < n; j++) {
-                if (result[j] != 0) break search;
-            }
-            // If they are, fill in using a SplitMix-style PRNG.
-            // Using "& ~1L" in the next line defends against the case z==1
-            // by guaranteeing that the first generated value will be nonzero.
-            long w = result[0] & ~1L;
-            for (int j = n - z; j < n; j++) {
-                result[j] = mixMurmur64(w += SILVER_RATIO_64);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Given an array of seed bytes of any length, construct an array
-     * of {@code int} seed values of length {@code n}, such that the
-     * last {@code z} values are not all zero.
-     *
-     * @param seed an array of {@code byte} values
-     * @param n the length of the result array (should be nonnegative)
-     * @param z the number of trailing result elements that are required
-     *        to be not all zero (should be nonnegative but not larger
-     *        than {@code n})
-     *
-     * @return an array of length {@code n} containing {@code int} seed values
-     */
-    public static int[] convertSeedBytesToInts(byte[] seed, int n, int z) {
-        final int[] result = new int[n];
-        final int m = Math.min(seed.length, n << 2);
-        // Distribute seed bytes into the words to be formed.
-        for (int j = 0; j < m; j++) {
-            result[j>>2] = (result[j>>2] << 8) | seed[j];
-        }
-        // If there aren't enough seed bytes for all the words we need,
-        // use a SplitMix-style PRNG to fill in the rest.
-        int v = result[0];
-        for (int j = (m + 3) >> 2; j < n; j++) {
-            result[j] = mixMurmur32(v += SILVER_RATIO_32);
-        }
-        // Finally, we need to make sure the last z words are not all zero.
-        search: {
-            for (int j = n - z; j < n; j++) {
-                if (result[j] != 0) break search;
-            }
-            // If they are, fill in using a SplitMix-style PRNG.
-            // Using "& ~1" in the next line defends against the case z==1
-            // by guaranteeing that the first generated value will be nonzero.
-            int w = result[0] & ~1;
-            for (int j = n - z; j < n; j++) {
-                result[j] = mixMurmur32(w += SILVER_RATIO_32);
-            }
-        }
-        return result;
-    }
-
-    /*
-     * Bounded 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.
-     */
-
-    /**
-     * This is the form of {@code nextLong} used by a {@link LongStream}
-     * {@link Spliterator} and by the public method
-     * {@code nextLong(origin, bound)}.  If {@code origin} is greater
-     * than {@code bound}, then this method simply calls the unbounded
-     * version of {@code nextLong()}, choosing pseudorandomly from
-     * among all 2<sup>64</sup> possible {@code long} values}, and
-     * otherwise uses one or more calls to {@code nextLong()} to
-     * choose a value pseudorandomly from the possible values
-     * between {@code origin} (inclusive) and {@code bound} (exclusive).
-     *
-     * @implNote This method first calls {@code nextLong()} to obtain
-     * a {@code long} value that is assumed to be pseudorandomly
-     * chosen uniformly and independently from the 2<sup>64</sup>
-     * possible {@code long} values (that is, each of the 2<sup>64</sup>
-     * possible long values is equally likely to be chosen).
-     * Under some circumstances (when the specified range is not
-     * a power of 2), {@code nextLong()} may be called additional times
-     * to ensure that that the values in the specified range are
-     * equally likely to be chosen (provided the assumption holds).
-     * <p>
-     * The implementation considers four cases:
-     * <ol>
-     *
-     * <li> If the {@code} bound} is less than or equal to the {@code origin}
-     *      (indicated an unbounded form), the 64-bit {@code long} value
-     *      obtained from {@code nextLong()} is returned directly.
-     *
-     * <li> Otherwise, if the length <i>n</i> of the specified range is an
-     *      exact power of two 2<sup><i>m</i></sup> for some integer
-     *      <i>m</i>, then return the sum of {@code origin} and the
-     *      <i>m</i> lowest-order bits of the value from {@code nextLong()}.
-     *
-     * <li> Otherwise, if the length <i>n</i> of the specified range
-     *      is less than 2<sup>63</sup>, then the basic idea is to use the
-     *      remainder modulo <i>n</i> of the value from {@code nextLong()},
-     *      but with this approach some values will be over-represented.
-     *      Therefore a loop is used to avoid potential bias by rejecting
-     *      candidates that are too large.  Assuming that the results from
-     *      {@code nextLong()} are truly chosen uniformly and independently,
-     *      the expected number of iterations will be somewhere between
-     *      1 and 2, depending on the precise value of <i>n</i>.
-     *
-     * <li> Otherwise, the length <i>n</i> of the specified range
-     *      cannot be represented as a positive {@code long} value.
-     *      A loop repeatedly calls {@code nextlong()} until obtaining
-     *      a suitable candidate,  Again, the expected number of iterations
-     *      is less than 2.
-     *
-     * </ol>
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code long} values
-     * @param origin the least value that can be produced,
-     *        unless greater than or equal to {@code bound}
-     * @param bound the upper bound (exclusive), unless {@code origin}
-     *        is greater than or equal to {@code bound}
-     *
-     * @return a pseudorandomly chosen {@code long} value,
-     *         which will be between {@code origin} (inclusive) and
-     *         {@code bound} exclusive unless {@code origin}
-     *         is greater than or equal to {@code bound}
-     */
-    public static long boundedNextLong(RandomNumberGenerator rng, long origin, long bound) {
-        long r = rng.nextLong();
-        if (origin < bound) {
-            // It's not case (1).
-            final long n = bound - origin;
-            final long m = n - 1;
-            if ((n & m) == 0L) {
-                // It is case (2): length of range is a power of 2.
-                r = (r & m) + origin;
-            } else if (n > 0L) {
-                // It is case (3): need to reject over-represented candidates.
-                /* This loop takes an unlovable form (but it works):
-                   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. */
-                for (long u = r >>> 1;            // ensure nonnegative
-                     u + m - (r = u % n) < 0L;    // rejection check
-                     u = rng.nextLong() >>> 1) // retry
-                    ;
-                r += origin;
-            }
-            else {
-                // It is case (4): length of range not representable as long.
-                while (r < origin || r >= bound)
-                    r = rng.nextLong();
-            }
-        }
-        return r;
-    }
-
-    /**
-     * This is the form of {@code nextLong} used by the public method
-     * {@code nextLong(bound)}.  This is essentially a version of
-     * {@code boundedNextLong(origin, bound)} that has been
-     * specialized for the case where the {@code origin} is zero
-     * and the {@code bound} is greater than zero.  The value
-     * returned is chosen pseudorandomly from nonnegative integer
-     * values less than {@code bound}.
-     *
-     * @implNote This method first calls {@code nextLong()} to obtain
-     * a {@code long} value that is assumed to be pseudorandomly
-     * chosen uniformly and independently from the 2<sup>64</sup>
-     * possible {@code long} values (that is, each of the 2<sup>64</sup>
-     * possible long values is equally likely to be chosen).
-     * Under some circumstances (when the specified range is not
-     * a power of 2), {@code nextLong()} may be called additional times
-     * to ensure that that the values in the specified range are
-     * equally likely to be chosen (provided the assumption holds).
-     * <p>
-     * The implementation considers two cases:
-     * <ol>
-     *
-     * <li> If {@code bound} is an exact power of two 2<sup><i>m</i></sup>
-     *      for some integer <i>m</i>, then return the sum of {@code origin}
-     *      and the <i>m</i> lowest-order bits of the value from
-     *      {@code nextLong()}.
-     *
-     * <li> Otherwise, the basic idea is to use the remainder modulo
-     *      <i>bound</i> of the value from {@code nextLong()},
-     *      but with this approach some values will be over-represented.
-     *      Therefore a loop is used to avoid potential bias by rejecting
-     *      candidates that vare too large.  Assuming that the results from
-     *      {@code nextLong()} are truly chosen uniformly and independently,
-     *      the expected number of iterations will be somewhere between
-     *      1 and 2, depending on the precise value of <i>bound</i>.
-     *
-     * </ol>
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code long} values
-     * @param bound the upper bound (exclusive); must be greater than zero
-     *
-     * @return a pseudorandomly chosen {@code long} value
-     */
-    public static long boundedNextLong(RandomNumberGenerator rng, long bound) {
-        // Specialize boundedNextLong for origin == 0, bound > 0
-        final long m = bound - 1;
-        long r = rng.nextLong();
-        if ((bound & m) == 0L) {
-            // The bound is a power of 2.
-            r &= m;
-        } else {
-            // Must reject over-represented candidates
-            /* This loop takes an unlovable form (but it works):
-               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. */
-            for (long u = r >>> 1;
-                 u + m - (r = u % bound) < 0L;
-                 u = rng.nextLong() >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * This is the form of {@code nextInt} used by an {@link IntStream}
-     * {@link Spliterator} and by the public method
-     * {@code nextInt(origin, bound)}.  If {@code origin} is greater
-     * than {@code bound}, then this method simply calls the unbounded
-     * version of {@code nextInt()}, choosing pseudorandomly from
-     * among all 2<sup>64</sup> possible {@code int} values}, and
-     * otherwise uses one or more calls to {@code nextInt()} to
-     * choose a value pseudorandomly from the possible values
-     * between {@code origin} (inclusive) and {@code bound} (exclusive).
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code int} values
-     * @param origin the least value that can be produced,
-     *        unless greater than or equal to {@code bound}
-     * @param bound the upper bound (exclusive), unless {@code origin}
-     *        is greater than or equal to {@code bound}
-     *
-     * @return a pseudorandomly chosen {@code int} value,
-     *         which will be between {@code origin} (inclusive) and
-     *         {@code bound} exclusive unless {@code origin}
-     *         is greater than or equal to {@code bound}
-     *
-     * @implNote The implementation of this method is identical to
-     *           the implementation of {@code nextLong(origin, bound)}
-     *           except that {@code int} values and the {@code nextInt()}
-     *           method are used rather than {@code long} values and the
-     *           {@code nextLong()} method.
-     */
-    public static int boundedNextInt(RandomNumberGenerator rng, int origin, int bound) {
-        int r = rng.nextInt();
-        if (origin < bound) {
-            // It's not case (1).
-            final int n = bound - origin;
-            final int m = n - 1;
-            if ((n & m) == 0) {
-                // It is case (2): length of range is a power of 2.
-                r = (r & m) + origin;
-            } else if (n > 0) {
-                // It is case (3): need to reject over-represented candidates.
-                for (int u = r >>> 1;
-                     u + m - (r = u % n) < 0;
-                     u = rng.nextInt() >>> 1)
-                    ;
-                r += origin;
-            }
-            else {
-                // It is case (4): length of range not representable as long.
-                while (r < origin || r >= bound) {
-                    r = rng.nextInt();
-                }
-            }
-        }
-        return r;
-    }
-
-    /**
-     * This is the form of {@code nextInt} used by the public method
-     * {@code nextInt(bound)}.  This is essentially a version of
-     * {@code boundedNextInt(origin, bound)} that has been
-     * specialized for the case where the {@code origin} is zero
-     * and the {@code bound} is greater than zero.  The value
-     * returned is chosen pseudorandomly from nonnegative integer
-     * values less than {@code bound}.
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code long} values
-     * @param bound the upper bound (exclusive); must be greater than zero
-     *
-     * @return a pseudorandomly chosen {@code long} value
-     *
-     * @implNote The implementation of this method is identical to
-     *           the implementation of {@code nextLong(bound)}
-     *           except that {@code int} values and the {@code nextInt()}
-     *           method are used rather than {@code long} values and the
-     *           {@code nextLong()} method.
-     */
-    public static int boundedNextInt(RandomNumberGenerator rng, int bound) {
-        // Specialize boundedNextInt for origin == 0, bound > 0
-        final int m = bound - 1;
-        int r = rng.nextInt();
-        if ((bound & m) == 0) {
-            // The bound is a power of 2.
-            r &= m;
-        } else {
-            // Must reject over-represented candidates
-            for (int u = r >>> 1;
-                 u + m - (r = u % bound) < 0;
-                 u = rng.nextInt() >>> 1)
-                ;
-        }
-        return r;
-    }
-
-    /**
-     * This is the form of {@code nextDouble} used by a {@link DoubleStream}
-     * {@link Spliterator} and by the public method
-     * {@code nextDouble(origin, bound)}.  If {@code origin} is greater
-     * than {@code bound}, then this method simply calls the unbounded
-     * version of {@code nextDouble()}, and otherwise scales and translates
-     * the result of a call to {@code nextDouble()} so that it lies
-     * between {@code origin} (inclusive) and {@code bound} (exclusive).
-     *
-     * @implNote The implementation considers two cases:
-     * <ol>
-     *
-     * <li> If the {@code bound} is less than or equal to the {@code origin}
-     *      (indicated an unbounded form), the 64-bit {@code double} value
-     *      obtained from {@code nextDouble()} is returned directly.
-     *
-     * <li> Otherwise, the result of a call to {@code nextDouble} is
-     *      multiplied by {@code (bound - origin)}, then {@code origin}
-     *      is added, and then if this this result is not less than
-     *      {@code bound} (which can sometimes occur because of rounding),
-     *      it is replaced with the largest {@code double} value that
-     *      is less than {@code bound}.
-     *
-     * </ol>
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code double} values
-     * @param origin the least value that can be produced,
-     *        unless greater than or equal to {@code bound}; must be finite
-     * @param bound the upper bound (exclusive), unless {@code origin}
-     *        is greater than or equal to {@code bound}; must be finite
-     * @return a pseudorandomly chosen {@code double} value,
-     *         which will be between {@code origin} (inclusive) and
-     *         {@code bound} exclusive unless {@code origin}
-     *         is greater than or equal to {@code bound},
-     *         in which case it will be between 0.0 (inclusive)
-     *         and 1.0 (exclusive)
-     */
-    public static double boundedNextDouble(RandomNumberGenerator rng, double origin, double bound) {
-        double r = rng.nextDouble();
-        if (origin < bound) {
-            r = r * (bound - origin) + origin;
-            if (r >= bound)  // may need to correct a rounding problem
-                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-        }
-        return r;
-    }
-
-    /**
-     * This is the form of {@code nextDouble} used by the public method
-     * {@code nextDouble(bound)}.  This is essentially a version of
-     * {@code boundedNextDouble(origin, bound)} that has been
-     * specialized for the case where the {@code origin} is zero
-     * and the {@code bound} is greater than zero.
-     *
-     * @implNote The result of a call to {@code nextDouble} is
-     *      multiplied by {@code bound}, and then if this result is
-     *      not less than {@code bound} (which can sometimes occur
-     *      because of rounding), it is replaced with the largest
-     *      {@code double} value that is less than {@code bound}.
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code double} values
-     * @param bound the upper bound (exclusive); must be finite and
-     *        greater than zero
-     * @return a pseudorandomly chosen {@code double} value
-     *         between zero (inclusive) and {@code bound} (exclusive)
-     */
-    public static double boundedNextDouble(RandomNumberGenerator rng, double bound) {
-        // Specialize boundedNextDouble for origin == 0, bound > 0
-        double r = rng.nextDouble();
-        r = r * bound;
-        if (r >= bound)  // may need to correct a rounding problem
-            r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
-        return r;
-    }
-
-    /**
-     * This is the form of {@code nextFloat} used by a {@code Stream<Float>}
-     * {@link Spliterator} (if there were any) and by the public method
-     * {@code nextFloat(origin, bound)}.  If {@code origin} is greater
-     * than {@code bound}, then this method simply calls the unbounded
-     * version of {@code nextFloat()}, and otherwise scales and translates
-     * the result of a call to {@code nextFloat()} so that it lies
-     * between {@code origin} (inclusive) and {@code bound} (exclusive).
-     *
-     * @implNote The implementation of this method is identical to
-     *     the implementation of {@code nextDouble(origin, bound)}
-     *     except that {@code float} values and the {@code nextFloat()}
-     *     method are used rather than {@code double} values and the
-     *     {@code nextDouble()} method.
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code float} values
-     * @param origin the least value that can be produced,
-     *        unless greater than or equal to {@code bound}; must be finite
-     * @param bound the upper bound (exclusive), unless {@code origin}
-     *        is greater than or equal to {@code bound}; must be finite
-     * @return a pseudorandomly chosen {@code float} value,
-     *         which will be between {@code origin} (inclusive) and
-     *         {@code bound} exclusive unless {@code origin}
-     *         is greater than or equal to {@code bound},
-     *         in which case it will be between 0.0 (inclusive)
-     *         and 1.0 (exclusive)
-     */
-    public static float boundedNextFloat(RandomNumberGenerator rng, float origin, float bound) {
-        float r = rng.nextFloat();
-        if (origin < bound) {
-            r = r * (bound - origin) + origin;
-            if (r >= bound) // may need to correct a rounding problem
-                r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);
-        }
-        return r;
-    }
-
-    /**
-     * This is the form of {@code nextFloat} used by the public method
-     * {@code nextFloat(bound)}.  This is essentially a version of
-     * {@code boundedNextFloat(origin, bound)} that has been
-     * specialized for the case where the {@code origin} is zero
-     * and the {@code bound} is greater than zero.
-     *
-     * @implNote The implementation of this method is identical to
-     *     the implementation of {@code nextDouble(bound)}
-     *     except that {@code float} values and the {@code nextFloat()}
-     *     method are used rather than {@code double} values and the
-     *     {@code nextDouble()} method.
-     *
-     * @param rng a random number generator to be used as a
-     *        source of pseudorandom {@code float} values
-     * @param bound the upper bound (exclusive); must be finite and
-     *        greater than zero
-     * @return a pseudorandomly chosen {@code float} value
-     *         between zero (inclusive) and {@code bound} (exclusive)
-     */
-    public static float boundedNextFloat(RandomNumberGenerator rng, float bound) {
-        // Specialize boundedNextFloat for origin == 0, bound > 0
-        float r = rng.nextFloat();
-        r = r * bound;
-        if (r >= bound) // may need to correct a rounding problem
-            r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);
-        return r;
-    }
-
-    // The following decides which of two strategies initialSeed() will use.
-    private static boolean secureRandomSeedRequested() {
-        String pp = java.security.AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction(
-                        "java.util.secureRandomSeed"));
-        return (pp != null && pp.equalsIgnoreCase("true"));
-    }
-
-    private static final boolean useSecureRandomSeed = secureRandomSeedRequested();
-
-    /**
-     * Returns a {@code long} value (chosen from some
-     * machine-dependent entropy source) that may be useful for
-     * initializing a source of seed values for instances of {@link RandomNumberGenerator}
-     * created by zero-argument constructors.  (This method should
-     * <i>not</i> be called repeatedly, once per constructed
-     * object; at most it should be called once per class.)
-     *
-     * @return a {@code long} value, randomly chosen using
-     *         appropriate environmental entropy
-     */
-    public static long initialSeed() {
-        if (useSecureRandomSeed) {
-            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);
-            return s;
-        }
-        return (mixStafford13(System.currentTimeMillis()) ^
-                mixStafford13(System.nanoTime()));
-    }
-
-    /**
-     * The first 32 bits of the golden ratio (1+sqrt(5))/2, forced to be odd.
-     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
-     */
-    public static final int  GOLDEN_RATIO_32 = 0x9e3779b9;
-
-    /**
-     * The first 64 bits of the golden ratio (1+sqrt(5))/2, forced to be odd.
-     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
-     */
-    public static final long GOLDEN_RATIO_64 = 0x9e3779b97f4a7c15L;
-
-    /**
-     * The first 32 bits of the silver ratio 1+sqrt(2), forced to be odd.
-     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
-     */
-    public static final int  SILVER_RATIO_32 = 0x6A09E667;
-
-    /**
-     * The first 64 bits of the silver ratio 1+sqrt(2), forced to be odd.
-     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
-     */
-    public static final long SILVER_RATIO_64 = 0x6A09E667F3BCC909L;
-
-    /**
-     * Computes the 64-bit mixing function for MurmurHash3.
-     * This is a 64-bit hashing function with excellent avalanche statistics.
-     * https://github.com/aappleby/smhasher/wiki/MurmurHash3
-     *
-     * Note that if the argument {@code z} is 0, the result is 0.
-     *
-     * @param z any long value
-     *
-     * @return the result of hashing z
-     */
-    public static long mixMurmur64(long z) {
-        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
-        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
-        return z ^ (z >>> 33);
-    }
-
-    /**
-     * Computes Stafford variant 13 of the 64-bit mixing function for MurmurHash3.
-     * This is a 64-bit hashing function with excellent avalanche statistics.
-     * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
-     *
-     * Note that if the argument {@code z} is 0, the result is 0.
-     *
-     * @param z any long value
-     *
-     * @return the result of hashing z
-     */
-    public static long mixStafford13(long z) {
-        z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
-        z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
-        return z ^ (z >>> 31);
-    }
-
-    /**
-     * Computes Doug Lea's 64-bit mixing function.
-     * This is a 64-bit hashing function with excellent avalanche statistics.
-     * It has the advantages of using the same multiplicative constant twice
-     * and of using only 32-bit shifts.
-     *
-     * Note that if the argument {@code z} is 0, the result is 0.
-     *
-     * @param z any long value
-     *
-     * @return the result of hashing z
-     */
-    public static long mixLea64(long z) {
-        z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L;
-        z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L;
-        return z ^ (z >>> 32);
-    }
-
-    /**
-     * Computes the 32-bit mixing function for MurmurHash3.
-     * This is a 32-bit hashing function with excellent avalanche statistics.
-     * https://github.com/aappleby/smhasher/wiki/MurmurHash3
-     *
-     * Note that if the argument {@code z} is 0, the result is 0.
-     *
-     * @param z any long value
-     *
-     * @return the result of hashing z
-     */
-    public static int mixMurmur32(int z) {
-        z = (z ^ (z >>> 16)) * 0x85ebca6b;
-        z = (z ^ (z >>> 13)) * 0xc2b2ae35;
-        return z ^ (z >>> 16);
-    }
-
-    /**
-     * Computes Doug Lea's 32-bit mixing function.
-     * This is a 32-bit hashing function with excellent avalanche statistics.
-     * It has the advantages of using the same multiplicative constant twice
-     * and of using only 16-bit shifts.
-     *
-     * Note that if the argument {@code z} is 0, the result is 0.
-     *
-     * @param z any long value
-     *
-     * @return the result of hashing z
-     */
-    public static int mixLea32(int z) {
-        z = (z ^ (z >>> 16)) * 0xd36d884b;
-        z = (z ^ (z >>> 16)) * 0xd36d884b;
-        return z ^ (z >>> 16);
-    }
-
-    // Non-public (package only) support for spliterators needed by AbstractSplittableRNG
-    // and AbstractArbitrarilyJumpableRNG and AbstractSharedRNG
-
-    /**
-     * Base class for making Spliterator classes for streams of randomly chosen values.
-     */
-    static abstract class RandomSpliterator {
-        long index;
-        final long fence;
-
-        RandomSpliterator(long index, long fence) {
-            this.index = index; this.fence = fence;
-        }
-
-        public long estimateSize() {
-            return fence - index;
-        }
-
-        public int characteristics() {
-            return (Spliterator.SIZED | Spliterator.SUBSIZED |
-                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
-        }
-    }
-
-
-    /*
-     * Implementation support for nextExponential() and nextGaussian() methods of RandomNumberGenerator.
-     *
-     * Each is implemented using McFarland's fast modified ziggurat algorithm (largely
-     * table-driven, with rare cases handled by computation and rejection sampling).
-     * Walker's alias method for sampling a discrete distribution also plays a role.
-     *
-     * The tables themselves, as well as a number of associated parameters, are defined
-     * in class java.util.DoubleZigguratTables, which is automatically generated by the
-     * program create_ziggurat_tables.c (which takes only a few seconds to run).
-     *
-     * For more information about the algorithms, see these articles:
-     *
-     * Christopher D. McFarland.  2016 (published online 24 Jun 2015).  A modified ziggurat
-     * algorithm for generating exponentially and normally distributed pseudorandom numbers.
-     * Journal of Statistical Computation and Simulation 86 (7), pages 1281-1294.
-     * https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234
-     * Also at https://arxiv.org/abs/1403.6870 (26 March 2014).
-     *
-     * Alastair J. Walker.  1977.  An efficient method for generating discrete random
-     * variables with general distributions. ACM Trans. Math. Software 3, 3
-     * (September 1977), 253-256. DOI: https://doi.org/10.1145/355744.355749
-     *
-     * Certain details of these algorithms depend critically on the quality of the
-     * low-order bits delivered by NextLong().  These algorithms should not be used
-     * with RNG algorithms (such as a simple Linear Congruential Generator) whose
-     * low-order output bits do not have good statistical quality.
-     */
-
-    // Implementation support for nextExponential()
-
-    static double computeNextExponential(RandomNumberGenerator rng) {
-        long U1 = rng.nextLong();
-        // Experimentation on a variety of machines indicates that it is overall much faster
-        // to do the following & and < operations on longs rather than first cast U1 to int
-        // (but then we need to cast to int before doing the array indexing operation).
-        long i = U1 & DoubleZigguratTables.exponentialLayerMask;
-        if (i < DoubleZigguratTables.exponentialNumberOfLayers) {
-            // This is the fast path (occurring more than 98% of the time).  Make an early exit.
-            return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1);
-        }
-        // We didn't use the upper part of U1 after all.  We'll be able to use it later.
-
-        for (double extra = 0.0; ; ) {
-            // Use Walker's alias method to sample an (unsigned) integer j from a discrete
-            // probability distribution that includes the tail and all the ziggurat overhangs;
-            // j will be less than DoubleZigguratTables.exponentialNumberOfLayers + 1.
-            long UA = rng.nextLong();
-            int j = (int)UA & DoubleZigguratTables.exponentialAliasMask;
-            if (UA >= DoubleZigguratTables.exponentialAliasThreshold[j]) {
-                j = DoubleZigguratTables.exponentialAliasMap[j] & DoubleZigguratTables.exponentialSignCorrectionMask;
-            }
-            if (j > 0) {   // Sample overhang j
-                // For the exponential distribution, every overhang is convex.
-                final double[] X = DoubleZigguratTables.exponentialX;
-                final double[] Y = DoubleZigguratTables.exponentialY;
-                for (;; U1 = (rng.nextLong() >>> 1)) {
-                    long U2 = (rng.nextLong() >>> 1);
-                    // Compute the actual x-coordinate of the randomly chosen point.
-                    double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
-                    // Does the point lie below the curve?
-                    long Udiff = U2 - U1;
-                    if (Udiff < 0) {
-                        // We picked a point in the upper-right triangle.  None of those can be accepted.
-                        // So remap the point into the lower-left triangle and try that.
-                        // In effect, we swap U1 and U2, and invert the sign of Udiff.
-                        Udiff = -Udiff;
-                        U2 = U1;
-                        U1 -= Udiff;
-                    }
-                    if (Udiff >= DoubleZigguratTables.exponentialConvexMargin) {
-                        return x + extra;   // The chosen point is way below the curve; accept it.
-                    }
-                    // Compute the actual y-coordinate of the randomly chosen point.
-                    double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
-                    // Now see how that y-coordinate compares to the curve
-                    if (y <= Math.exp(-x)) {
-                        return x + extra;   // The chosen point is below the curve; accept it.
-                    }
-                    // Otherwise, we reject this sample and have to try again.
-                }
-            }
-            // We are now committed to sampling from the tail.  We could do a recursive call
-            // and then add X[0] but we save some time and stack space by using an iterative loop.
-            extra += DoubleZigguratTables.exponentialX0;
-            // This is like the first five lines of this method, but if it returns, it first adds "extra".
-            U1 = rng.nextLong();
-            i = U1 & DoubleZigguratTables.exponentialLayerMask;
-            if (i < DoubleZigguratTables.exponentialNumberOfLayers) {
-                return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1) + extra;
-            }
-        }
-    }
-
-    // Implementation support for nextGaussian()
-
-    static double computeNextGaussian(RandomNumberGenerator rng) {
-        long U1 = rng.nextLong();
-        // Experimentation on a variety of machines indicates that it is overall much faster
-        // to do the following & and < operations on longs rather than first cast U1 to int
-        // (but then we need to cast to int before doing the array indexing operation).
-        long i = U1 & DoubleZigguratTables.normalLayerMask;
-
-        if (i < DoubleZigguratTables.normalNumberOfLayers) {
-            // This is the fast path (occurring more than 98% of the time).  Make an early exit.
-            return DoubleZigguratTables.normalX[(int)i] * U1;   // Note that the sign bit of U1 is used here.
-        }
-        // We didn't use the upper part of U1 after all.
-        // Pull U1 apart into a sign bit and a 63-bit value for later use.
-        double signBit = (U1 >= 0) ? 1.0 : -1.0;
-        U1 = (U1 << 1) >>> 1;
-
-        // Use Walker's alias method to sample an (unsigned) integer j from a discrete
-        // probability distribution that includes the tail and all the ziggurat overhangs;
-        // j will be less than DoubleZigguratTables.normalNumberOfLayers + 1.
-        long UA = rng.nextLong();
-        int j = (int)UA & DoubleZigguratTables.normalAliasMask;
-        if (UA >= DoubleZigguratTables.normalAliasThreshold[j]) {
-            j = DoubleZigguratTables.normalAliasMap[j] & DoubleZigguratTables.normalSignCorrectionMask;
-        }
-
-        double x;
-        // Now the goal is to choose the result, which will be multiplied by signBit just before return.
-
-        // There are four kinds of overhangs:
-        //
-        //  j == 0                          :  Sample from tail
-        //  0 < j < normalInflectionIndex   :  Overhang is convex; can reject upper-right triangle
-        //  j == normalInflectionIndex      :  Overhang includes the inflection point
-        //  j > normalInflectionIndex       :  Overhang is concave; can accept point in lower-left triangle
-        //
-        // Choose one of four loops to compute x, each specialized for a specific kind of overhang.
-        // Conditional statements are arranged such that the more likely outcomes are first.
-
-        // In the three cases other than the tail case:
-        // U1 represents a fraction (scaled by 2**63) of the width of rectangle measured from the left.
-        // U2 represents a fraction (scaled by 2**63) of the height of rectangle measured from the top.
-        // Together they indicate a randomly chosen point within the rectangle.
-
-        final double[] X = DoubleZigguratTables.normalX;
-        final double[] Y = DoubleZigguratTables.normalY;
-        if (j > DoubleZigguratTables.normalInflectionIndex) {   // Concave overhang
-            for (;; U1 = (rng.nextLong() >>> 1)) {
-                long U2 = (rng.nextLong() >>> 1);
-                // Compute the actual x-coordinate of the randomly chosen point.
-                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
-                // Does the point lie below the curve?
-                long Udiff = U2 - U1;
-                if (Udiff >= 0) {
-                    break;   // The chosen point is in the lower-left triangle; accept it.
-                }
-                if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) {
-                    continue;   // The chosen point is way above the curve; reject it.
-                }
-                // Compute the actual y-coordinate of the randomly chosen point.
-                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
-                // Now see how that y-coordinate compares to the curve
-                if (y <= Math.exp(-0.5*x*x)) {
-                    break;   // The chosen point is below the curve; accept it.
-                }
-                // Otherwise, we reject this sample and have to try again.
-            }
-        } else if (j == 0) {   // Tail
-            // Tail-sampling method of Marsaglia and Tsang.  See any one of:
-            // Marsaglia and Tsang. 1984. A fast, easily implemented method for sampling from decreasing
-            //    or symmetric unimodal density functions. SIAM J. Sci. Stat. Comput. 5, 349-359.
-            // Marsaglia and Tsang. 1998. The Monty Python method for generating random variables.
-            //    ACM Trans. Math. Softw. 24, 3 (September 1998), 341-350.  See page 342, step (4).
-            //    http://doi.org/10.1145/292395.292453
-            // Thomas, Luk, Leong, and Villasenor. 2007. Gaussian random number generators.
-            //    ACM Comput. Surv. 39, 4, Article 11 (November 2007).  See Algorithm 16.
-            //    http://doi.org/10.1145/1287620.1287622
-            // Compute two separate random exponential samples and then compare them in certain way.
-            do {
-                x = (1.0 / DoubleZigguratTables.normalX0) * computeNextExponential(rng);
-            } while (computeNextExponential(rng) < 0.5*x*x);
-            x += DoubleZigguratTables.normalX0;
-        } else if (j < DoubleZigguratTables.normalInflectionIndex) {   // Convex overhang
-            for (;; U1 = (rng.nextLong() >>> 1)) {
-                long U2 = (rng.nextLong() >>> 1);
-                // Compute the actual x-coordinate of the randomly chosen point.
-                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
-                // Does the point lie below the curve?
-                long Udiff = U2 - U1;
-                if (Udiff < 0) {
-                    // We picked a point in the upper-right triangle.  None of those can be accepted.
-                    // So remap the point into the lower-left triangle and try that.
-                    // In effect, we swap U1 and U2, and invert the sign of Udiff.
-                    Udiff = -Udiff;
-                    U2 = U1;
-                    U1 -= Udiff;
-                }
-                if (Udiff >= DoubleZigguratTables.normalConvexMargin) {
-                    break;   // The chosen point is way below the curve; accept it.
-                }
-                // Compute the actual y-coordinate of the randomly chosen point.
-                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
-                // Now see how that y-coordinate compares to the curve
-                if (y <= Math.exp(-0.5*x*x)) break;                // The chosen point is below the curve; accept it.
-                // Otherwise, we reject this sample and have to try again.
-            }
-        } else {
-            // The overhang includes the inflection point, so the curve is both convex and concave
-            for (;; U1 = (rng.nextLong() >>> 1)) {
-                long U2 = (rng.nextLong() >>> 1);
-                // Compute the actual x-coordinate of the randomly chosen point.
-                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
-                // Does the point lie below the curve?
-                long Udiff = U2 - U1;
-                if (Udiff >= DoubleZigguratTables.normalConvexMargin) {
-                    break;   // The chosen point is way below the curve; accept it.
-                }
-                if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) {
-                    continue;   // The chosen point is way above the curve; reject it.
-                }
-                // Compute the actual y-coordinate of the randomly chosen point.
-                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
-                // Now see how that y-coordinate compares to the curve
-                if (y <= Math.exp(-0.5*x*x)) {
-                    break;   // The chosen point is below the curve; accept it.
-                }
-                // Otherwise, we reject this sample and have to try again.
-            }
-        }
-        return signBit*x;
-    }
-
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/util/random/RandomGenerator.java	Fri Jul 26 15:37:05 2019 -0300
@@ -0,0 +1,1250 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.random;
+
+import java.math.BigInteger;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+/**
+ * The {@link RandomGenerator} interface is designed to provide a common protocol for objects
+ * that generate random or (more typically) pseudorandom sequences of numbers (or Boolean values).
+ * Such a sequence may be obtained by either repeatedly invoking a method that returns a single
+ * (pseudo)randomly chosen value, or by invoking a method that returns a stream of (pseudo)randomly
+ * chosen values.
+ * <p>
+ * Ideally, given an implicitly or explicitly specified range of values, each value would be chosen
+ * independently and uniformly from that range. In practice, one may have to settle for some
+ * approximation to independence and uniformity.
+ * <p>
+ * In the case of {@code int}, {@code long}, and {@link Boolean} values, if there is no explicit
+ * specification of range, then the range includes all possible values of the type.  In the case of
+ * {@code float} and {@code double} values, a value is always chosen from the set of
+ * 2<sup><i>w</i></sup> values between 0.0 (inclusive) and 1.0 (exclusive), where <i>w</i> is 23 for
+ * {@code float} values and 52 for {@code double} values, such that adjacent values differ by
+ * 2<sup>&minus;<i>w</i></sup>; if an explicit range is specified, then the chosen number is
+ * computationally scaled and translated so as to appear to have been chosen from that range.
+ * <p>
+ * Each method that returns a stream produces a stream of values each of which is chosen in the same
+ * manner as for a method that returns a single (pseudo)randomly chosen value.  For example, if
+ * {@code r} implements {@link RandomGenerator}, then the method call {@code r.ints(100)}
+ * returns a stream of 100 {@code int} values.  These are not necessarily the exact same values that
+ * would have been returned if instead {@code r.nextInt()} had been called 100 times; all that is
+ * guaranteed is that each value in the stream is chosen in a similar (pseudo)random manner from the
+ * same range.
+ * <p>
+ * Every object that implements the {@link RandomGenerator} interface is assumed to contain a
+ * finite amount of state.  Using such an object to generate a pseudorandomly chosen value alters
+ * its state.  The number of distinct possible states of such an object is called its
+ * <i>period</i>.  (Some implementations of the {@link RandomGenerator} interface
+ * may be truly random rather than pseudorandom, for example relying on the statistical behavior of
+ * a physical object to derive chosen values.  Such implementations do not have a fixed period.)
+ * <p>
+ * As a rule, objects that implement the {@link RandomGenerator} interface need not be
+ * thread-safe.  It is recommended that multithreaded applications use either {@link
+ * ThreadLocalRandom} or (preferably) pseudorandom number generators that implement the {@link
+ * SplittableGenerator} or {@link JumpableGenerator} interface.
+ * <p>
+ * To implement this interface, a class only needs to provide concrete definitions for the methods
+ * {@code nextLong()} and {@code period()}. Default implementations are provided for all other
+ * methods (but it may be desirable to override some of them, especially {@code nextInt()} if the
+ * underlying algorithm is {@code int}-based). Moerover, it may be preferable instead to implement
+ * another interface such as {@link JumpableGenerator} or {@link LeapableGenerator}, or to extend an abstract
+ * class such as {@link AbstractSplittableGenerator} or {@link AbstractArbitrarilyJumpableGenerator}.
+ * <p>
+ * Objects that implement {@link RandomGenerator} are typically not cryptographically secure.
+ * Consider instead using {@link java.security.SecureRandom} to get a cryptographically secure
+ * pseudorandom number generator for use by security-sensitive applications.  Note, however, that
+ * {@code java.security.SecureRandom} does implement the {@link RandomGenerator} interface, so
+ * that instances of {@code java.security.SecureRandom} may be used interchangeably with other types
+ * of pseudorandom generators in applications that do not require a secure generator.
+ *
+ * @since 14
+ */
+public interface RandomGenerator {
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandomly chosen
+     * {@code double} values.
+     *
+     * @return a stream of pseudorandomly chosen {@code double} values
+     *
+     * @implNote It is permitted to implement this method in a manner
+     * equivalent to {@code doubles(Long.MAX_VALUE)}.
+     *
+     * @implNote The default implementation produces a sequential stream
+     * that repeatedly calls {@code nextDouble()}.
+     */
+    default DoubleStream doubles() {
+        return DoubleStream.generate(this::nextDouble).sequential();
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandomly chosen
+     * {@code double} values, where each value is between the specified
+     * origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param randomNumberOrigin the least value that can be produced
+     * @param randomNumberBound the upper bound (exclusive) for each value produced
+     *
+     * @return a stream of pseudorandomly chosen {@code double} values, each between
+     *         the specified origin (inclusive) and the specified bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     *
+     * @implNote It is permitted to implement this method in a manner
+     *           equivalent to
+     *           {@code doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     * @implNote The default implementation produces a sequential stream that repeatedly
+     *           calls {@code nextDouble(randomNumberOrigin, randomNumberBound)}.
+     */
+    default DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
+        RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+        return DoubleStream.generate(() -> nextDouble(randomNumberOrigin, randomNumberBound)).sequential();
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandomly chosen {@code double} values.
+     *
+     * @param streamSize the number of values to generate
+     *
+     * @return a stream of pseudorandomly chosen {@code double} values
+     *
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     *
+     * @implNote The default implementation produces a sequential stream
+     * that repeatedly calls {@code nextDouble()}.
+     */
+    default DoubleStream doubles(long streamSize) {
+        RandomSupport.checkStreamSize(streamSize);
+        return doubles().limit(streamSize);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandomly chosen {@code double} values, where each value is between
+     * the specified origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the least value that can be produced
+     * @param randomNumberBound the upper bound (exclusive) for each value produced
+     *
+     * @return a stream of pseudorandomly chosen {@code double} values, each between
+     *         the specified origin (inclusive) and the specified bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero, or {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     *
+     * @implNote The default implementation produces a sequential stream
+     * that repeatedly calls {@code nextDouble(randomNumberOrigin, randomNumberBound)}.
+     */
+    default DoubleStream doubles(long streamSize, double randomNumberOrigin,
+                          double randomNumberBound) {
+        RandomSupport.checkStreamSize(streamSize);
+        RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+        return doubles(randomNumberOrigin, randomNumberBound).limit(streamSize);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandomly chosen
+     * {@code int} values.
+     *
+     * @return a stream of pseudorandomly chosen {@code int} values
+     *
+     * @implNote It is permitted to implement this method in a manner
+     * equivalent to {@code ints(Long.MAX_VALUE)}.
+     * @implNote The default implementation produces a sequential stream
+     * that repeatedly calls {@code nextInt()}.
+     */
+    default IntStream ints() {
+        return IntStream.generate(this::nextInt).sequential();
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandomly chosen
+     * {@code int} values, where each value is between the specified
+     * origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param randomNumberOrigin the least value that can be produced
+     * @param randomNumberBound the upper bound (exclusive) for each value produced
+     *
+     * @return a stream of pseudorandomly chosen {@code int} values, each between
+     *         the specified origin (inclusive) and the specified bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     *
+     * @implNote It is permitted to implement this method in a manner equivalent to
+     *           {@code ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     * @implNote The default implementation produces a sequential stream that repeatedly
+     *           calls {@code nextInt(randomNumberOrigin, randomNumberBound)}.
+     */
+    default IntStream ints(int randomNumberOrigin, int randomNumberBound) {
+        RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+        return IntStream.generate(() -> nextInt(randomNumberOrigin, randomNumberBound)).sequential();
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandomly chosen {@code int} values.
+     *
+     * @param streamSize the number of values to generate
+     *
+     * @return a stream of pseudorandomly chosen {@code int} values
+     *
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     *
+     * @implNote The default implementation produces a sequential stream
+     *           that repeatedly calls {@code nextInt()}.
+     */
+    default IntStream ints(long streamSize) {
+        RandomSupport.checkStreamSize(streamSize);
+        return ints().limit(streamSize);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandomly chosen {@code int} values, where each value is between
+     * the specified origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the least value that can be produced
+     * @param randomNumberBound the upper bound (exclusive) for each value produced
+     *
+     * @return a stream of pseudorandomly chosen {@code int} values, each between
+     *         the specified origin (inclusive) and the specified bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero, or {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     *
+     * @implNote The default implementation produces a sequential stream that repeatedly
+     *           calls {@code nextInt(randomNumberOrigin, randomNumberBound)}.
+     */
+    default IntStream ints(long streamSize, int randomNumberOrigin,
+                          int randomNumberBound) {
+        RandomSupport.checkStreamSize(streamSize);
+        RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+        return ints(randomNumberOrigin, randomNumberBound).limit(streamSize);
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandomly chosen
+     * {@code long} values.
+     *
+     * @return a stream of pseudorandomly chosen {@code long} values
+     *
+     * @implNote It is permitted to implement this method in a manner
+     *           equivalent to {@code longs(Long.MAX_VALUE)}.
+     * @implNote The default implementation produces a sequential stream
+     *           that repeatedly calls {@code nextLong()}.
+     */
+    default LongStream longs() {
+        return LongStream.generate(this::nextLong).sequential();
+    }
+
+    /**
+     * Returns an effectively unlimited stream of pseudorandomly chosen
+     * {@code long} values, where each value is between the specified
+     * origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param randomNumberOrigin the least value that can be produced
+     * @param randomNumberBound the upper bound (exclusive) for each value produced
+     *
+     * @return a stream of pseudorandomly chosen {@code long} values, each between
+     *         the specified origin (inclusive) and the specified bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     *
+     * @implNote It is permitted to implement this method in a manner
+     *           equivalent to {@code longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+     * @implNote The default implementation produces a sequential stream that repeatedly
+     *           calls {@code nextLong(randomNumberOrigin, randomNumberBound)}.
+     */
+    default LongStream longs(long randomNumberOrigin, long randomNumberBound) {
+        RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+        return LongStream.generate(() -> nextLong(randomNumberOrigin, randomNumberBound)).sequential();
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandomly chosen {@code long} values.
+     *
+     * @param streamSize the number of values to generate
+     *
+     * @return a stream of pseudorandomly chosen {@code long} values
+     *
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero
+     *
+     * @implNote The default implementation produces a sequential stream
+     * that repeatedly calls {@code nextLong()}.
+     */
+    default LongStream longs(long streamSize) {
+        RandomSupport.checkStreamSize(streamSize);
+        return longs().limit(streamSize);
+    }
+
+    /**
+     * Returns a stream producing the given {@code streamSize} number of
+     * pseudorandomly chosen {@code long} values, where each value is between
+     * the specified origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param streamSize the number of values to generate
+     * @param randomNumberOrigin the least value that can be produced
+     * @param randomNumberBound the upper bound (exclusive) for each value produced
+     *
+     * @return a stream of pseudorandomly chosen {@code long} values, each between
+     *         the specified origin (inclusive) and the specified bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code streamSize} is
+     *         less than zero, or {@code randomNumberOrigin}
+     *         is greater than or equal to {@code randomNumberBound}
+     *
+     * @implNote The default implementation produces a sequential stream that repeatedly
+     *            calls {@code nextLong(randomNumberOrigin, randomNumberBound)}.
+     */
+    default LongStream longs(long streamSize, long randomNumberOrigin,
+                          long randomNumberBound) {
+        RandomSupport.checkStreamSize(streamSize);
+        RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+        return longs(randomNumberOrigin, randomNumberBound).limit(streamSize);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code boolean} value.
+     * <p>
+     * The default implementation tests the high-order bit (sign bit) of a value produced by {@code
+     * nextInt()}, on the grounds that some algorithms for pseudorandom number generation produce
+     * values whose high-order bits have better statistical quality than the low-order bits.
+     *
+     * @return a pseudorandomly chosen {@code boolean} value
+     */
+    default boolean nextBoolean() {
+        return nextInt() < 0;
+    }
+
+    /**
+     * Returns a pseudorandom {@code float} value between zero (inclusive) and one (exclusive).
+     * <p>
+     * The default implementation uses the 24 high-order bits from a call to {@code nextInt()}.
+     *
+     * @return a pseudorandom {@code float} value between zero (inclusive) and one (exclusive)
+     */
+    default float nextFloat() {
+        return (nextInt() >>> 8) * 0x1.0p-24f;
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code float} value between zero
+     * (inclusive) and the specified bound (exclusive).
+     *
+     * @param bound the upper bound (exclusive) for the returned value.
+     *        Must be positive and finite
+     *
+     * @return a pseudorandomly chosen {@code float} value between
+     *         zero (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not
+     *         positive and finite
+     *
+     * @implNote The default implementation simply calls
+     *     {@code RandomSupport.checkBound(bound)} and then
+     *     {@code RandomSupport.boundedNextFloat(this, bound)}.
+     */
+    default float nextFloat(float bound) {
+        RandomSupport.checkBound(bound);
+        return RandomSupport.boundedNextFloat(this, bound);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code float} value between the
+     * specified origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param origin the least value that can be returned
+     * @param bound the upper bound (exclusive)
+     *
+     * @return a pseudorandomly chosen {@code float} value between the
+     *         origin (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException unless {@code origin} is finite,
+     *         {@code bound} is finite, and {@code origin} is less than
+     *         {@code bound}
+     *
+     * @implNote The default implementation simply calls
+     *           {@code RandomSupport.checkRange(origin, bound)} and then
+     *          {@code RandomSupport.boundedNextFloat(this, origin, bound)}.
+     */
+    default float nextFloat(float origin, float bound) {
+        RandomSupport.checkRange(origin, bound);
+        return RandomSupport.boundedNextFloat(this, origin, bound);
+    }
+
+    /**
+     * Returns a pseudorandom {@code double} value between zero (inclusive) and one (exclusive).
+     * <p>
+     * The default implementation uses the 53 high-order bits from a call to {@code nextLong()}.
+     *
+     * @return a pseudorandom {@code double} value between zero (inclusive) and one (exclusive)
+     */
+    default double nextDouble() {
+        return (nextLong() >>> 11) * 0x1.0p-53;
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code double} value between zero
+     * (inclusive) and the specified bound (exclusive).
+     *
+     * @param bound the upper bound (exclusive) for the returned value.
+     *        Must be positive and finite
+     *
+     * @return a pseudorandomly chosen {@code double} value between
+     *         zero (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not
+     *         positive and finite
+     *
+     * @implNote The default implementation simply calls
+     *           {@code RandomSupport.checkBound(bound)} and then
+     *           {@code RandomSupport.boundedNextDouble(this, bound)}.
+     */
+    default double nextDouble(double bound) {
+        RandomSupport.checkBound(bound);
+        return RandomSupport.boundedNextDouble(this, bound);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code double} value between the
+     * specified origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param origin the least value that can be returned
+     * @param bound the upper bound (exclusive) for the returned value
+     *
+     * @return a pseudorandomly chosen {@code double} value between the
+     *         origin (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException unless {@code origin} is finite,
+     *         {@code bound} is finite, and {@code origin} is less than
+     *         {@code bound}
+     *
+     * @implNote The default implementation simply calls
+     *           {@code RandomSupport.checkRange(origin, bound)} and then
+     *           {@code RandomSupport.boundedNextDouble(this, origin, bound)}.
+     */
+    default double nextDouble(double origin, double bound) {
+        RandomSupport.checkRange(origin, bound);
+        return RandomSupport.boundedNextDouble(this, origin, bound);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code int} value.
+     * <p>
+     * The default implementation uses the 32 high-order bits from a call to {@code nextLong()}.
+     *
+     * @return a pseudorandomly chosen {@code int} value
+     */
+    default public int nextInt() {
+        return (int)(nextLong() >>> 32);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code int} value between
+     * zero (inclusive) and the specified bound (exclusive).
+     *
+     * @param bound the upper bound (exclusive) for the returned value. Must be positive.
+     *
+     * @return a pseudorandomly chosen {@code int} value between
+     *         zero (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not positive
+     *
+     * @implNote The default implementation simply calls
+     *           {@code RandomSupport.checkBound(bound)} and then
+     *           {@code RandomSupport.boundedNextInt(this, bound)}.
+     */
+    default int nextInt(int bound) {
+        RandomSupport.checkBound(bound);
+        return RandomSupport.boundedNextInt(this, bound);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code int} value between the
+     * specified origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param origin the least value that can be returned
+     * @param bound the upper bound (exclusive) for the returned value
+     *
+     * @return a pseudorandomly chosen {@code int} value between the
+     *         origin (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code origin} is greater than
+     *         or equal to {@code bound}
+     *
+     * @implNote The default implementation simply calls
+     *           {@code RandomSupport.checkRange(origin, bound)} and then
+     *           {@code RandomSupport.boundedNextInt(this, origin, bound)}.
+     */
+    default int nextInt(int origin, int bound) {
+        RandomSupport.checkRange(origin, bound);
+        return RandomSupport.boundedNextInt(this, origin, bound);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code long} value.
+     *
+     * @return a pseudorandomly chosen {@code long} value
+     */
+    long nextLong();
+
+    /**
+     * Returns a pseudorandomly chosen {@code long} value between
+     * zero (inclusive) and the specified bound (exclusive).
+     *
+     * @param bound the upper bound (exclusive) for the returned value.  Must be positive.
+     *
+     * @return a pseudorandomly chosen {@code long} value between
+     *         zero (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not positive
+     *
+     * @implNote The default implementation simply calls
+     *           {@code RandomSupport.checkBound(bound)} and then
+     *           {@code RandomSupport.boundedNextLong(this, bound)}.
+     */
+    default long nextLong(long bound) {
+        RandomSupport.checkBound(bound);
+        return RandomSupport.boundedNextLong(this, bound);
+    }
+
+    /**
+     * Returns a pseudorandomly chosen {@code long} value between the
+     * specified origin (inclusive) and the specified bound (exclusive).
+     *
+     * @param origin the least value that can be returned
+     * @param bound the upper bound (exclusive) for the returned value
+     *
+     * @return a pseudorandomly chosen {@code long} value between the
+     *         origin (inclusive) and the bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code origin} is greater than
+     *         or equal to {@code bound}
+     *
+     * @implNote The default implementation simply calls
+     *           {@code RandomSupport.checkRange(origin, bound)} and then
+     *           {@code RandomSupport.boundedNextInt(this, origin, bound)}.
+     *
+     */
+    default long nextLong(long origin, long bound) {
+        RandomSupport.checkRange(origin, bound);
+        return RandomSupport.boundedNextLong(this, origin, bound);
+    }
+
+    /**
+     * Returns a {@code double} value pseudorandomly chosen from
+     * a Gaussian (normal) distribution whose mean is 0 and whose
+     * standard deviation is 1.
+     *
+     * @return a {@code double} value pseudorandomly chosen from a
+     *         Gaussian distribution
+     */
+    default double nextGaussian() {
+        return RandomSupport.computeNextGaussian(this);
+    }
+
+    /**
+     * Returns a {@code double} value pseudorandomly chosen from
+     * a Gaussian (normal) distribution with a mean and
+     * standard deviation specified by the arguments.
+     *
+     * @param mean the mean of the Gaussian distribution to be drawn from
+     * @param stddev the standard deviation (square root of the variance)
+     *        of the Gaussian distribution to be drawn from
+     *
+     * @return a {@code double} value pseudorandomly chosen from the
+     *         specified Gaussian distribution
+     *
+     * @throws IllegalArgumentException if {@code stddev} is negative
+     */
+    default double nextGaussian(double mean, double stddev) {
+        if (stddev < 0.0) throw new IllegalArgumentException("standard deviation must be non-negative");
+        return mean + stddev * RandomSupport.computeNextGaussian(this);
+    }
+
+    /**
+     * Returns a nonnegative {@code double} value pseudorandomly chosen
+     * from an exponential distribution whose mean is 1.
+     *
+     * @return a nonnegative {@code double} value pseudorandomly chosen from an
+     *         exponential distribution
+     */
+    default double nextExponential() {
+        return RandomSupport.computeNextExponential(this);
+    }
+
+    /**
+     * Returns the period of this {@link RandomGenerator} object.
+     *
+     * @return a {@link BigInteger} whose value is the number of distinct possible states of this
+     *         {@link RandomGenerator} object, or 0 if unknown, or negative if extremely
+     *         large.
+     */
+    BigInteger period();
+
+    /**
+     * The value (0) returned by the {@code period()} method if the period is unknown.
+     */
+    static final BigInteger UNKNOWN_PERIOD = BigInteger.ZERO;
+
+    /**
+     * The (negative) value returned by the {@code period()} method if this generator
+     * has no period because it is truly random rather than just pseudorandom.
+     */
+    static final BigInteger TRULY_RANDOM = BigInteger.valueOf(-1);
+
+    /**
+     * The (negative) value that may be returned by the {@code period()} method
+     * if this generator has a huge period (larger than 2**(2**16)).
+     */
+    static final BigInteger HUGE_PERIOD = BigInteger.valueOf(-2);
+
+    /**
+     * The {@link StreamableGenerator} interface augments the {@link RandomGenerator} interface
+     * to provide methods that return streams of {@link RandomGenerator} objects.
+     * Ideally, such a stream of objects would have the property that the
+     * behavior of each object is statistically independent of all the others.
+     * In practice, one may have to settle for some approximation to this property.
+     *
+     * A generator that implements interface {@link SplittableGenerator}
+     * may choose to use its {@code splits} method to implement the {@code rngs}
+     * method required by this interface.
+     *
+     * A generator that implements interface {@link JumpableGenerator}
+     * may choose to use its {@code jumps} method to implement the {@code rngs}
+     * method required by this interface.
+     *
+     * A generator that implements interface {@link LeapableGenerator}
+     * may choose to use its {@code leaps} method to implement the {@code rngs}
+     * method required by this interface.
+     * <p>
+     * An implementation of the {@link StreamableGenerator} interface must provide
+     * concrete definitions for the methods {@code nextInt()}, {@code nextLong},
+     * {@code period()}, and {@code rngs()}.
+     * Default implementations are provided for all other methods.
+     * <p>
+     * Objects that implement {@link StreamableGenerator} are typically
+     * not cryptographically secure.  Consider instead using
+     * {@link java.security.SecureRandom} to get a cryptographically
+     * secure pseudo-random number generator for use by
+     * security-sensitive applications.
+     *
+     * @since 14
+     */
+    public interface StreamableGenerator extends RandomGenerator {
+        /**
+         * Returns an effectively unlimited stream of objects, each of
+         * which implements the {@link RandomGenerator} interface.  Ideally the
+         * generators in the stream will appear to be statistically
+         * independent.  The new generators should be of the same kind
+         * as this generator.
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @implNote It is permitted to implement this method in a manner
+         *           equivalent to {@code rngs(Long.MAX_VALUE)}.
+         */
+        Stream<RandomGenerator> rngs();
+
+        /**
+         * Returns an effectively unlimited stream of objects, each of
+         * which implements the {@link RandomGenerator} interface.  Ideally the
+         * generators in the stream will appear to be statistically
+         * independent.  The new generators should be of the same kind
+         * as this generator.
+         *
+         * @param streamSize the number of generators to generate
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is
+         *         less than zero
+         *
+         * @implNote The default implementation calls {@code rngs()} and
+         *           then limits its length to {@code streamSize}.
+         */
+        default Stream<RandomGenerator> rngs(long streamSize) {
+            RandomSupport.checkStreamSize(streamSize);
+            return rngs().limit(streamSize);
+        }
+    }
+
+    /**
+     * This interface is designed to provide a common protocol for objects
+     * that generate sequences of pseudorandom numbers (or Boolean values)
+     * and furthermore can be <i>split</i> into two objects (the original
+     * one and a new one) each of which obey that same protocol (and therefore
+     * can be recursively split indefinitely).
+     * <p>
+     * Ideally, all {@link SplittableGenerator} objects produced by recursive
+     * splitting from a single original {@link SplittableGenerator} object are
+     * statistically independent of one another and individually uniform.
+     * Therefore we would expect the set of values collectively generated
+     * by a set of such objects to have the same statistical properties as
+     * if the same quantity of values were generated by a single thread
+     * using a single {@link SplittableGenerator} object.  In practice, one must
+     * settle for some approximation to independence and uniformity.
+     * <p>
+     * Methods are provided to perform a single splitting operation and
+     * also to produce a stream of generators split off from the original
+     * (by either iterative or recursive splitting, or a combination).
+     * <p>
+     * An implementation of the {@link SplittableGenerator} interface must provide
+     * concrete definitions for the methods {@code nextInt()}, {@code nextLong},
+     * {@code period()}, {@code split()}, {@code split(SplittableGenerator)},
+     * {@code splits()}, {@code splits(long)}, {@code splits(SplittableGenerator)},
+     * and {@code splits(long, SplittableGenerator)}.  Perhaps the most convenient
+     * way to implement this interface is to extend the abstract class
+     * {@link AbstractSplittableGenerator}.
+     * <p>
+     * Objects that implement {@link SplittableGenerator} are
+     * typically not cryptographically secure.  Consider instead using
+     * {@link java.security.SecureRandom} to get a cryptographically
+     * secure pseudo-random number generator for use by
+     * security-sensitive applications.
+     *
+     * @since 14
+     */
+    public interface SplittableGenerator extends StreamableGenerator {
+
+        /**
+         * Returns a new pseudorandom number generator, split off from
+         * this one, that implements the {@link RandomGenerator} and {@link SplittableGenerator}
+         * interfaces.
+         *
+         * This pseudorandom number generator may be used as a source of
+         * pseudorandom bits used to initialize the state the new one.
+         *
+         * @return a new object that implements the {@link RandomGenerator} and
+         *         {@link SplittableGenerator} interfaces
+         */
+        SplittableGenerator split();
+
+        /**
+         * Returns a new pseudorandom number generator, split off from
+         * this one, that implements the {@link RandomGenerator} and {@link SplittableGenerator}
+         * interfaces.
+         *
+         * @param source a {@link SplittableGenerator} instance to be used instead
+         *               of this one as a source of pseudorandom bits used to
+         *               initialize the state of the new ones.
+         *
+         * @return an object that implements the {@link RandomGenerator} and
+         *         {@link SplittableGenerator} interfaces
+         */
+        SplittableGenerator split(SplittableGenerator source);
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom
+         * number generators, each of which implements the {@link SplittableGenerator}
+         * interface.
+         *
+         * This pseudorandom number generator may be used as a source of
+         * pseudorandom bits used to initialize the state the new ones.
+         *
+         * @implNote It is permitted to implement this method in a manner
+         * equivalent to {@code splits(Long.MAX_VALUE)}.
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         */
+        default Stream<SplittableGenerator> splits() {
+            return this.splits(this);
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of
+         * new pseudorandom number generators, each of which implements the
+         * {@link SplittableGenerator} interface.
+         *
+         * This pseudorandom number generator may be used as a source of
+         * pseudorandom bits used to initialize the state the new ones.
+         *
+         * @param streamSize the number of values to generate
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is
+         *         less than zero
+         */
+        Stream<SplittableGenerator> splits(long streamSize);
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom
+         * number generators, each of which implements the {@link SplittableGenerator}
+         * interface.
+         *
+         * @param source a {@link SplittableGenerator} instance to be used instead
+         *               of this one as a source of pseudorandom bits used to
+         *               initialize the state of the new ones.
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         *
+         * @implNote It is permitted to implement this method in a manner
+         *           equivalent to {@code splits(Long.MAX_VALUE, source)}.
+         */
+        Stream<SplittableGenerator> splits(SplittableGenerator source);
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of
+         * new pseudorandom number generators, each of which implements the
+         * {@link SplittableGenerator} interface.
+         *
+         * @param streamSize the number of values to generate
+         * @param source a {@link SplittableGenerator} instance to be used instead
+         *               of this one as a source of pseudorandom bits used to
+         *               initialize the state of the new ones.
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is
+         *         less than zero
+         */
+        Stream<SplittableGenerator> splits(long streamSize, SplittableGenerator source);
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom
+         * number generators, each of which implements the {@link RandomGenerator}
+         * interface.  Ideally the generators in the stream will appear
+         * to be statistically independent.
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @implNote The default implementation calls {@code splits()}.
+         */
+        default Stream<RandomGenerator> rngs() {
+            return this.splits().map(x -> (RandomGenerator)x);
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of
+         * new pseudorandom number generators, each of which implements the
+         * {@link RandomGenerator} interface.  Ideally the generators in the stream will
+         * appear to be statistically independent.
+         *
+         * @param streamSize the number of generators to generate
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is
+         *         less than zero
+         *
+         * @implNote The default implementation calls {@code splits(streamSize)}.
+         */
+        default Stream<RandomGenerator> rngs(long streamSize) {
+            return this.splits(streamSize).map(x -> (RandomGenerator)x);
+        }
+    }
+
+    /**
+     * This interface is designed to provide a common protocol for objects that generate pseudorandom
+     * sequences of numbers (or Boolean values) and furthermore can easily <i>jump</i> forward (by a
+     * fixed amount) to a distant point in the state cycle.
+     * <p>
+     * Ideally, all {@link JumpableGenerator} objects produced by iterative jumping from a single original
+     * {@link JumpableGenerator} object are statistically independent of one another and individually uniform.
+     * In practice, one must settle for some approximation to independence and uniformity.  In
+     * particular, a specific implementation may assume that each generator in a stream produced by the
+     * {@code jumps} method is used to produce a number of values no larger than either 2<sup>64</sup>
+     * or the square root of its period.  Implementors are advised to use algorithms whose period is at
+     * least 2<sup>127</sup>.
+     * <p>
+     * Methods are provided to perform a single jump operation and also to produce a stream of
+     * generators produced from the original by iterative copying and jumping of internal state.  A
+     * typical strategy for a multithreaded application is to create a single {@link JumpableGenerator}
+     * object, calls its {@code jumps} method exactly once, and then parcel out generators from the
+     * resulting stream, one to each thread.  It is generally not a good idea to call {@code jump} on a
+     * generator that was itself produced by the {@code jumps} method, because the result may be a
+     * generator identical to another generator already produce by that call to the {@code jumps}
+     * method. For this reason, the return type of the {@code jumps} method is {@code
+     * Stream<RandomGenerator>} rather than {@code Stream<JumpableGenerator>}, even though the actual
+     * generator objects in that stream likely do also implement the {@link JumpableGenerator} interface.
+     * <p>
+     * An implementation of the {@link JumpableGenerator} interface must provide concrete definitions for the
+     * methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code copy()}, {@code jump()},
+     * and {@code defaultJumpDistance()}. Default implementations are provided for all other methods.
+     * <p>
+     * Objects that implement {@link JumpableGenerator} are typically not cryptographically secure.  Consider
+     * instead using {@link java.security.SecureRandom} to get a cryptographically secure pseudo-random
+     * number generator for use by security-sensitive applications.
+     *
+     * @since 14
+     */
+    public interface JumpableGenerator extends StreamableGenerator {
+        /**
+         * Returns a new generator whose internal state is an exact copy of this generator (therefore
+         * their future behavior should be identical if subjected to the same series of operations).
+         *
+         * @return a new object that is a copy of this generator
+         */
+        JumpableGenerator copy();
+
+        /**
+         * Alter the state of this pseudorandom number generator so as to jump forward a large, fixed
+         * distance (typically 2<sup>64</sup> or more) within its state cycle.
+         */
+        void jump();
+
+        /**
+         * Returns the distance by which the {@code jump()} method will jump forward within the state
+         * cycle of this generator object.
+         *
+         * @return the default jump distance (as a {@code double} value)
+         */
+        double defaultJumpDistance();
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link RandomGenerator} interface.
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @implNote It is permitted to implement this method in a manner equivalent to
+         *         {@code jumps(Long.MAX_VALUE)}.
+         * @implNote The default implementation produces a sequential stream that  repeatedly
+         *         calls {@code copy()} and {@code jump()} on this generator, and the copies become the
+         *         generators produced by the stream.
+         */
+        default Stream<RandomGenerator> jumps() {
+            return Stream.generate(this::copyAndJump).sequential();
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link RandomGenerator} interface.
+         *
+         * @param streamSize the number of generators to generate
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         * @implNote The default implementation produces a sequential stream that  repeatedly
+         *         calls {@code copy()} and {@code jump()} on this generator, and the copies become the
+         *         generators produced by the stream.
+         */
+        default Stream<RandomGenerator> jumps(long streamSize) {
+            return jumps().limit(streamSize);
+        }
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link RandomGenerator} interface.  Ideally the generators in the stream
+         * will appear to be statistically independent.
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @implNote The default implementation calls {@code jumps()}.
+         */
+        default Stream<RandomGenerator> rngs() {
+            return this.jumps();
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link RandomGenerator} interface.  Ideally
+         * the generators in the stream will appear to be statistically independent.
+         *
+         * @param streamSize the number of generators to generate
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         * @implNote The default implementation calls {@code jumps(streamSize)}.
+         */
+        default Stream<RandomGenerator> rngs(long streamSize) {
+            return this.jumps(streamSize);
+        }
+
+        /**
+         * Copy this generator, jump this generator forward, then return the copy.
+         *
+         * @return a copy of this generator object before the jump occurred
+         */
+        default RandomGenerator copyAndJump() {
+            RandomGenerator result = copy();
+            jump();
+            return result;
+        }
+
+    }
+
+    /**
+     * This interface is designed to provide a common protocol for objects that generate sequences of
+     * pseudorandom numbers (or Boolean values) and furthermore can easily not only jump but also
+     * <i>leap</i> to a very distant point in the state cycle.
+     * <p>
+     * Typically one will construct a series of {@link LeapableGenerator} objects by iterative leaping from a
+     * single original {@link LeapableGenerator} object, and then for each such object produce a subseries of
+     * objects by iterative jumping.  There is little conceptual difference between leaping and jumping,
+     * but typically a leap will be a very long jump in the state cycle (perhaps distance
+     * 2<sup>128</sup> or so).
+     * <p>
+     * Ideally, all {@link LeapableGenerator} objects produced by iterative leaping and jumping from a single
+     * original {@link LeapableGenerator} object are statistically independent of one another and individually
+     * uniform. In practice, one must settle for some approximation to independence and uniformity.  In
+     * particular, a specific implementation may assume that each generator in a stream produced by the
+     * {@code leaps} method is used to produce (by jumping) a number of objects no larger than
+     * 2<sup>64</sup>.  Implementors are advised to use algorithms whose period is at least
+     * 2<sup>191</sup>.
+     * <p>
+     * Methods are provided to perform a single leap operation and also to produce a stream of
+     * generators produced from the original by iterative copying and leaping of internal state.  The
+     * generators produced must implement the {@link JumpableGenerator} interface but need not also implement
+     * the {@link LeapableGenerator} interface.  A typical strategy for a multithreaded application is to
+     * create a single {@link LeapableGenerator} object, calls its {@code leaps} method exactly once, and then
+     * parcel out generators from the resulting stream, one to each thread.  Then the {@code jumps}
+     * method of each such generator be called to produce a substream of generator objects.
+     * <p>
+     * An implementation of the {@link LeapableGenerator} interface must provide concrete definitions for the
+     * methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code copy()}, {@code jump()},
+     * {@code defaultJumpDistance()}, {@code leap()}, and {@code defaultLeapDistance()}. Default
+     * implementations are provided for all other methods.
+     * <p>
+     * Objects that implement {@link LeapableGenerator} are typically not cryptographically secure.  Consider
+     * instead using {@link java.security.SecureRandom} to get a cryptographically secure pseudo-random
+     * number generator for use by security-sensitive applications.
+     *
+     * @since 14
+     */
+    public interface LeapableGenerator extends JumpableGenerator {
+        /**
+         * Returns a new generator whose internal state is an exact copy of this generator (therefore
+         * their future behavior should be identical if subjected to the same series of operations).
+         *
+         * @return a new object that is a copy of this generator
+         */
+        LeapableGenerator copy();
+
+        /**
+         * Alter the state of this pseudorandom number generator so as to leap forward a large, fixed
+         * distance (typically 2<sup>96</sup> or more) within its state cycle.
+         */
+        void leap();
+
+        /**
+         * Returns the distance by which the {@code leap()} method will leap forward within the state
+         * cycle of this generator object.
+         *
+         * @return the default leap distance (as a {@code double} value)
+         */
+        double defaultLeapDistance();
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link JumpableGenerator} interface.
+         *
+         * @return a stream of objects that implement the {@link JumpableGenerator} interface
+         *
+         * @implNote It is permitted to implement this method in a manner equivalent to {@code
+         *         leaps(Long.MAX_VALUE)}.
+         * @implNote The default implementation produces a sequential stream that  repeatedly
+         *         calls {@code copy()} and {@code leap()} on this generator, and the copies become the
+         *         generators produced by the stream.
+         */
+        default Stream<JumpableGenerator> leaps() {
+            return Stream.generate(this::copyAndLeap).sequential();
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link JumpableGenerator} interface.
+         *
+         * @param streamSize the number of generators to generate
+         *
+         * @return a stream of objects that implement the {@link JumpableGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         * @implNote The default implementation produces a sequential stream that  repeatedly
+         *         calls {@code copy()} and {@code leap()} on this generator, and the copies become the
+         *         generators produced by the stream.
+         */
+        default Stream<JumpableGenerator> leaps(long streamSize) {
+            return leaps().limit(streamSize);
+        }
+
+        /**
+         * Copy this generator, leap this generator forward, then return the copy.
+         *
+         * @return a copy of this generator object before the leap occurred
+         */
+        default JumpableGenerator copyAndLeap() {
+            JumpableGenerator result = copy();
+            leap();
+            return result;
+        }
+
+    }
+
+    /**
+     * This interface is designed to provide a common protocol for objects that generate sequences of
+     * pseudorandom numbers (or Boolean values) and furthermore can easily <i>jump</i> to an arbitrarily
+     * specified distant point in the state cycle.
+     * <p>
+     * Ideally, all {@link ArbitrarilyJumpableGenerator} objects produced by iterative jumping from a single
+     * original {@link ArbitrarilyJumpableGenerator} object are statistically independent of one another and
+     * individually uniform, provided that they do not traverse overlapping portions of the state cycle.
+     *  In practice, one must settle for some approximation to independence and uniformity.  In
+     * particular, a specific implementation may assume that each generator in a stream produced by the
+     * {@code jumps} method is used to produce a number of values no larger than the jump distance
+     * specified.  Implementors are advised to use algorithms whose period is at least 2<sup>127</sup>.
+     * <p>
+     * For many applications, it suffices to jump forward by a power of two or some small multiple of a
+     * power of two, but this power of two may not be representable as a {@code long} value.  To avoid
+     * the use of {@link java.math.BigInteger} values as jump distances, {@code double} values are used
+     * instead.
+     * <p>
+     * Methods are provided to perform a single jump operation and also to produce a stream of
+     * generators produced from the original by iterative copying and jumping of internal state.  A
+     * typical strategy for a multithreaded application is to create a single {@link
+     * ArbitrarilyJumpableGenerator} object, call its {@code jumps} method exactly once, and then parcel out
+     * generators from the resulting stream, one to each thread.  However, each generator produced also
+     * has type {@link ArbitrarilyJumpableGenerator}; with care, different jump distances can be used to
+     * traverse the entire state cycle in various ways.
+     * <p>
+     * An implementation of the {@link ArbitrarilyJumpableGenerator} interface must provide concrete
+     * definitions for the methods {@code nextInt()}, {@code nextLong}, {@code period()}, {@code
+     * copy()}, {@code jump(double)}, {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
+     * Default implementations are provided for all other methods. Perhaps the most convenient way to
+     * implement this interface is to extend the abstract class {@link ArbitrarilyJumpableGenerator}, which
+     * provides spliterator-based implementations of the methods {@code ints}, {@code longs}, {@code
+     * doubles}, {@code rngs}, {@code jumps}, and {@code leaps}.
+     * <p>
+     * Objects that implement {@link ArbitrarilyJumpableGenerator} are typically not cryptographically secure.
+     * Consider instead using {@link java.security.SecureRandom} to get a cryptographically secure
+     * pseudo-random number generator for use by security-sensitive applications.
+     *
+     * @since 14
+     */
+    public interface ArbitrarilyJumpableGenerator extends LeapableGenerator {
+        /**
+         * Returns a new generator whose internal state is an exact copy of this generator (therefore
+         * their future behavior should be identical if subjected to the same series of operations).
+         *
+         * @return a new object that is a copy of this generator
+         */
+        ArbitrarilyJumpableGenerator copy();
+
+        /**
+         * Alter the state of this pseudorandom number generator so as to jump forward a distance equal
+         * to 2<sup>{@code logDistance}</sup> within its state cycle.
+         *
+         * @param logDistance the base-2 logarithm of the distance to jump forward within the state
+         *                    cycle
+         *
+         * @throws IllegalArgumentException if {@code logDistance} is NaN or negative, or if
+         *                                  2<sup>{@code logDistance}</sup> is greater than the period
+         *                                  of this generator
+         */
+        void jumpPowerOfTwo(int logDistance);
+
+        /**
+         * Alter the state of this pseudorandom number generator so as to jump forward a specified
+         * distance within its state cycle.
+         *
+         * @param distance the distance to jump forward within the state cycle
+         *
+         * @throws IllegalArgumentException if {@code distance} is Nan, negative, or greater than the
+         *                                  period of this generator
+         */
+        void jump(double distance);
+
+        /**
+         * Alter the state of this pseudorandom number generator so as to jump forward a large, fixed
+         * distance (typically 2<sup>64</sup> or more) within its state cycle.  The distance used is
+         * that returned by method {@code defaultJumpDistance()}.
+         */
+        default void jump() { jump(defaultJumpDistance()); }
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link ArbitrarilyJumpableGenerator} interface, produced by jumping copies of this
+         * generator by different integer multiples of the specified jump distance.
+         *
+         * @param distance a distance to jump forward within the state cycle
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @implNote This method is implemented to be equivalent to {@code jumps(Long.MAX_VALUE)}.
+         */
+        default Stream<ArbitrarilyJumpableGenerator> jumps(double distance) {
+            return Stream.generate(() -> copyAndJump(distance)).sequential();
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link ArbitrarilyJumpableGenerator} interface, produced
+         * by jumping copies of this generator by different integer multiples of the specified jump
+         * distance.
+         *
+         * @param streamSize the number of generators to generate
+         * @param distance   a distance to jump forward within the state cycle
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         */
+        default Stream<ArbitrarilyJumpableGenerator> jumps(long streamSize, double distance) {
+            return jumps(distance).limit(streamSize);
+        }
+
+        /**
+         * Alter the state of this pseudorandom number generator so as to jump forward a very large,
+         * fixed distance (typically 2<sup>128</sup> or more) within its state cycle.  The distance used
+         * is that returned by method {@code defaultJLeapDistance()}.
+         */
+        default void leap() { jump(defaultLeapDistance()); }
+
+        /**
+         * Copy this generator, jump this generator forward, then return the copy.
+         *
+         * @param distance a distance to jump forward within the state cycle
+         *
+         * @return a copy of this generator object before the jump occurred
+         */
+        default ArbitrarilyJumpableGenerator copyAndJump(double distance) {
+            ArbitrarilyJumpableGenerator result = copy();
+            jump(distance);
+            return result;
+        }
+
+    }
+}
--- a/src/java.base/share/classes/java/util/random/RandomNumberGenerator.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,639 +0,0 @@
-/*
- * Copyright (c) 2016, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.math.BigInteger;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-
-/**
- * The {@link RandomNumberGenerator} interface is designed to provide a common protocol for objects
- * that generate random or (more typically) pseudorandom sequences of numbers (or Boolean values).
- * Such a sequence may be obtained by either repeatedly invoking a method that returns a single
- * (pseudo)randomly chosen value, or by invoking a method that returns a stream of (pseudo)randomly
- * chosen values.
- * <p>
- * Ideally, given an implicitly or explicitly specified range of values, each value would be chosen
- * independently and uniformly from that range. In practice, one may have to settle for some
- * approximation to independence and uniformity.
- * <p>
- * In the case of {@code int}, {@code long}, and {@link Boolean} values, if there is no explicit
- * specification of range, then the range includes all possible values of the type.  In the case of
- * {@code float} and {@code double} values, a value is always chosen from the set of
- * 2<sup><i>w</i></sup> values between 0.0 (inclusive) and 1.0 (exclusive), where <i>w</i> is 23 for
- * {@code float} values and 52 for {@code double} values, such that adjacent values differ by
- * 2<sup>&minus;<i>w</i></sup>; if an explicit range is specified, then the chosen number is
- * computationally scaled and translated so as to appear to have been chosen from that range.
- * <p>
- * Each method that returns a stream produces a stream of values each of which is chosen in the same
- * manner as for a method that returns a single (pseudo)randomly chosen value.  For example, if
- * {@code r} implements {@link RandomNumberGenerator}, then the method call {@code r.ints(100)}
- * returns a stream of 100 {@code int} values.  These are not necessarily the exact same values that
- * would have been returned if instead {@code r.nextInt()} had been called 100 times; all that is
- * guaranteed is that each value in the stream is chosen in a similar (pseudo)random manner from the
- * same range.
- * <p>
- * Every object that implements the {@link RandomNumberGenerator} interface is assumed to contain a
- * finite amount of state.  Using such an object to generate a pseudorandomly chosen value alters
- * its state.  The number of distinct possible states of such an object is called its
- * <i>period</i>.  (Some implementations of the {@link RandomNumberGenerator} interface
- * may be truly random rather than pseudorandom, for example relying on the statistical behavior of
- * a physical object to derive chosen values.  Such implementations do not have a fixed period.)
- * <p>
- * As a rule, objects that implement the {@link RandomNumberGenerator} interface need not be
- * thread-safe.  It is recommended that multithreaded applications use either {@link
- * ThreadLocalRandom} or (preferably) pseudorandom number generators that implement the {@link
- * SplittableRNG} or {@link JumpableRNG} interface.
- * <p>
- * To implement this interface, a class only needs to provide concrete definitions for the methods
- * {@code nextLong()} and {@code period()}. Default implementations are provided for all other
- * methods (but it may be desirable to override some of them, especially {@code nextInt()} if the
- * underlying algorithm is {@code int}-based). Moerover, it may be preferable instead to implement
- * another interface such as {@link JumpableRNG} or {@link LeapableRNG}, or to extend an abstract
- * class such as {@link AbstractSplittableRNG} or {@link AbstractArbitrarilyJumpableRNG}.
- * <p>
- * Objects that implement {@link RandomNumberGenerator} are typically not cryptographically secure.
- * Consider instead using {@link java.security.SecureRandom} to get a cryptographically secure
- * pseudorandom number generator for use by security-sensitive applications.  Note, however, that
- * {@code java.security.SecureRandom} does implement the {@link RandomNumberGenerator} interface, so
- * that instances of {@code java.security.SecureRandom} may be used interchangeably with other types
- * of pseudorandom generators in applications that do not require a secure generator.
- *
- * @since 14
- */
-public interface RandomNumberGenerator {
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandomly chosen
-     * {@code double} values.
-     *
-     * @return a stream of pseudorandomly chosen {@code double} values
-     *
-     * @implNote It is permitted to implement this method in a manner
-     * equivalent to {@code doubles(Long.MAX_VALUE)}.
-     *
-     * @implNote The default implementation produces a sequential stream
-     * that repeatedly calls {@code nextDouble()}.
-     */
-    default DoubleStream doubles() {
-        return DoubleStream.generate(this::nextDouble).sequential();
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandomly chosen
-     * {@code double} values, where each value is between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param randomNumberOrigin the least value that can be produced
-     * @param randomNumberBound the upper bound (exclusive) for each value produced
-     *
-     * @return a stream of pseudorandomly chosen {@code double} values, each between
-     *         the specified origin (inclusive) and the specified bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     *
-     * @implNote It is permitted to implement this method in a manner
-     *           equivalent to
-     *           {@code doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     * @implNote The default implementation produces a sequential stream that repeatedly
-     *           calls {@code nextDouble(randomNumberOrigin, randomNumberBound)}.
-     */
-    default DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return DoubleStream.generate(() -> nextDouble(randomNumberOrigin, randomNumberBound)).sequential();
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandomly chosen {@code double} values.
-     *
-     * @param streamSize the number of values to generate
-     *
-     * @return a stream of pseudorandomly chosen {@code double} values
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     *
-     * @implNote The default implementation produces a sequential stream
-     * that repeatedly calls {@code nextDouble()}.
-     */
-    default DoubleStream doubles(long streamSize) {
-        RNGSupport.checkStreamSize(streamSize);
-        return doubles().limit(streamSize);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandomly chosen {@code double} values, where each value is between
-     * the specified origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the least value that can be produced
-     * @param randomNumberBound the upper bound (exclusive) for each value produced
-     *
-     * @return a stream of pseudorandomly chosen {@code double} values, each between
-     *         the specified origin (inclusive) and the specified bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     *
-     * @implNote The default implementation produces a sequential stream
-     * that repeatedly calls {@code nextDouble(randomNumberOrigin, randomNumberBound)}.
-     */
-    default DoubleStream doubles(long streamSize, double randomNumberOrigin,
-                          double randomNumberBound) {
-        RNGSupport.checkStreamSize(streamSize);
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return doubles(randomNumberOrigin, randomNumberBound).limit(streamSize);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandomly chosen
-     * {@code int} values.
-     *
-     * @return a stream of pseudorandomly chosen {@code int} values
-     *
-     * @implNote It is permitted to implement this method in a manner
-     * equivalent to {@code ints(Long.MAX_VALUE)}.
-     * @implNote The default implementation produces a sequential stream
-     * that repeatedly calls {@code nextInt()}.
-     */
-    default IntStream ints() {
-        return IntStream.generate(this::nextInt).sequential();
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandomly chosen
-     * {@code int} values, where each value is between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param randomNumberOrigin the least value that can be produced
-     * @param randomNumberBound the upper bound (exclusive) for each value produced
-     *
-     * @return a stream of pseudorandomly chosen {@code int} values, each between
-     *         the specified origin (inclusive) and the specified bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     *
-     * @implNote It is permitted to implement this method in a manner equivalent to
-     *           {@code ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     * @implNote The default implementation produces a sequential stream that repeatedly
-     *           calls {@code nextInt(randomNumberOrigin, randomNumberBound)}.
-     */
-    default IntStream ints(int randomNumberOrigin, int randomNumberBound) {
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return IntStream.generate(() -> nextInt(randomNumberOrigin, randomNumberBound)).sequential();
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandomly chosen {@code int} values.
-     *
-     * @param streamSize the number of values to generate
-     *
-     * @return a stream of pseudorandomly chosen {@code int} values
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     *
-     * @implNote The default implementation produces a sequential stream
-     *           that repeatedly calls {@code nextInt()}.
-     */
-    default IntStream ints(long streamSize) {
-        RNGSupport.checkStreamSize(streamSize);
-        return ints().limit(streamSize);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandomly chosen {@code int} values, where each value is between
-     * the specified origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the least value that can be produced
-     * @param randomNumberBound the upper bound (exclusive) for each value produced
-     *
-     * @return a stream of pseudorandomly chosen {@code int} values, each between
-     *         the specified origin (inclusive) and the specified bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     *
-     * @implNote The default implementation produces a sequential stream that repeatedly
-     *           calls {@code nextInt(randomNumberOrigin, randomNumberBound)}.
-     */
-    default IntStream ints(long streamSize, int randomNumberOrigin,
-                          int randomNumberBound) {
-        RNGSupport.checkStreamSize(streamSize);
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return ints(randomNumberOrigin, randomNumberBound).limit(streamSize);
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandomly chosen
-     * {@code long} values.
-     *
-     * @return a stream of pseudorandomly chosen {@code long} values
-     *
-     * @implNote It is permitted to implement this method in a manner
-     *           equivalent to {@code longs(Long.MAX_VALUE)}.
-     * @implNote The default implementation produces a sequential stream
-     *           that repeatedly calls {@code nextLong()}.
-     */
-    default LongStream longs() {
-        return LongStream.generate(this::nextLong).sequential();
-    }
-
-    /**
-     * Returns an effectively unlimited stream of pseudorandomly chosen
-     * {@code long} values, where each value is between the specified
-     * origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param randomNumberOrigin the least value that can be produced
-     * @param randomNumberBound the upper bound (exclusive) for each value produced
-     *
-     * @return a stream of pseudorandomly chosen {@code long} values, each between
-     *         the specified origin (inclusive) and the specified bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     *
-     * @implNote It is permitted to implement this method in a manner
-     *           equivalent to {@code longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
-     * @implNote The default implementation produces a sequential stream that repeatedly
-     *           calls {@code nextLong(randomNumberOrigin, randomNumberBound)}.
-     */
-    default LongStream longs(long randomNumberOrigin, long randomNumberBound) {
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return LongStream.generate(() -> nextLong(randomNumberOrigin, randomNumberBound)).sequential();
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandomly chosen {@code long} values.
-     *
-     * @param streamSize the number of values to generate
-     *
-     * @return a stream of pseudorandomly chosen {@code long} values
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     *
-     * @implNote The default implementation produces a sequential stream
-     * that repeatedly calls {@code nextLong()}.
-     */
-    default LongStream longs(long streamSize) {
-        RNGSupport.checkStreamSize(streamSize);
-        return longs().limit(streamSize);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * pseudorandomly chosen {@code long} values, where each value is between
-     * the specified origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param streamSize the number of values to generate
-     * @param randomNumberOrigin the least value that can be produced
-     * @param randomNumberBound the upper bound (exclusive) for each value produced
-     *
-     * @return a stream of pseudorandomly chosen {@code long} values, each between
-     *         the specified origin (inclusive) and the specified bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero, or {@code randomNumberOrigin}
-     *         is greater than or equal to {@code randomNumberBound}
-     *
-     * @implNote The default implementation produces a sequential stream that repeatedly
-     *            calls {@code nextLong(randomNumberOrigin, randomNumberBound)}.
-     */
-    default LongStream longs(long streamSize, long randomNumberOrigin,
-                          long randomNumberBound) {
-        RNGSupport.checkStreamSize(streamSize);
-        RNGSupport.checkRange(randomNumberOrigin, randomNumberBound);
-        return longs(randomNumberOrigin, randomNumberBound).limit(streamSize);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code boolean} value.
-     * <p>
-     * The default implementation tests the high-order bit (sign bit) of a value produced by {@code
-     * nextInt()}, on the grounds that some algorithms for pseudorandom number generation produce
-     * values whose high-order bits have better statistical quality than the low-order bits.
-     *
-     * @return a pseudorandomly chosen {@code boolean} value
-     */
-    default boolean nextBoolean() {
-        return nextInt() < 0;
-    }
-
-    /**
-     * Returns a pseudorandom {@code float} value between zero (inclusive) and one (exclusive).
-     * <p>
-     * The default implementation uses the 24 high-order bits from a call to {@code nextInt()}.
-     *
-     * @return a pseudorandom {@code float} value between zero (inclusive) and one (exclusive)
-     */
-    default float nextFloat() {
-        return (nextInt() >>> 8) * 0x1.0p-24f;
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code float} value between zero
-     * (inclusive) and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive) for the returned value.
-     *        Must be positive and finite
-     *
-     * @return a pseudorandomly chosen {@code float} value between
-     *         zero (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not
-     *         positive and finite
-     *
-     * @implNote The default implementation simply calls
-     *     {@code RNGSupport.checkBound(bound)} and then
-     *     {@code RNGSupport.boundedNextFloat(this, bound)}.
-     */
-    default float nextFloat(float bound) {
-        RNGSupport.checkBound(bound);
-        return RNGSupport.boundedNextFloat(this, bound);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code float} value between the
-     * specified origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value that can be returned
-     * @param bound the upper bound (exclusive)
-     *
-     * @return a pseudorandomly chosen {@code float} value between the
-     *         origin (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException unless {@code origin} is finite,
-     *         {@code bound} is finite, and {@code origin} is less than
-     *         {@code bound}
-     *
-     * @implNote The default implementation simply calls
-     *           {@code RNGSupport.checkRange(origin, bound)} and then
-     *          {@code RNGSupport.boundedNextFloat(this, origin, bound)}.
-     */
-    default float nextFloat(float origin, float bound) {
-        RNGSupport.checkRange(origin, bound);
-        return RNGSupport.boundedNextFloat(this, origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandom {@code double} value between zero (inclusive) and one (exclusive).
-     * <p>
-     * The default implementation uses the 53 high-order bits from a call to {@code nextLong()}.
-     *
-     * @return a pseudorandom {@code double} value between zero (inclusive) and one (exclusive)
-     */
-    default double nextDouble() {
-        return (nextLong() >>> 11) * 0x1.0p-53;
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code double} value between zero
-     * (inclusive) and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive) for the returned value.
-     *        Must be positive and finite
-     *
-     * @return a pseudorandomly chosen {@code double} value between
-     *         zero (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not
-     *         positive and finite
-     *
-     * @implNote The default implementation simply calls
-     *           {@code RNGSupport.checkBound(bound)} and then
-     *           {@code RNGSupport.boundedNextDouble(this, bound)}.
-     */
-    default double nextDouble(double bound) {
-        RNGSupport.checkBound(bound);
-        return RNGSupport.boundedNextDouble(this, bound);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code double} value between the
-     * specified origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value that can be returned
-     * @param bound the upper bound (exclusive) for the returned value
-     *
-     * @return a pseudorandomly chosen {@code double} value between the
-     *         origin (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException unless {@code origin} is finite,
-     *         {@code bound} is finite, and {@code origin} is less than
-     *         {@code bound}
-     *
-     * @implNote The default implementation simply calls
-     *           {@code RNGSupport.checkRange(origin, bound)} and then
-     *           {@code RNGSupport.boundedNextDouble(this, origin, bound)}.
-     */
-    default double nextDouble(double origin, double bound) {
-        RNGSupport.checkRange(origin, bound);
-        return RNGSupport.boundedNextDouble(this, origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code int} value.
-     * <p>
-     * The default implementation uses the 32 high-order bits from a call to {@code nextLong()}.
-     *
-     * @return a pseudorandomly chosen {@code int} value
-     */
-    default public int nextInt() {
-        return (int)(nextLong() >>> 32);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code int} value between
-     * zero (inclusive) and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive) for the returned value. Must be positive.
-     *
-     * @return a pseudorandomly chosen {@code int} value between
-     *         zero (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     *
-     * @implNote The default implementation simply calls
-     *           {@code RNGSupport.checkBound(bound)} and then
-     *           {@code RNGSupport.boundedNextInt(this, bound)}.
-     */
-    default int nextInt(int bound) {
-        RNGSupport.checkBound(bound);
-        return RNGSupport.boundedNextInt(this, bound);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code int} value between the
-     * specified origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value that can be returned
-     * @param bound the upper bound (exclusive) for the returned value
-     *
-     * @return a pseudorandomly chosen {@code int} value between the
-     *         origin (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     *
-     * @implNote The default implementation simply calls
-     *           {@code RNGSupport.checkRange(origin, bound)} and then
-     *           {@code RNGSupport.boundedNextInt(this, origin, bound)}.
-     */
-    default int nextInt(int origin, int bound) {
-        RNGSupport.checkRange(origin, bound);
-        return RNGSupport.boundedNextInt(this, origin, bound);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code long} value.
-     *
-     * @return a pseudorandomly chosen {@code long} value
-     */
-    long nextLong();
-
-    /**
-     * Returns a pseudorandomly chosen {@code long} value between
-     * zero (inclusive) and the specified bound (exclusive).
-     *
-     * @param bound the upper bound (exclusive) for the returned value.  Must be positive.
-     *
-     * @return a pseudorandomly chosen {@code long} value between
-     *         zero (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code bound} is not positive
-     *
-     * @implNote The default implementation simply calls
-     *           {@code RNGSupport.checkBound(bound)} and then
-     *           {@code RNGSupport.boundedNextLong(this, bound)}.
-     */
-    default long nextLong(long bound) {
-        RNGSupport.checkBound(bound);
-        return RNGSupport.boundedNextLong(this, bound);
-    }
-
-    /**
-     * Returns a pseudorandomly chosen {@code long} value between the
-     * specified origin (inclusive) and the specified bound (exclusive).
-     *
-     * @param origin the least value that can be returned
-     * @param bound the upper bound (exclusive) for the returned value
-     *
-     * @return a pseudorandomly chosen {@code long} value between the
-     *         origin (inclusive) and the bound (exclusive)
-     *
-     * @throws IllegalArgumentException if {@code origin} is greater than
-     *         or equal to {@code bound}
-     *
-     * @implNote The default implementation simply calls
-     *           {@code RNGSupport.checkRange(origin, bound)} and then
-     *           {@code RNGSupport.boundedNextInt(this, origin, bound)}.
-     *
-     */
-    default long nextLong(long origin, long bound) {
-        RNGSupport.checkRange(origin, bound);
-        return RNGSupport.boundedNextLong(this, origin, bound);
-    }
-
-    /**
-     * Returns a {@code double} value pseudorandomly chosen from
-     * a Gaussian (normal) distribution whose mean is 0 and whose
-     * standard deviation is 1.
-     *
-     * @return a {@code double} value pseudorandomly chosen from a
-     *         Gaussian distribution
-     */
-    default double nextGaussian() {
-        return RNGSupport.computeNextGaussian(this);
-    }
-
-    /**
-     * Returns a {@code double} value pseudorandomly chosen from
-     * a Gaussian (normal) distribution with a mean and
-     * standard deviation specified by the arguments.
-     *
-     * @param mean the mean of the Gaussian distribution to be drawn from
-     * @param stddev the standard deviation (square root of the variance)
-     *        of the Gaussian distribution to be drawn from
-     *
-     * @return a {@code double} value pseudorandomly chosen from the
-     *         specified Gaussian distribution
-     *
-     * @throws IllegalArgumentException if {@code stddev} is negative
-     */
-    default double nextGaussian(double mean, double stddev) {
-        if (stddev < 0.0) throw new IllegalArgumentException("standard deviation must be non-negative");
-        return mean + stddev * RNGSupport.computeNextGaussian(this);
-    }
-
-    /**
-     * Returns a nonnegative {@code double} value pseudorandomly chosen
-     * from an exponential distribution whose mean is 1.
-     *
-     * @return a nonnegative {@code double} value pseudorandomly chosen from an
-     *         exponential distribution
-     */
-    default double nextExponential() {
-        return RNGSupport.computeNextExponential(this);
-    }
-
-    /**
-     * Returns the period of this {@link RandomNumberGenerator} object.
-     *
-     * @return a {@link BigInteger} whose value is the number of distinct possible states of this
-     *         {@link RandomNumberGenerator} object, or 0 if unknown, or negative if extremely
-     *         large.
-     */
-    BigInteger period();
-
-    /**
-     * The value (0) returned by the {@code period()} method if the period is unknown.
-     */
-    static final BigInteger UNKNOWN_PERIOD = BigInteger.ZERO;
-
-    /**
-     * The (negative) value returned by the {@code period()} method if this generator
-     * has no period because it is truly random rather than just pseudorandom.
-     */
-    static final BigInteger TRULY_RANDOM = BigInteger.valueOf(-1);
-
-    /**
-     * The (negative) value that may be returned by the {@code period()} method
-     * if this generator has a huge period (larger than 2**(2**16)).
-     */
-    static final BigInteger HUGE_PERIOD = BigInteger.valueOf(-2);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/util/random/RandomSupport.java	Fri Jul 26 15:37:05 2019 -0300
@@ -0,0 +1,2247 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.random;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+import java.util.random.RandomGenerator.SplittableGenerator;
+import java.util.Spliterator;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+/**
+ * Low-level utility methods helpful for implementing pseudorandom number generators.
+ *
+ * This class is mostly for library writers creating specific implementations of the
+ * interface {@link RandomGenerator}.
+ *
+ * @since 14
+ */
+public class RandomSupport {
+
+    /*
+     * Implementation Overview.
+     *
+     * This class provides utility methods and constants frequently
+     * useful in the implentation of pseudorandom number generators
+     * that satisfy the interface {@link RandomGenerator}.
+     *
+     * File organization: First some message strings, then the main
+     * public methods, followed by a non-public base spliterator class.
+     */
+
+    // IllegalArgumentException messages
+    static final String BAD_SIZE = "size must be non-negative";
+    static final String BAD_DISTANCE = "jump distance must be finite, positive, and an exact integer";
+    static final String BAD_BOUND = "bound must be positive";
+    static final String BAD_FLOATING_BOUND = "bound must be finite and positive";
+    static final String BAD_RANGE = "bound must be greater than origin";
+
+    /* ---------------- public methods ---------------- */
+
+    /**
+     * Check a {@code long} proposed stream size for validity.
+     *
+     * @param streamSize the proposed stream size
+     *
+     * @throws IllegalArgumentException if {@code streamSize} is negative
+     */
+    public static void checkStreamSize(long streamSize) {
+        if (streamSize < 0L)
+            throw new IllegalArgumentException(BAD_SIZE);
+    }
+
+    /**
+     * Check a {@code double} proposed jump distance for validity.
+     *
+     * @param distance the proposed jump distance
+     *
+     * @throws IllegalArgumentException if {@code size} not positive, finite, and an exact integer
+     */
+    public static void checkJumpDistance(double distance) {
+        if (!(distance > 0.0 && distance < Float.POSITIVE_INFINITY
+                             && distance == Math.floor(distance))) {
+            throw new IllegalArgumentException(BAD_DISTANCE);
+        }
+    }
+
+    /**
+     * Checks a {@code float} upper bound value for validity.
+     *
+     * @param bound the upper bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not positive and finite
+     */
+    public static void checkBound(float bound) {
+        if (!(bound > 0.0 && bound < Float.POSITIVE_INFINITY)) {
+            throw new IllegalArgumentException(BAD_FLOATING_BOUND);
+        }
+    }
+
+    /**
+     * Checks a {@code double} upper bound value for validity.
+     *
+     * @param bound the upper bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not positive and finite
+     */
+    public static void checkBound(double bound) {
+        if (!(bound > 0.0 && bound < Double.POSITIVE_INFINITY)) {
+            throw new IllegalArgumentException(BAD_FLOATING_BOUND);
+        }
+    }
+
+    /**
+     * Checks an {@code int} upper bound value for validity.
+     *
+     * @param bound the upper bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not positive
+     */
+    public static void checkBound(int bound) {
+        if (bound <= 0) {
+            throw new IllegalArgumentException(BAD_BOUND);
+        }
+    }
+
+    /**
+     * Checks a {@code long} upper bound value for validity.
+     *
+     * @param bound the upper bound (exclusive)
+     *
+     * @throws IllegalArgumentException if {@code bound} is not positive
+     */
+    public static void checkBound(long bound) {
+        if (bound <= 0) {
+            throw new IllegalArgumentException(BAD_BOUND);
+        }
+    }
+
+    /**
+     * Checks a {@code float} range for validity.
+     *
+     * @param origin the least value (inclusive) in the range
+     * @param bound  the upper bound (exclusive) of the range
+     *
+     * @throws IllegalArgumentException unless {@code origin} is finite, {@code bound} is finite,
+     *                                  and {@code bound - origin} is finite
+     */
+    public static void checkRange(float origin, float bound) {
+        if (!(origin < bound && (bound - origin) < Float.POSITIVE_INFINITY)) {
+            throw new IllegalArgumentException(BAD_RANGE);
+        }
+    }
+
+    /**
+     * Checks a {@code double} range for validity.
+     *
+     * @param origin the least value (inclusive) in the range
+     * @param bound  the upper bound (exclusive) of the range
+     *
+     * @throws IllegalArgumentException unless {@code origin} is finite, {@code bound} is finite,
+     *                                  and {@code bound - origin} is finite
+     */
+    public static void checkRange(double origin, double bound) {
+        if (!(origin < bound && (bound - origin) < Double.POSITIVE_INFINITY)) {
+            throw new IllegalArgumentException(BAD_RANGE);
+        }
+    }
+
+    /**
+     * Checks an {@code int} range for validity.
+     *
+     * @param origin the least value that can be returned
+     * @param bound  the upper bound (exclusive) for the returned value
+     *
+     * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound}
+     */
+    public static void checkRange(int origin, int bound) {
+        if (origin >= bound) {
+            throw new IllegalArgumentException(BAD_RANGE);
+        }
+    }
+
+    /**
+     * Checks a {@code long} range for validity.
+     *
+     * @param origin the least value that can be returned
+     * @param bound  the upper bound (exclusive) for the returned value
+     *
+     * @throws IllegalArgumentException if {@code origin} is greater than or equal to {@code bound}
+     */
+    public static void checkRange(long origin, long bound) {
+        if (origin >= bound) {
+            throw new IllegalArgumentException(BAD_RANGE);
+        }
+    }
+
+    /**
+     * Given an array of seed bytes of any length, construct an array
+     * of {@code long} seed values of length {@code n}, such that the
+     * last {@code z} values are not all zero.
+     *
+     * @param seed an array of {@code byte} values
+     * @param n the length of the result array (should be nonnegative)
+     * @param z the number of trailing result elements that are required
+     *        to be not all zero (should be nonnegative but not larger
+     *        than {@code n})
+     *
+     * @return an array of length {@code n} containing {@code long} seed values
+     */
+    public static long[] convertSeedBytesToLongs(byte[] seed, int n, int z) {
+        final long[] result = new long[n];
+        final int m = Math.min(seed.length, n << 3);
+        // Distribute seed bytes into the words to be formed.
+        for (int j = 0; j < m; j++) {
+            result[j>>3] = (result[j>>3] << 8) | seed[j];
+        }
+        // If there aren't enough seed bytes for all the words we need,
+        // use a SplitMix-style PRNG to fill in the rest.
+        long v = result[0];
+        for (int j = (m + 7) >> 3; j < n; j++) {
+            result[j] = mixMurmur64(v += SILVER_RATIO_64);
+        }
+        // Finally, we need to make sure the last z words are not all zero.
+        search: {
+            for (int j = n - z; j < n; j++) {
+                if (result[j] != 0) break search;
+            }
+            // If they are, fill in using a SplitMix-style PRNG.
+            // Using "& ~1L" in the next line defends against the case z==1
+            // by guaranteeing that the first generated value will be nonzero.
+            long w = result[0] & ~1L;
+            for (int j = n - z; j < n; j++) {
+                result[j] = mixMurmur64(w += SILVER_RATIO_64);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Given an array of seed bytes of any length, construct an array
+     * of {@code int} seed values of length {@code n}, such that the
+     * last {@code z} values are not all zero.
+     *
+     * @param seed an array of {@code byte} values
+     * @param n the length of the result array (should be nonnegative)
+     * @param z the number of trailing result elements that are required
+     *        to be not all zero (should be nonnegative but not larger
+     *        than {@code n})
+     *
+     * @return an array of length {@code n} containing {@code int} seed values
+     */
+    public static int[] convertSeedBytesToInts(byte[] seed, int n, int z) {
+        final int[] result = new int[n];
+        final int m = Math.min(seed.length, n << 2);
+        // Distribute seed bytes into the words to be formed.
+        for (int j = 0; j < m; j++) {
+            result[j>>2] = (result[j>>2] << 8) | seed[j];
+        }
+        // If there aren't enough seed bytes for all the words we need,
+        // use a SplitMix-style PRNG to fill in the rest.
+        int v = result[0];
+        for (int j = (m + 3) >> 2; j < n; j++) {
+            result[j] = mixMurmur32(v += SILVER_RATIO_32);
+        }
+        // Finally, we need to make sure the last z words are not all zero.
+        search: {
+            for (int j = n - z; j < n; j++) {
+                if (result[j] != 0) break search;
+            }
+            // If they are, fill in using a SplitMix-style PRNG.
+            // Using "& ~1" in the next line defends against the case z==1
+            // by guaranteeing that the first generated value will be nonzero.
+            int w = result[0] & ~1;
+            for (int j = n - z; j < n; j++) {
+                result[j] = mixMurmur32(w += SILVER_RATIO_32);
+            }
+        }
+        return result;
+    }
+
+    /*
+     * Bounded 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.
+     */
+
+    /**
+     * This is the form of {@code nextLong} used by a {@link LongStream}
+     * {@link Spliterator} and by the public method
+     * {@code nextLong(origin, bound)}.  If {@code origin} is greater
+     * than {@code bound}, then this method simply calls the unbounded
+     * version of {@code nextLong()}, choosing pseudorandomly from
+     * among all 2<sup>64</sup> possible {@code long} values}, and
+     * otherwise uses one or more calls to {@code nextLong()} to
+     * choose a value pseudorandomly from the possible values
+     * between {@code origin} (inclusive) and {@code bound} (exclusive).
+     *
+     * @implNote This method first calls {@code nextLong()} to obtain
+     * a {@code long} value that is assumed to be pseudorandomly
+     * chosen uniformly and independently from the 2<sup>64</sup>
+     * possible {@code long} values (that is, each of the 2<sup>64</sup>
+     * possible long values is equally likely to be chosen).
+     * Under some circumstances (when the specified range is not
+     * a power of 2), {@code nextLong()} may be called additional times
+     * to ensure that that the values in the specified range are
+     * equally likely to be chosen (provided the assumption holds).
+     * <p>
+     * The implementation considers four cases:
+     * <ol>
+     *
+     * <li> If the {@code} bound} is less than or equal to the {@code origin}
+     *      (indicated an unbounded form), the 64-bit {@code long} value
+     *      obtained from {@code nextLong()} is returned directly.
+     *
+     * <li> Otherwise, if the length <i>n</i> of the specified range is an
+     *      exact power of two 2<sup><i>m</i></sup> for some integer
+     *      <i>m</i>, then return the sum of {@code origin} and the
+     *      <i>m</i> lowest-order bits of the value from {@code nextLong()}.
+     *
+     * <li> Otherwise, if the length <i>n</i> of the specified range
+     *      is less than 2<sup>63</sup>, then the basic idea is to use the
+     *      remainder modulo <i>n</i> of the value from {@code nextLong()},
+     *      but with this approach some values will be over-represented.
+     *      Therefore a loop is used to avoid potential bias by rejecting
+     *      candidates that are too large.  Assuming that the results from
+     *      {@code nextLong()} are truly chosen uniformly and independently,
+     *      the expected number of iterations will be somewhere between
+     *      1 and 2, depending on the precise value of <i>n</i>.
+     *
+     * <li> Otherwise, the length <i>n</i> of the specified range
+     *      cannot be represented as a positive {@code long} value.
+     *      A loop repeatedly calls {@code nextlong()} until obtaining
+     *      a suitable candidate,  Again, the expected number of iterations
+     *      is less than 2.
+     *
+     * </ol>
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code long} values
+     * @param origin the least value that can be produced,
+     *        unless greater than or equal to {@code bound}
+     * @param bound the upper bound (exclusive), unless {@code origin}
+     *        is greater than or equal to {@code bound}
+     *
+     * @return a pseudorandomly chosen {@code long} value,
+     *         which will be between {@code origin} (inclusive) and
+     *         {@code bound} exclusive unless {@code origin}
+     *         is greater than or equal to {@code bound}
+     */
+    public static long boundedNextLong(RandomGenerator rng, long origin, long bound) {
+        long r = rng.nextLong();
+        if (origin < bound) {
+            // It's not case (1).
+            final long n = bound - origin;
+            final long m = n - 1;
+            if ((n & m) == 0L) {
+                // It is case (2): length of range is a power of 2.
+                r = (r & m) + origin;
+            } else if (n > 0L) {
+                // It is case (3): need to reject over-represented candidates.
+                /* This loop takes an unlovable form (but it works):
+                   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. */
+                for (long u = r >>> 1;            // ensure nonnegative
+                     u + m - (r = u % n) < 0L;    // rejection check
+                     u = rng.nextLong() >>> 1) // retry
+                    ;
+                r += origin;
+            }
+            else {
+                // It is case (4): length of range not representable as long.
+                while (r < origin || r >= bound)
+                    r = rng.nextLong();
+            }
+        }
+        return r;
+    }
+
+    /**
+     * This is the form of {@code nextLong} used by the public method
+     * {@code nextLong(bound)}.  This is essentially a version of
+     * {@code boundedNextLong(origin, bound)} that has been
+     * specialized for the case where the {@code origin} is zero
+     * and the {@code bound} is greater than zero.  The value
+     * returned is chosen pseudorandomly from nonnegative integer
+     * values less than {@code bound}.
+     *
+     * @implNote This method first calls {@code nextLong()} to obtain
+     * a {@code long} value that is assumed to be pseudorandomly
+     * chosen uniformly and independently from the 2<sup>64</sup>
+     * possible {@code long} values (that is, each of the 2<sup>64</sup>
+     * possible long values is equally likely to be chosen).
+     * Under some circumstances (when the specified range is not
+     * a power of 2), {@code nextLong()} may be called additional times
+     * to ensure that that the values in the specified range are
+     * equally likely to be chosen (provided the assumption holds).
+     * <p>
+     * The implementation considers two cases:
+     * <ol>
+     *
+     * <li> If {@code bound} is an exact power of two 2<sup><i>m</i></sup>
+     *      for some integer <i>m</i>, then return the sum of {@code origin}
+     *      and the <i>m</i> lowest-order bits of the value from
+     *      {@code nextLong()}.
+     *
+     * <li> Otherwise, the basic idea is to use the remainder modulo
+     *      <i>bound</i> of the value from {@code nextLong()},
+     *      but with this approach some values will be over-represented.
+     *      Therefore a loop is used to avoid potential bias by rejecting
+     *      candidates that vare too large.  Assuming that the results from
+     *      {@code nextLong()} are truly chosen uniformly and independently,
+     *      the expected number of iterations will be somewhere between
+     *      1 and 2, depending on the precise value of <i>bound</i>.
+     *
+     * </ol>
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code long} values
+     * @param bound the upper bound (exclusive); must be greater than zero
+     *
+     * @return a pseudorandomly chosen {@code long} value
+     */
+    public static long boundedNextLong(RandomGenerator rng, long bound) {
+        // Specialize boundedNextLong for origin == 0, bound > 0
+        final long m = bound - 1;
+        long r = rng.nextLong();
+        if ((bound & m) == 0L) {
+            // The bound is a power of 2.
+            r &= m;
+        } else {
+            // Must reject over-represented candidates
+            /* This loop takes an unlovable form (but it works):
+               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. */
+            for (long u = r >>> 1;
+                 u + m - (r = u % bound) < 0L;
+                 u = rng.nextLong() >>> 1)
+                ;
+        }
+        return r;
+    }
+
+    /**
+     * This is the form of {@code nextInt} used by an {@link IntStream}
+     * {@link Spliterator} and by the public method
+     * {@code nextInt(origin, bound)}.  If {@code origin} is greater
+     * than {@code bound}, then this method simply calls the unbounded
+     * version of {@code nextInt()}, choosing pseudorandomly from
+     * among all 2<sup>64</sup> possible {@code int} values}, and
+     * otherwise uses one or more calls to {@code nextInt()} to
+     * choose a value pseudorandomly from the possible values
+     * between {@code origin} (inclusive) and {@code bound} (exclusive).
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code int} values
+     * @param origin the least value that can be produced,
+     *        unless greater than or equal to {@code bound}
+     * @param bound the upper bound (exclusive), unless {@code origin}
+     *        is greater than or equal to {@code bound}
+     *
+     * @return a pseudorandomly chosen {@code int} value,
+     *         which will be between {@code origin} (inclusive) and
+     *         {@code bound} exclusive unless {@code origin}
+     *         is greater than or equal to {@code bound}
+     *
+     * @implNote The implementation of this method is identical to
+     *           the implementation of {@code nextLong(origin, bound)}
+     *           except that {@code int} values and the {@code nextInt()}
+     *           method are used rather than {@code long} values and the
+     *           {@code nextLong()} method.
+     */
+    public static int boundedNextInt(RandomGenerator rng, int origin, int bound) {
+        int r = rng.nextInt();
+        if (origin < bound) {
+            // It's not case (1).
+            final int n = bound - origin;
+            final int m = n - 1;
+            if ((n & m) == 0) {
+                // It is case (2): length of range is a power of 2.
+                r = (r & m) + origin;
+            } else if (n > 0) {
+                // It is case (3): need to reject over-represented candidates.
+                for (int u = r >>> 1;
+                     u + m - (r = u % n) < 0;
+                     u = rng.nextInt() >>> 1)
+                    ;
+                r += origin;
+            }
+            else {
+                // It is case (4): length of range not representable as long.
+                while (r < origin || r >= bound) {
+                    r = rng.nextInt();
+                }
+            }
+        }
+        return r;
+    }
+
+    /**
+     * This is the form of {@code nextInt} used by the public method
+     * {@code nextInt(bound)}.  This is essentially a version of
+     * {@code boundedNextInt(origin, bound)} that has been
+     * specialized for the case where the {@code origin} is zero
+     * and the {@code bound} is greater than zero.  The value
+     * returned is chosen pseudorandomly from nonnegative integer
+     * values less than {@code bound}.
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code long} values
+     * @param bound the upper bound (exclusive); must be greater than zero
+     *
+     * @return a pseudorandomly chosen {@code long} value
+     *
+     * @implNote The implementation of this method is identical to
+     *           the implementation of {@code nextLong(bound)}
+     *           except that {@code int} values and the {@code nextInt()}
+     *           method are used rather than {@code long} values and the
+     *           {@code nextLong()} method.
+     */
+    public static int boundedNextInt(RandomGenerator rng, int bound) {
+        // Specialize boundedNextInt for origin == 0, bound > 0
+        final int m = bound - 1;
+        int r = rng.nextInt();
+        if ((bound & m) == 0) {
+            // The bound is a power of 2.
+            r &= m;
+        } else {
+            // Must reject over-represented candidates
+            for (int u = r >>> 1;
+                 u + m - (r = u % bound) < 0;
+                 u = rng.nextInt() >>> 1)
+                ;
+        }
+        return r;
+    }
+
+    /**
+     * This is the form of {@code nextDouble} used by a {@link DoubleStream}
+     * {@link Spliterator} and by the public method
+     * {@code nextDouble(origin, bound)}.  If {@code origin} is greater
+     * than {@code bound}, then this method simply calls the unbounded
+     * version of {@code nextDouble()}, and otherwise scales and translates
+     * the result of a call to {@code nextDouble()} so that it lies
+     * between {@code origin} (inclusive) and {@code bound} (exclusive).
+     *
+     * @implNote The implementation considers two cases:
+     * <ol>
+     *
+     * <li> If the {@code bound} is less than or equal to the {@code origin}
+     *      (indicated an unbounded form), the 64-bit {@code double} value
+     *      obtained from {@code nextDouble()} is returned directly.
+     *
+     * <li> Otherwise, the result of a call to {@code nextDouble} is
+     *      multiplied by {@code (bound - origin)}, then {@code origin}
+     *      is added, and then if this this result is not less than
+     *      {@code bound} (which can sometimes occur because of rounding),
+     *      it is replaced with the largest {@code double} value that
+     *      is less than {@code bound}.
+     *
+     * </ol>
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code double} values
+     * @param origin the least value that can be produced,
+     *        unless greater than or equal to {@code bound}; must be finite
+     * @param bound the upper bound (exclusive), unless {@code origin}
+     *        is greater than or equal to {@code bound}; must be finite
+     * @return a pseudorandomly chosen {@code double} value,
+     *         which will be between {@code origin} (inclusive) and
+     *         {@code bound} exclusive unless {@code origin}
+     *         is greater than or equal to {@code bound},
+     *         in which case it will be between 0.0 (inclusive)
+     *         and 1.0 (exclusive)
+     */
+    public static double boundedNextDouble(RandomGenerator rng, double origin, double bound) {
+        double r = rng.nextDouble();
+        if (origin < bound) {
+            r = r * (bound - origin) + origin;
+            if (r >= bound)  // may need to correct a rounding problem
+                r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
+        }
+        return r;
+    }
+
+    /**
+     * This is the form of {@code nextDouble} used by the public method
+     * {@code nextDouble(bound)}.  This is essentially a version of
+     * {@code boundedNextDouble(origin, bound)} that has been
+     * specialized for the case where the {@code origin} is zero
+     * and the {@code bound} is greater than zero.
+     *
+     * @implNote The result of a call to {@code nextDouble} is
+     *      multiplied by {@code bound}, and then if this result is
+     *      not less than {@code bound} (which can sometimes occur
+     *      because of rounding), it is replaced with the largest
+     *      {@code double} value that is less than {@code bound}.
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code double} values
+     * @param bound the upper bound (exclusive); must be finite and
+     *        greater than zero
+     * @return a pseudorandomly chosen {@code double} value
+     *         between zero (inclusive) and {@code bound} (exclusive)
+     */
+    public static double boundedNextDouble(RandomGenerator rng, double bound) {
+        // Specialize boundedNextDouble for origin == 0, bound > 0
+        double r = rng.nextDouble();
+        r = r * bound;
+        if (r >= bound)  // may need to correct a rounding problem
+            r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
+        return r;
+    }
+
+    /**
+     * This is the form of {@code nextFloat} used by a {@code Stream<Float>}
+     * {@link Spliterator} (if there were any) and by the public method
+     * {@code nextFloat(origin, bound)}.  If {@code origin} is greater
+     * than {@code bound}, then this method simply calls the unbounded
+     * version of {@code nextFloat()}, and otherwise scales and translates
+     * the result of a call to {@code nextFloat()} so that it lies
+     * between {@code origin} (inclusive) and {@code bound} (exclusive).
+     *
+     * @implNote The implementation of this method is identical to
+     *     the implementation of {@code nextDouble(origin, bound)}
+     *     except that {@code float} values and the {@code nextFloat()}
+     *     method are used rather than {@code double} values and the
+     *     {@code nextDouble()} method.
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code float} values
+     * @param origin the least value that can be produced,
+     *        unless greater than or equal to {@code bound}; must be finite
+     * @param bound the upper bound (exclusive), unless {@code origin}
+     *        is greater than or equal to {@code bound}; must be finite
+     * @return a pseudorandomly chosen {@code float} value,
+     *         which will be between {@code origin} (inclusive) and
+     *         {@code bound} exclusive unless {@code origin}
+     *         is greater than or equal to {@code bound},
+     *         in which case it will be between 0.0 (inclusive)
+     *         and 1.0 (exclusive)
+     */
+    public static float boundedNextFloat(RandomGenerator rng, float origin, float bound) {
+        float r = rng.nextFloat();
+        if (origin < bound) {
+            r = r * (bound - origin) + origin;
+            if (r >= bound) // may need to correct a rounding problem
+                r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);
+        }
+        return r;
+    }
+
+    /**
+     * This is the form of {@code nextFloat} used by the public method
+     * {@code nextFloat(bound)}.  This is essentially a version of
+     * {@code boundedNextFloat(origin, bound)} that has been
+     * specialized for the case where the {@code origin} is zero
+     * and the {@code bound} is greater than zero.
+     *
+     * @implNote The implementation of this method is identical to
+     *     the implementation of {@code nextDouble(bound)}
+     *     except that {@code float} values and the {@code nextFloat()}
+     *     method are used rather than {@code double} values and the
+     *     {@code nextDouble()} method.
+     *
+     * @param rng a random number generator to be used as a
+     *        source of pseudorandom {@code float} values
+     * @param bound the upper bound (exclusive); must be finite and
+     *        greater than zero
+     * @return a pseudorandomly chosen {@code float} value
+     *         between zero (inclusive) and {@code bound} (exclusive)
+     */
+    public static float boundedNextFloat(RandomGenerator rng, float bound) {
+        // Specialize boundedNextFloat for origin == 0, bound > 0
+        float r = rng.nextFloat();
+        r = r * bound;
+        if (r >= bound) // may need to correct a rounding problem
+            r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);
+        return r;
+    }
+
+    // The following decides which of two strategies initialSeed() will use.
+    private static boolean secureRandomSeedRequested() {
+        String pp = java.security.AccessController.doPrivileged(
+                new sun.security.action.GetPropertyAction(
+                        "java.util.secureRandomSeed"));
+        return (pp != null && pp.equalsIgnoreCase("true"));
+    }
+
+    private static final boolean useSecureRandomSeed = secureRandomSeedRequested();
+
+    /**
+     * Returns a {@code long} value (chosen from some
+     * machine-dependent entropy source) that may be useful for
+     * initializing a source of seed values for instances of {@link RandomGenerator}
+     * created by zero-argument constructors.  (This method should
+     * <i>not</i> be called repeatedly, once per constructed
+     * object; at most it should be called once per class.)
+     *
+     * @return a {@code long} value, randomly chosen using
+     *         appropriate environmental entropy
+     */
+    public static long initialSeed() {
+        if (useSecureRandomSeed) {
+            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);
+            return s;
+        }
+        return (mixStafford13(System.currentTimeMillis()) ^
+                mixStafford13(System.nanoTime()));
+    }
+
+    /**
+     * The first 32 bits of the golden ratio (1+sqrt(5))/2, forced to be odd.
+     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
+     */
+    public static final int  GOLDEN_RATIO_32 = 0x9e3779b9;
+
+    /**
+     * The first 64 bits of the golden ratio (1+sqrt(5))/2, forced to be odd.
+     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
+     */
+    public static final long GOLDEN_RATIO_64 = 0x9e3779b97f4a7c15L;
+
+    /**
+     * The first 32 bits of the silver ratio 1+sqrt(2), forced to be odd.
+     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
+     */
+    public static final int  SILVER_RATIO_32 = 0x6A09E667;
+
+    /**
+     * The first 64 bits of the silver ratio 1+sqrt(2), forced to be odd.
+     * Useful for producing good Weyl sequences or as an arbitrary nonzero odd value.
+     */
+    public static final long SILVER_RATIO_64 = 0x6A09E667F3BCC909L;
+
+    /**
+     * Computes the 64-bit mixing function for MurmurHash3.
+     * This is a 64-bit hashing function with excellent avalanche statistics.
+     * https://github.com/aappleby/smhasher/wiki/MurmurHash3
+     *
+     * Note that if the argument {@code z} is 0, the result is 0.
+     *
+     * @param z any long value
+     *
+     * @return the result of hashing z
+     */
+    public static long mixMurmur64(long z) {
+        z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
+        z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
+        return z ^ (z >>> 33);
+    }
+
+    /**
+     * Computes Stafford variant 13 of the 64-bit mixing function for MurmurHash3.
+     * This is a 64-bit hashing function with excellent avalanche statistics.
+     * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
+     *
+     * Note that if the argument {@code z} is 0, the result is 0.
+     *
+     * @param z any long value
+     *
+     * @return the result of hashing z
+     */
+    public static long mixStafford13(long z) {
+        z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
+        z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
+        return z ^ (z >>> 31);
+    }
+
+    /**
+     * Computes Doug Lea's 64-bit mixing function.
+     * This is a 64-bit hashing function with excellent avalanche statistics.
+     * It has the advantages of using the same multiplicative constant twice
+     * and of using only 32-bit shifts.
+     *
+     * Note that if the argument {@code z} is 0, the result is 0.
+     *
+     * @param z any long value
+     *
+     * @return the result of hashing z
+     */
+    public static long mixLea64(long z) {
+        z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L;
+        z = (z ^ (z >>> 32)) * 0xdaba0b6eb09322e3L;
+        return z ^ (z >>> 32);
+    }
+
+    /**
+     * Computes the 32-bit mixing function for MurmurHash3.
+     * This is a 32-bit hashing function with excellent avalanche statistics.
+     * https://github.com/aappleby/smhasher/wiki/MurmurHash3
+     *
+     * Note that if the argument {@code z} is 0, the result is 0.
+     *
+     * @param z any long value
+     *
+     * @return the result of hashing z
+     */
+    public static int mixMurmur32(int z) {
+        z = (z ^ (z >>> 16)) * 0x85ebca6b;
+        z = (z ^ (z >>> 13)) * 0xc2b2ae35;
+        return z ^ (z >>> 16);
+    }
+
+    /**
+     * Computes Doug Lea's 32-bit mixing function.
+     * This is a 32-bit hashing function with excellent avalanche statistics.
+     * It has the advantages of using the same multiplicative constant twice
+     * and of using only 16-bit shifts.
+     *
+     * Note that if the argument {@code z} is 0, the result is 0.
+     *
+     * @param z any long value
+     *
+     * @return the result of hashing z
+     */
+    public static int mixLea32(int z) {
+        z = (z ^ (z >>> 16)) * 0xd36d884b;
+        z = (z ^ (z >>> 16)) * 0xd36d884b;
+        return z ^ (z >>> 16);
+    }
+
+    // Non-public (package only) support for spliterators needed by AbstractSplittableGenerator
+    // and AbstractArbitrarilyJumpableGenerator and AbstractSharedGenerator
+
+    /**
+     * Base class for making Spliterator classes for streams of randomly chosen values.
+     */
+    public abstract static class RandomSpliterator {
+
+        /** low range value */
+        public long index;
+
+        /** high range value */
+        public final long fence;
+
+        /**
+         * Constructor
+         *
+         * @param index  low range value
+         * @param fence  high range value
+         */
+        public RandomSpliterator(long index, long fence) {
+            this.index = index; this.fence = fence;
+        }
+
+        /**
+         * Returns estimated size.
+         *
+         * @return estimated size
+         */
+        public long estimateSize() {
+            return fence - index;
+        }
+
+        /**
+         * Returns characteristics.
+         *
+         * @return characteristics
+         */
+        public int characteristics() {
+            return (Spliterator.SIZED | Spliterator.SUBSIZED |
+                    Spliterator.NONNULL | Spliterator.IMMUTABLE);
+        }
+    }
+
+
+    /*
+     * Implementation support for nextExponential() and nextGaussian() methods of RandomGenerator.
+     *
+     * Each is implemented using McFarland's fast modified ziggurat algorithm (largely
+     * table-driven, with rare cases handled by computation and rejection sampling).
+     * Walker's alias method for sampling a discrete distribution also plays a role.
+     *
+     * The tables themselves, as well as a number of associated parameters, are defined
+     * in class java.util.DoubleZigguratTables, which is automatically generated by the
+     * program create_ziggurat_tables.c (which takes only a few seconds to run).
+     *
+     * For more information about the algorithms, see these articles:
+     *
+     * Christopher D. McFarland.  2016 (published online 24 Jun 2015).  A modified ziggurat
+     * algorithm for generating exponentially and normally distributed pseudorandom numbers.
+     * Journal of Statistical Computation and Simulation 86 (7), pages 1281-1294.
+     * https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234
+     * Also at https://arxiv.org/abs/1403.6870 (26 March 2014).
+     *
+     * Alastair J. Walker.  1977.  An efficient method for generating discrete random
+     * variables with general distributions. ACM Trans. Math. Software 3, 3
+     * (September 1977), 253-256. DOI: https://doi.org/10.1145/355744.355749
+     *
+     * Certain details of these algorithms depend critically on the quality of the
+     * low-order bits delivered by NextLong().  These algorithms should not be used
+     * with RNG algorithms (such as a simple Linear Congruential Generator) whose
+     * low-order output bits do not have good statistical quality.
+     */
+
+    // Implementation support for nextExponential()
+
+    static double computeNextExponential(RandomGenerator rng) {
+        long U1 = rng.nextLong();
+        // Experimentation on a variety of machines indicates that it is overall much faster
+        // to do the following & and < operations on longs rather than first cast U1 to int
+        // (but then we need to cast to int before doing the array indexing operation).
+        long i = U1 & DoubleZigguratTables.exponentialLayerMask;
+        if (i < DoubleZigguratTables.exponentialNumberOfLayers) {
+            // This is the fast path (occurring more than 98% of the time).  Make an early exit.
+            return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1);
+        }
+        // We didn't use the upper part of U1 after all.  We'll be able to use it later.
+
+        for (double extra = 0.0; ; ) {
+            // Use Walker's alias method to sample an (unsigned) integer j from a discrete
+            // probability distribution that includes the tail and all the ziggurat overhangs;
+            // j will be less than DoubleZigguratTables.exponentialNumberOfLayers + 1.
+            long UA = rng.nextLong();
+            int j = (int)UA & DoubleZigguratTables.exponentialAliasMask;
+            if (UA >= DoubleZigguratTables.exponentialAliasThreshold[j]) {
+                j = DoubleZigguratTables.exponentialAliasMap[j] & DoubleZigguratTables.exponentialSignCorrectionMask;
+            }
+            if (j > 0) {   // Sample overhang j
+                // For the exponential distribution, every overhang is convex.
+                final double[] X = DoubleZigguratTables.exponentialX;
+                final double[] Y = DoubleZigguratTables.exponentialY;
+                for (;; U1 = (rng.nextLong() >>> 1)) {
+                    long U2 = (rng.nextLong() >>> 1);
+                    // Compute the actual x-coordinate of the randomly chosen point.
+                    double x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
+                    // Does the point lie below the curve?
+                    long Udiff = U2 - U1;
+                    if (Udiff < 0) {
+                        // We picked a point in the upper-right triangle.  None of those can be accepted.
+                        // So remap the point into the lower-left triangle and try that.
+                        // In effect, we swap U1 and U2, and invert the sign of Udiff.
+                        Udiff = -Udiff;
+                        U2 = U1;
+                        U1 -= Udiff;
+                    }
+                    if (Udiff >= DoubleZigguratTables.exponentialConvexMargin) {
+                        return x + extra;   // The chosen point is way below the curve; accept it.
+                    }
+                    // Compute the actual y-coordinate of the randomly chosen point.
+                    double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
+                    // Now see how that y-coordinate compares to the curve
+                    if (y <= Math.exp(-x)) {
+                        return x + extra;   // The chosen point is below the curve; accept it.
+                    }
+                    // Otherwise, we reject this sample and have to try again.
+                }
+            }
+            // We are now committed to sampling from the tail.  We could do a recursive call
+            // and then add X[0] but we save some time and stack space by using an iterative loop.
+            extra += DoubleZigguratTables.exponentialX0;
+            // This is like the first five lines of this method, but if it returns, it first adds "extra".
+            U1 = rng.nextLong();
+            i = U1 & DoubleZigguratTables.exponentialLayerMask;
+            if (i < DoubleZigguratTables.exponentialNumberOfLayers) {
+                return DoubleZigguratTables.exponentialX[(int)i] * (U1 >>> 1) + extra;
+            }
+        }
+    }
+
+    // Implementation support for nextGaussian()
+
+    static double computeNextGaussian(RandomGenerator rng) {
+        long U1 = rng.nextLong();
+        // Experimentation on a variety of machines indicates that it is overall much faster
+        // to do the following & and < operations on longs rather than first cast U1 to int
+        // (but then we need to cast to int before doing the array indexing operation).
+        long i = U1 & DoubleZigguratTables.normalLayerMask;
+
+        if (i < DoubleZigguratTables.normalNumberOfLayers) {
+            // This is the fast path (occurring more than 98% of the time).  Make an early exit.
+            return DoubleZigguratTables.normalX[(int)i] * U1;   // Note that the sign bit of U1 is used here.
+        }
+        // We didn't use the upper part of U1 after all.
+        // Pull U1 apart into a sign bit and a 63-bit value for later use.
+        double signBit = (U1 >= 0) ? 1.0 : -1.0;
+        U1 = (U1 << 1) >>> 1;
+
+        // Use Walker's alias method to sample an (unsigned) integer j from a discrete
+        // probability distribution that includes the tail and all the ziggurat overhangs;
+        // j will be less than DoubleZigguratTables.normalNumberOfLayers + 1.
+        long UA = rng.nextLong();
+        int j = (int)UA & DoubleZigguratTables.normalAliasMask;
+        if (UA >= DoubleZigguratTables.normalAliasThreshold[j]) {
+            j = DoubleZigguratTables.normalAliasMap[j] & DoubleZigguratTables.normalSignCorrectionMask;
+        }
+
+        double x;
+        // Now the goal is to choose the result, which will be multiplied by signBit just before return.
+
+        // There are four kinds of overhangs:
+        //
+        //  j == 0                          :  Sample from tail
+        //  0 < j < normalInflectionIndex   :  Overhang is convex; can reject upper-right triangle
+        //  j == normalInflectionIndex      :  Overhang includes the inflection point
+        //  j > normalInflectionIndex       :  Overhang is concave; can accept point in lower-left triangle
+        //
+        // Choose one of four loops to compute x, each specialized for a specific kind of overhang.
+        // Conditional statements are arranged such that the more likely outcomes are first.
+
+        // In the three cases other than the tail case:
+        // U1 represents a fraction (scaled by 2**63) of the width of rectangle measured from the left.
+        // U2 represents a fraction (scaled by 2**63) of the height of rectangle measured from the top.
+        // Together they indicate a randomly chosen point within the rectangle.
+
+        final double[] X = DoubleZigguratTables.normalX;
+        final double[] Y = DoubleZigguratTables.normalY;
+        if (j > DoubleZigguratTables.normalInflectionIndex) {   // Concave overhang
+            for (;; U1 = (rng.nextLong() >>> 1)) {
+                long U2 = (rng.nextLong() >>> 1);
+                // Compute the actual x-coordinate of the randomly chosen point.
+                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
+                // Does the point lie below the curve?
+                long Udiff = U2 - U1;
+                if (Udiff >= 0) {
+                    break;   // The chosen point is in the lower-left triangle; accept it.
+                }
+                if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) {
+                    continue;   // The chosen point is way above the curve; reject it.
+                }
+                // Compute the actual y-coordinate of the randomly chosen point.
+                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
+                // Now see how that y-coordinate compares to the curve
+                if (y <= Math.exp(-0.5*x*x)) {
+                    break;   // The chosen point is below the curve; accept it.
+                }
+                // Otherwise, we reject this sample and have to try again.
+            }
+        } else if (j == 0) {   // Tail
+            // Tail-sampling method of Marsaglia and Tsang.  See any one of:
+            // Marsaglia and Tsang. 1984. A fast, easily implemented method for sampling from decreasing
+            //    or symmetric unimodal density functions. SIAM J. Sci. Stat. Comput. 5, 349-359.
+            // Marsaglia and Tsang. 1998. The Monty Python method for generating random variables.
+            //    ACM Trans. Math. Softw. 24, 3 (September 1998), 341-350.  See page 342, step (4).
+            //    http://doi.org/10.1145/292395.292453
+            // Thomas, Luk, Leong, and Villasenor. 2007. Gaussian random number generators.
+            //    ACM Comput. Surv. 39, 4, Article 11 (November 2007).  See Algorithm 16.
+            //    http://doi.org/10.1145/1287620.1287622
+            // Compute two separate random exponential samples and then compare them in certain way.
+            do {
+                x = (1.0 / DoubleZigguratTables.normalX0) * computeNextExponential(rng);
+            } while (computeNextExponential(rng) < 0.5*x*x);
+            x += DoubleZigguratTables.normalX0;
+        } else if (j < DoubleZigguratTables.normalInflectionIndex) {   // Convex overhang
+            for (;; U1 = (rng.nextLong() >>> 1)) {
+                long U2 = (rng.nextLong() >>> 1);
+                // Compute the actual x-coordinate of the randomly chosen point.
+                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
+                // Does the point lie below the curve?
+                long Udiff = U2 - U1;
+                if (Udiff < 0) {
+                    // We picked a point in the upper-right triangle.  None of those can be accepted.
+                    // So remap the point into the lower-left triangle and try that.
+                    // In effect, we swap U1 and U2, and invert the sign of Udiff.
+                    Udiff = -Udiff;
+                    U2 = U1;
+                    U1 -= Udiff;
+                }
+                if (Udiff >= DoubleZigguratTables.normalConvexMargin) {
+                    break;   // The chosen point is way below the curve; accept it.
+                }
+                // Compute the actual y-coordinate of the randomly chosen point.
+                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
+                // Now see how that y-coordinate compares to the curve
+                if (y <= Math.exp(-0.5*x*x)) break;                // The chosen point is below the curve; accept it.
+                // Otherwise, we reject this sample and have to try again.
+            }
+        } else {
+            // The overhang includes the inflection point, so the curve is both convex and concave
+            for (;; U1 = (rng.nextLong() >>> 1)) {
+                long U2 = (rng.nextLong() >>> 1);
+                // Compute the actual x-coordinate of the randomly chosen point.
+                x = (X[j] * 0x1.0p63) + ((X[j-1] - X[j]) * (double)U1);
+                // Does the point lie below the curve?
+                long Udiff = U2 - U1;
+                if (Udiff >= DoubleZigguratTables.normalConvexMargin) {
+                    break;   // The chosen point is way below the curve; accept it.
+                }
+                if (Udiff <= -DoubleZigguratTables.normalConcaveMargin) {
+                    continue;   // The chosen point is way above the curve; reject it.
+                }
+                // Compute the actual y-coordinate of the randomly chosen point.
+                double y = (Y[j] * 0x1.0p63) + ((Y[j] - Y[j-1]) * (double)U2);
+                // Now see how that y-coordinate compares to the curve
+                if (y <= Math.exp(-0.5*x*x)) {
+                    break;   // The chosen point is below the curve; accept it.
+                }
+                // Otherwise, we reject this sample and have to try again.
+            }
+        }
+        return signBit*x;
+    }
+
+    /**
+     * This class overrides the stream-producing methods (such as {@code ints()})
+     * in class {@link AbstractGenerator} to provide {@link Spliterator}-based
+     * implmentations that support potentially parallel execution.
+     *
+     * To implement a pseudorandom number generator, the programmer needs
+     * only to extend this class and provide implementations for the methods
+     * {@code nextInt()}, {@code nextLong()}, {@code makeIntsSpliterator},
+     * {@code makeLongsSpliterator}, and {@code makeDoublesSpliterator}.
+     *
+     * This class is not public; it provides shared code to the public
+     * classes {@link AbstractSplittableGenerator}, {@link AbstractSharedGenerator},
+     * and {@link AbstractArbitrarilyJumpableGenerator}.
+     *
+     * @since 14
+     */
+    public abstract static class AbstractSpliteratorGenerator implements RandomGenerator {
+        /*
+         * Implementation Overview.
+         *
+         * This class provides most of the "user API" methods needed to
+         * satisfy the interface RandomGenerator.  An implementation of this
+         * interface need only extend this class and provide implementations
+         * of six methods: nextInt, nextLong, and nextDouble (the versions
+         * that take no arguments) and makeIntsSpliterator,
+         * makeLongsSpliterator, and makeDoublesSpliterator.
+         *
+         * File organization: First the non-public abstract methods needed
+         * to create spliterators, then the main public methods.
+         */
+
+        /**
+         * Needs comment (was made public to be overridden out of package.)
+         *
+         * @param index low
+         * @param fence high
+         * @param origin low
+         * @param bound high
+         * @return result
+         */
+        public abstract Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound);
+
+        /**
+         * Needs comment (was made public to be overridden out of package.)
+         *
+         * @param index low
+         * @param fence high
+         * @param origin low
+         * @param bound high
+         * @return result
+         */
+        public abstract Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound);
+
+        /**
+         * Needs comment (was made public to be overridden out of package.)
+         *
+         * @param index low
+         * @param fence high
+         * @param origin low
+         * @param bound high
+         * @return result
+         */
+        public abstract Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound);
+
+        /* ---------------- public methods ---------------- */
+
+        // stream methods, coded in a way intended to better isolate for
+        // maintenance purposes the small differences across forms.
+
+        private static IntStream intStream(Spliterator.OfInt srng) {
+            return StreamSupport.intStream(srng, false);
+        }
+
+        private static LongStream longStream(Spliterator.OfLong srng) {
+            return StreamSupport.longStream(srng, false);
+        }
+
+        private static DoubleStream doubleStream(Spliterator.OfDouble srng) {
+            return StreamSupport.doubleStream(srng, false);
+        }
+
+        /**
+         * 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) {
+            RandomSupport.checkStreamSize(streamSize);
+            return intStream(makeIntsSpliterator(0L, streamSize, Integer.MAX_VALUE, 0));
+        }
+
+        /**
+         * Returns an effectively unlimited stream of pseudorandomly chosen
+         * {@code int} values.
+         *
+         * @implNote The implementation of this method is effectively
+         * equivalent to {@code ints(Long.MAX_VALUE)}.
+         *
+         * @return a stream of pseudorandomly chosen {@code int} values
+         */
+
+        public IntStream ints() {
+            return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0));
+        }
+
+        /**
+         * 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) {
+            RandomSupport.checkStreamSize(streamSize);
+            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+            return intStream(makeIntsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
+        }
+
+        /**
+         * 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).
+         *
+         * @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}
+         *
+         * @implNote This method is implemented to be equivalent to {@code ints(Long.MAX_VALUE,
+         *         randomNumberOrigin, randomNumberBound)}.
+         */
+        public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
+            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+            return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound));
+        }
+
+        /**
+         * 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) {
+            RandomSupport.checkStreamSize(streamSize);
+            return longStream(makeLongsSpliterator(0L, streamSize, Long.MAX_VALUE, 0L));
+        }
+
+        /**
+         * Returns an effectively unlimited stream of pseudorandom {@code long} values from this
+         * generator and/or one split from it.
+         *
+         * @return a stream of pseudorandom {@code long} values
+         *
+         * @implNote This method is implemented to be equivalent to {@code
+         *         longs(Long.MAX_VALUE)}.
+         */
+        public LongStream longs() {
+            return longStream(makeLongsSpliterator(0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L));
+        }
+
+        /**
+         * 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) {
+            RandomSupport.checkStreamSize(streamSize);
+            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+            return longStream(makeLongsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
+        }
+
+        /**
+         * 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).
+         *
+         * @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}
+         *
+         * @implNote This method is implemented to be equivalent to {@code longs(Long.MAX_VALUE,
+         *         randomNumberOrigin, randomNumberBound)}.
+         */
+        public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
+            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+            return StreamSupport.longStream
+                (makeLongsSpliterator(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) {
+            RandomSupport.checkStreamSize(streamSize);
+            return doubleStream(makeDoublesSpliterator(0L, streamSize, Double.MAX_VALUE, 0.0));
+        }
+
+        /**
+         * 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).
+         *
+         * @return a stream of pseudorandom {@code double} values
+         *
+         * @implNote This method is implemented to be equivalent to {@code
+         *         doubles(Long.MAX_VALUE)}.
+         */
+        public DoubleStream doubles() {
+            return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0));
+        }
+
+        /**
+         * 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
+         * @throws IllegalArgumentException if {@code randomNumberOrigin} is greater than or equal to
+         *                                  {@code randomNumberBound}
+         */
+        public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
+            RandomSupport.checkStreamSize(streamSize);
+            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+            return doubleStream(makeDoublesSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
+        }
+
+        /**
+         * 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).
+         *
+         * @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}
+         *
+         * @implNote This method is implemented to be equivalent to {@code
+         *         doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
+         */
+        public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
+            RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+            return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound));
+        }
+
+    }
+
+    /**
+     * This class provides much of the implementation of the
+     * {@link ArbitrarilyJumpableGenerator} interface, to minimize the effort
+     * required to implement that interface.
+     *
+     * To implement a pseudorandom number generator, the programmer needs
+     * only to extend this class and provide implementations for the
+     * methods {@link #nextInt()}, {@link #nextLong()}, {@link #copy()},
+     * {@link #jump(double)}, {@link #jumpPowerOfTwo(int)},
+     * {@link #defaultJumpDistance()}, and {@link #defaultLeapDistance()}.
+     *
+     * (If the pseudorandom number generator also has the ability to split,
+     * then the programmer may wish to consider instead extending
+     * {@link AbstractSplittableGenerator}.)
+     *
+     * The programmer should generally provide at least three constructors:
+     * one that takes no arguments, one that accepts a {@code long}
+     * seed value, and one that accepts an array of seed {@code byte} values.
+     * This class provides a public {@code initialSeed()} method that may
+     * be useful in initializing some static state from which to derive
+     * defaults seeds for use by the no-argument constructor.
+     *
+     * For the stream methods (such as {@code ints()} and {@code splits()}),
+     * this class provides {@link Spliterator}-based implementations that
+     * allow parallel execution when appropriate.  In this respect
+     * {@link ArbitrarilyJumpableGenerator} differs from {@link JumpableGenerator},
+     * which provides very simple implementations that produce
+     * sequential streams only.
+     *
+     * <p>An implementation of the {@link AbstractArbitrarilyJumpableGenerator} class
+     * must provide concrete definitions for the methods {@code nextInt()},
+     * {@code nextLong}, {@code period()}, {@code copy()}, {@code jump(double)},
+     * {@code defaultJumpDistance()}, and {@code defaultLeapDistance()}.
+     * Default implementations are provided for all other methods.
+     *
+     * The documentation for each non-abstract method in this class
+     * describes its implementation in detail. Each of these methods may
+     * be overridden if the pseudorandom number generator being
+     * implemented admits a more efficient implementation.
+     *
+     * @since 14
+     */
+    public abstract static class AbstractArbitrarilyJumpableGenerator
+        extends AbstractSpliteratorGenerator implements RandomGenerator.ArbitrarilyJumpableGenerator {
+
+        /*
+         * Implementation Overview.
+         *
+         * This class provides most of the "user API" methods needed to satisfy
+         * the interface ArbitrarilyJumpableGenerator.  Most of these methods
+         * are in turn inherited from AbstractGenerator and the non-public class
+         * AbstractSpliteratorGenerator; this file implements four versions of the
+         * jumps method and defines the spliterators necessary to support them.
+         *
+         * File organization: First the non-public methods needed by the class
+         * AbstractSpliteratorGenerator, then the main public methods, followed by some
+         * custom spliterator classes needed for stream methods.
+         */
+
+        // IllegalArgumentException messages
+        static final String BadLogDistance  = "logDistance must be non-negative";
+
+        // 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);
+        }
+
+        // Similar methods used by this class
+        Spliterator<RandomGenerator> makeJumpsSpliterator(long index, long fence, double distance) {
+            return new RandomJumpsSpliterator(this, index, fence, distance);
+        }
+        Spliterator<JumpableGenerator> makeLeapsSpliterator(long index, long fence, double distance) {
+            return new RandomLeapsSpliterator(this, index, fence, distance);
+        }
+        Spliterator<ArbitrarilyJumpableGenerator> makeArbitraryJumpsSpliterator(long index, long fence, double distance) {
+            return new RandomArbitraryJumpsSpliterator(this, index, fence, distance);
+        }
+
+        /* ---------------- public methods ---------------- */
+
+        /**
+         * Returns a new generator whose internal state is an exact copy
+         * of this generator (therefore their future behavior should be
+         * identical if subjected to the same series of operations).
+         *
+         * @return a new object that is a copy of this generator
+         */
+        public abstract AbstractArbitrarilyJumpableGenerator copy();
+
+        // Stream methods for jumping
+
+        private static <T> Stream<T> stream(Spliterator<T> srng) {
+            return StreamSupport.stream(srng, false);
+        }
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link RandomGenerator} interface, produced by jumping copies of this
+         * generator by different integer multiples of the default jump distance.
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @implNote This method is implemented to be equivalent to {@code
+         *         jumps(Long.MAX_VALUE)}.
+         */
+        public Stream<RandomGenerator> jumps() {
+            return stream(makeJumpsSpliterator(0L, Long.MAX_VALUE, defaultJumpDistance()));
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of
+         * new pseudorandom number generators, each of which implements the
+         * {@link RandomGenerator} interface, produced by jumping copies of this generator
+         * by different integer multiples of the default jump distance.
+         *
+         * @param streamSize the number of generators to generate
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         */
+        public Stream<RandomGenerator> jumps(long streamSize) {
+            RandomSupport.checkStreamSize(streamSize);
+            return stream(makeJumpsSpliterator(0L, streamSize, defaultJumpDistance()));
+        }
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link RandomGenerator} interface, produced by jumping copies of this
+         * generator by different integer multiples of the specified jump distance.
+         *
+         * @param distance a distance to jump forward within the state cycle
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @implNote This method is implemented to be equivalent to {@code
+         *         jumps(Long.MAX_VALUE)}.
+         */
+        public Stream<ArbitrarilyJumpableGenerator> jumps(double distance) {
+            return stream(makeArbitraryJumpsSpliterator(0L, Long.MAX_VALUE, distance));
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link RandomGenerator} interface, produced by
+         * jumping copies of this generator by different integer multiples of the specified jump
+         * distance.
+         *
+         * @param streamSize the number of generators to generate
+         * @param distance   a distance to jump forward within the state cycle
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         */
+        public Stream<ArbitrarilyJumpableGenerator> jumps(long streamSize, double distance) {
+            RandomSupport.checkStreamSize(streamSize);
+            return stream(makeArbitraryJumpsSpliterator(0L, streamSize, distance));
+        }
+
+        /**
+         * Alter the state of this pseudorandom number generator so as to
+         * jump forward a very large, fixed distance (typically 2<sup>128</sup>
+         * or more) within its state cycle.  The distance used is that
+         * returned by method {@code defaultLeapDistance()}.
+         */
+        public void leap() {
+            jump(defaultLeapDistance());
+        }
+
+        // Stream methods for leaping
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link RandomGenerator} interface, produced by jumping copies of this
+         * generator by different integer multiples of the default leap distance.
+         *
+         * @implNote This method is implemented to be equivalent to {@code leaps(Long.MAX_VALUE)}.
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         */
+        public Stream<JumpableGenerator> leaps() {
+            return stream(makeLeapsSpliterator(0L, Long.MAX_VALUE, defaultLeapDistance()));
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link RandomGenerator} interface, produced by
+         * jumping copies of this generator by different integer multiples of the default leap
+         * distance.
+         *
+         * @param streamSize the number of generators to generate
+         *
+         * @return a stream of objects that implement the {@link RandomGenerator} interface
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         */
+        public Stream<JumpableGenerator> leaps(long streamSize) {
+            return stream(makeLeapsSpliterator(0L, streamSize, defaultLeapDistance()));
+        }
+
+
+        /**
+         * 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
+         * {@code Long.MAX_VALUE}. For splits, we choose to override the method {@code trySplit()} to
+         * try to optimize execution speed: instead of dividing a range in half, it breaks off the
+         * largest possible chunk whose size is a power of two such that the remaining chunk is not
+         * empty. In this way, the necessary jump distances will tend to be powers of two.  The long
+         * and double versions of this class are identical except for types.
+         */
+        static class RandomIntsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfInt {
+            final ArbitrarilyJumpableGenerator generatingGenerator;
+            final int origin;
+            final int bound;
+
+            RandomIntsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, int origin, int bound) {
+                super(index, fence);
+                this.origin = origin; this.bound = bound;
+                this.generatingGenerator = generatingGenerator;
+            }
+
+            public Spliterator.OfInt trySplit() {
+                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
+                if (m <= i) return null;
+                index = m;
+                ArbitrarilyJumpableGenerator r = generatingGenerator;
+                return new RandomIntsSpliterator(r.copyAndJump((double)delta), 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;
+                    ArbitrarilyJumpableGenerator 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 ArbitrarilyJumpableGenerator generatingGenerator;
+            final long origin;
+            final long bound;
+
+            RandomLongsSpliterator(ArbitrarilyJumpableGenerator 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, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
+                if (m <= i) return null;
+                index = m;
+                ArbitrarilyJumpableGenerator r = generatingGenerator;
+                return new RandomLongsSpliterator(r.copyAndJump((double)delta), 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;
+                    ArbitrarilyJumpableGenerator 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 ArbitrarilyJumpableGenerator generatingGenerator;
+            final double origin;
+            final double bound;
+
+            RandomDoublesSpliterator(ArbitrarilyJumpableGenerator 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, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
+                if (m <= i) return null;
+                index = m;
+                ArbitrarilyJumpableGenerator r = generatingGenerator;
+                return new RandomDoublesSpliterator(r.copyAndJump((double)delta), 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;
+                    ArbitrarilyJumpableGenerator r = generatingGenerator;
+                    double o = origin, b = bound;
+                    do {
+                        consumer.accept(RandomSupport.boundedNextDouble(r, o, b));
+                    } while (++i < f);
+                }
+            }
+        }
+
+        // Spliterators for producing new generators by jumping or leaping.  The
+        // complete implementation of each of these spliterators is right here.
+        // In the same manner as for the preceding spliterators, the method trySplit() is
+        // coded to optimize execution speed: instead of dividing a range
+        // in half, it breaks off the largest possible chunk whose
+        // size is a power of two such that the remaining chunk is not
+        // empty.  In this way, the necessary jump distances will tend to be
+        // powers of two.
+
+        /**
+         * Spliterator for stream of generators of type RandomGenerator produced by jumps.
+         */
+        static class RandomJumpsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator<RandomGenerator> {
+            ArbitrarilyJumpableGenerator generatingGenerator;
+            final double distance;
+
+            RandomJumpsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) {
+                super(index, fence);
+                this.generatingGenerator = generatingGenerator; this.distance = distance;
+            }
+
+            public Spliterator<RandomGenerator> trySplit() {
+                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
+                if (m <= i) return null;
+                index = m;
+                ArbitrarilyJumpableGenerator r = generatingGenerator;
+                // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
+                return new RandomJumpsSpliterator(r.copyAndJump(distance * (double)delta), i, m, distance);
+            }
+
+            public boolean tryAdvance(Consumer<? super RandomGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    consumer.accept(generatingGenerator.copyAndJump(distance));
+                    index = i + 1;
+                    return true;
+                }
+                return false;
+            }
+
+            public void forEachRemaining(Consumer<? super RandomGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    index = f;
+                    ArbitrarilyJumpableGenerator r = generatingGenerator;
+                    do {
+                        consumer.accept(r.copyAndJump(distance));
+                    } while (++i < f);
+                }
+            }
+        }
+
+        /**
+         * Spliterator for stream of generators of type RandomGenerator produced by leaps.
+         */
+        static class RandomLeapsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator<JumpableGenerator> {
+            ArbitrarilyJumpableGenerator generatingGenerator;
+            final double distance;
+
+            RandomLeapsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) {
+                super(index, fence);
+                this.generatingGenerator = generatingGenerator; this.distance = distance;
+            }
+
+            public Spliterator<JumpableGenerator> trySplit() {
+                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
+                if (m <= i) return null;
+                index = m;
+                // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
+                return new RandomLeapsSpliterator(generatingGenerator.copyAndJump(distance * (double)delta), i, m, distance);
+            }
+
+            public boolean tryAdvance(Consumer<? super JumpableGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    consumer.accept(generatingGenerator.copyAndJump(distance));
+                    index = i + 1;
+                    return true;
+                }
+                return false;
+            }
+
+            public void forEachRemaining(Consumer<? super JumpableGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    index = f;
+                    ArbitrarilyJumpableGenerator r = generatingGenerator;
+                    do {
+                        consumer.accept(r.copyAndJump(distance));
+                    } while (++i < f);
+                }
+            }
+        }
+
+        /**
+         * Spliterator for stream of generators of type RandomGenerator produced by arbitrary jumps.
+         */
+        static class RandomArbitraryJumpsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator<ArbitrarilyJumpableGenerator> {
+            ArbitrarilyJumpableGenerator generatingGenerator;
+            final double distance;
+
+            RandomArbitraryJumpsSpliterator(ArbitrarilyJumpableGenerator generatingGenerator, long index, long fence, double distance) {
+                super(index, fence);
+                this.generatingGenerator = generatingGenerator; this.distance = distance;
+            }
+
+            public Spliterator<ArbitrarilyJumpableGenerator> trySplit() {
+                long i = index, delta = Long.highestOneBit((fence - i) - 1), m = i + delta;
+                if (m <= i) return null;
+                index = m;
+                // Because delta is a power of two, (distance * (double)delta) can always be computed exactly.
+                return new RandomArbitraryJumpsSpliterator(generatingGenerator.copyAndJump(distance * (double)delta), i, m, distance);
+            }
+
+            public boolean tryAdvance(Consumer<? super ArbitrarilyJumpableGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    consumer.accept(generatingGenerator.copyAndJump(distance));
+                    index = i + 1;
+                    return true;
+                }
+                return false;
+            }
+
+            public void forEachRemaining(Consumer<? super ArbitrarilyJumpableGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    index = f;
+                    ArbitrarilyJumpableGenerator r = generatingGenerator;
+                    do {
+                        consumer.accept(r.copyAndJump(distance));
+                    } while (++i < f);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * This class provides much of the implementation of the {@link SplittableGenerator} interface, to
+     * minimize the effort required to implement this interface.
+     * <p>
+     * To implement a pseudorandom number generator, the programmer needs only to extend this class and
+     * provide implementations for the methods {@code nextInt()}, {@code nextLong()}, {@code period()},
+     * and {@code split(SplittableGenerator)}.
+     * <p>
+     * (If the pseudorandom number generator also has the ability to jump, then the programmer may wish
+     * to consider instead extending the class {@link ArbitrarilyJumpableGenerator}.  But if the pseudorandom
+     * number generator furthermore has the ability to jump an arbitrary specified distance, then the
+     * programmer may wish to consider instead extending the class {@link
+     * AbstractArbitrarilyJumpableGenerator}.)
+     * <p>
+     * The programmer should generally provide at least three constructors: one that takes no arguments,
+     * one that accepts a {@code long} seed value, and one that accepts an array of seed {@code byte}
+     * values. This class provides a public {@code initialSeed()} method that may be useful in
+     * initializing some static state from which to derive defaults seeds for use by the no-argument
+     * constructor.
+     * <p>
+     * For the stream methods (such as {@code ints()} and {@code splits()}), this class provides {@link
+     * Spliterator} based implementations that allow parallel execution when appropriate.
+     * <p>
+     * The documentation for each non-abstract method in this class describes its implementation in
+     * detail. Each of these methods may be overridden if the pseudorandom number generator being
+     * implemented admits a more efficient implementation.
+     *
+     * @since 14
+     */
+    public abstract static class AbstractSplittableGenerator extends AbstractSpliteratorGenerator implements SplittableGenerator {
+
+        /*
+         * Implementation Overview.
+         *
+         * This class provides most of the "user API" methods needed to
+         * satisfy the interface JumpableGenerator.  Most of these methods
+         * are in turn inherited from AbstractGenerator and the non-public class
+         * AbstractSpliteratorGenerator; this file implements two versions of the
+         * splits method and defines the spliterators necessary to support
+         * them.
+         *
+         * The abstract split() method from interface SplittableGenerator is redeclared
+         * here so as to narrow the return type to AbstractSplittableGenerator.
+         *
+         * File organization: First the non-public methods needed by the class
+         * AbstractSpliteratorGenerator, then the main public methods, followed by some
+         * custom spliterator classes.
+         */
+
+        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);
+        }
+
+        Spliterator<SplittableGenerator> makeSplitsSpliterator(long index, long fence, SplittableGenerator source) {
+            return new RandomSplitsSpliterator(source, index, fence, this);
+        }
+
+        /* ---------------- public methods ---------------- */
+
+        /**
+         * Implements the @code{split()} method as {@code this.split(this) }.
+         *
+         * @return the new {@link AbstractSplittableGenerator} instance
+         */
+        public SplittableGenerator split() {
+            return this.split(this);
+        }
+
+        // Stream methods for splittings
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link SplittableGenerator} interface.
+         * <p>
+         * This pseudorandom number generator provides the entropy used to seed the new ones.
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         *
+         * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}.
+         */
+        public Stream<SplittableGenerator> splits() {
+            return this.splits(Long.MAX_VALUE, this);
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link SplittableGenerator} interface.
+         * <p>
+         * This pseudorandom number generator provides the entropy used to seed the new ones.
+         *
+         * @param streamSize the number of values to generate
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         */
+        public Stream<SplittableGenerator> splits(long streamSize) {
+            return this.splits(streamSize, this);
+        }
+
+        /**
+         * Returns an effectively unlimited stream of new pseudorandom number generators, each of which
+         * implements the {@link SplittableGenerator} interface.
+         *
+         * @param source a {@link SplittableGenerator} instance to be used instead of this one as a source of
+         *               pseudorandom bits used to initialize the state of the new ones.
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         *
+         * @implNote This method is implemented to be equivalent to {@code splits(Long.MAX_VALUE)}.
+         */
+        public Stream<SplittableGenerator> splits(SplittableGenerator source) {
+            return this.splits(Long.MAX_VALUE, source);
+        }
+
+        /**
+         * Returns a stream producing the given {@code streamSize} number of new pseudorandom number
+         * generators, each of which implements the {@link SplittableGenerator} interface.
+         *
+         * @param streamSize the number of values to generate
+         * @param source     a {@link SplittableGenerator} instance to be used instead of this one as a source
+         *                   of pseudorandom bits used to initialize the state of the new ones.
+         *
+         * @return a stream of {@link SplittableGenerator} objects
+         *
+         * @throws IllegalArgumentException if {@code streamSize} is less than zero
+         */
+        public Stream<SplittableGenerator> splits(long streamSize, SplittableGenerator source) {
+            RandomSupport.checkStreamSize(streamSize);
+            return StreamSupport.stream(makeSplitsSpliterator(0L, streamSize, source), 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
+         * {@code 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 class RandomIntsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator.OfInt {
+            final SplittableGenerator generatingGenerator;
+            final int origin;
+            final int bound;
+
+            RandomIntsSpliterator(SplittableGenerator 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;
+                return new RandomIntsSpliterator(generatingGenerator.split(), 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 SplittableGenerator generatingGenerator;
+            final long origin;
+            final long bound;
+
+            RandomLongsSpliterator(SplittableGenerator 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;
+                return new RandomLongsSpliterator(generatingGenerator.split(), 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 SplittableGenerator generatingGenerator;
+            final double origin;
+            final double bound;
+
+            RandomDoublesSpliterator(SplittableGenerator 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;
+                return new RandomDoublesSpliterator(generatingGenerator.split(), 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);
+                }
+            }
+        }
+
+        /**
+         * Spliterator for stream of generators of type SplittableGenerator.  We multiplex the two
+         * versions into one class by treating "infinite" as equivalent to Long.MAX_VALUE.
+         * For splits, it uses the standard divide-by-two approach.
+         */
+        static class RandomSplitsSpliterator extends RandomSupport.RandomSpliterator implements Spliterator<SplittableGenerator> {
+            final SplittableGenerator generatingGenerator;
+            final SplittableGenerator constructingGenerator;
+
+            RandomSplitsSpliterator(SplittableGenerator generatingGenerator, long index, long fence, SplittableGenerator constructingGenerator) {
+                super(index, fence);
+                this.generatingGenerator = generatingGenerator;
+                this.constructingGenerator = constructingGenerator;
+            }
+
+            public Spliterator<SplittableGenerator> trySplit() {
+                long i = index, m = (i + fence) >>> 1;
+                if (m <= i) return null;
+                index = m;
+                return new RandomSplitsSpliterator(generatingGenerator.split(), i, m, constructingGenerator);
+            }
+
+            public boolean tryAdvance(Consumer<? super SplittableGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    consumer.accept(constructingGenerator.split(generatingGenerator));
+                    index = i + 1;
+                    return true;
+                }
+                else return false;
+            }
+
+            public void forEachRemaining(Consumer<? super SplittableGenerator> consumer) {
+                if (consumer == null) throw new NullPointerException();
+                long i = index, f = fence;
+                if (i < f) {
+                    index = f;
+                    SplittableGenerator c = constructingGenerator;
+                    SplittableGenerator r = generatingGenerator;
+                    do {
+                        consumer.accept(c.split(r));
+                    } while (++i < f);
+                }
+            }
+        }
+
+    }
+
+}
+
--- a/src/java.base/share/classes/java/util/random/SplittableRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-import java.util.stream.IntStream;
-import java.util.stream.LongStream;
-import java.util.stream.DoubleStream;
-
-/**
- * This interface is designed to provide a common protocol for objects
- * that generate sequences of pseudorandom numbers (or Boolean values)
- * and furthermore can be <i>split</i> into two objects (the original
- * one and a new one) each of which obey that same protocol (and therefore
- * can be recursively split indefinitely).
- * <p>
- * Ideally, all {@link SplittableRNG} objects produced by recursive
- * splitting from a single original {@link SplittableRNG} object are
- * statistically independent of one another and individually uniform.
- * Therefore we would expect the set of values collectively generated
- * by a set of such objects to have the same statistical properties as
- * if the same quantity of values were generated by a single thread
- * using a single {@link SplittableRNG} object.  In practice, one must
- * settle for some approximation to independence and uniformity.
- * <p>
- * Methods are provided to perform a single splitting operation and
- * also to produce a stream of generators split off from the original
- * (by either iterative or recursive splitting, or a combination).
- * <p>
- * An implementation of the {@link SplittableRNG} interface must provide
- * concrete definitions for the methods {@code nextInt()}, {@code nextLong},
- * {@code period()}, {@code split()}, {@code split(SplittableRNG)},
- * {@code splits()}, {@code splits(long)}, {@code splits(SplittableRNG)},
- * and {@code splits(long, SplittableRNG)}.  Perhaps the most convenient
- * way to implement this interface is to extend the abstract class
- * {@link AbstractSplittableRNG}.
- * <p>
- * Objects that implement {@link SplittableRNG} are
- * typically not cryptographically secure.  Consider instead using
- * {@link java.security.SecureRandom} to get a cryptographically
- * secure pseudo-random number generator for use by
- * security-sensitive applications.
- *
- * @since 14
- */
-public interface SplittableRNG extends StreamableRNG {
-
-    /**
-     * Returns a new pseudorandom number generator, split off from
-     * this one, that implements the {@link RandomNumberGenerator} and {@link SplittableRNG}
-     * interfaces.
-     *
-     * This pseudorandom number generator may be used as a source of
-     * pseudorandom bits used to initialize the state the new one.
-     *
-     * @return a new object that implements the {@link RandomNumberGenerator} and
-     *         {@link SplittableRNG} interfaces
-     */
-    SplittableRNG split();
-
-    /**
-     * Returns a new pseudorandom number generator, split off from
-     * this one, that implements the {@link RandomNumberGenerator} and {@link SplittableRNG}
-     * interfaces.
-     *
-     * @param source a {@link SplittableRNG} instance to be used instead
-     *               of this one as a source of pseudorandom bits used to
-     *               initialize the state of the new ones.
-     *
-     * @return an object that implements the {@link RandomNumberGenerator} and
-     *         {@link SplittableRNG} interfaces
-     */
-    SplittableRNG split(SplittableRNG source);
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom
-     * number generators, each of which implements the {@link SplittableRNG}
-     * interface.
-     *
-     * This pseudorandom number generator may be used as a source of
-     * pseudorandom bits used to initialize the state the new ones.
-     *
-     * @implNote It is permitted to implement this method in a manner
-     * equivalent to {@code splits(Long.MAX_VALUE)}.
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     */
-    default Stream<SplittableRNG> splits() {
-        return this.splits(this);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * new pseudorandom number generators, each of which implements the
-     * {@link SplittableRNG} interface.
-     *
-     * This pseudorandom number generator may be used as a source of
-     * pseudorandom bits used to initialize the state the new ones.
-     *
-     * @param streamSize the number of values to generate
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    Stream<SplittableRNG> splits(long streamSize);
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom
-     * number generators, each of which implements the {@link SplittableRNG}
-     * interface.
-     *
-     * @param source a {@link SplittableRNG} instance to be used instead
-     *               of this one as a source of pseudorandom bits used to
-     *               initialize the state of the new ones.
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     *
-     * @implNote It is permitted to implement this method in a manner
-     *           equivalent to {@code splits(Long.MAX_VALUE, source)}.
-     */
-    Stream<SplittableRNG> splits(SplittableRNG source);
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * new pseudorandom number generators, each of which implements the
-     * {@link SplittableRNG} interface.
-     *
-     * @param streamSize the number of values to generate
-     * @param source a {@link SplittableRNG} instance to be used instead
-     *               of this one as a source of pseudorandom bits used to
-     *               initialize the state of the new ones.
-     *
-     * @return a stream of {@link SplittableRNG} objects
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     */
-    Stream<SplittableRNG> splits(long streamSize, SplittableRNG source);
-
-    /**
-     * Returns an effectively unlimited stream of new pseudorandom
-     * number generators, each of which implements the {@link RandomNumberGenerator}
-     * interface.  Ideally the generators in the stream will appear
-     * to be statistically independent.
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @implNote The default implementation calls {@code splits()}.
-     */
-    default Stream<RandomNumberGenerator> rngs() {
-        return this.splits().map(x -> (RandomNumberGenerator)x);
-    }
-
-    /**
-     * Returns a stream producing the given {@code streamSize} number of
-     * new pseudorandom number generators, each of which implements the
-     * {@link RandomNumberGenerator} interface.  Ideally the generators in the stream will
-     * appear to be statistically independent.
-     *
-     * @param streamSize the number of generators to generate
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     *
-     * @implNote The default implementation calls {@code splits(streamSize)}.
-     */
-    default Stream<RandomNumberGenerator> rngs(long streamSize) {
-        return this.splits(streamSize).map(x -> (RandomNumberGenerator)x);
-    }
-}
--- a/src/java.base/share/classes/java/util/random/StreamableRNG.java	Fri Jul 26 15:20:31 2019 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.random;
-
-import java.util.stream.Stream;
-
-
-/**
- * The {@link StreamableRNG} interface augments the {@link RandomNumberGenerator} interface
- * to provide methods that return streams of {@link RandomNumberGenerator} objects.
- * Ideally, such a stream of objects would have the property that the
- * behavior of each object is statistically independent of all the others.
- * In practice, one may have to settle for some approximation to this property.
- *
- * A generator that implements interface {@link SplittableRNG}
- * may choose to use its {@code splits} method to implement the {@code rngs}
- * method required by this interface.
- *
- * A generator that implements interface {@link JumpableRNG}
- * may choose to use its {@code jumps} method to implement the {@code rngs}
- * method required by this interface.
- *
- * A generator that implements interface {@link LeapableRNG}
- * may choose to use its {@code leaps} method to implement the {@code rngs}
- * method required by this interface.
- * <p>
- * An implementation of the {@link StreamableRNG} interface must provide
- * concrete definitions for the methods {@code nextInt()}, {@code nextLong},
- * {@code period()}, and {@code rngs()}.
- * Default implementations are provided for all other methods.
- * <p>
- * Objects that implement {@link StreamableRNG} are typically
- * not cryptographically secure.  Consider instead using
- * {@link java.security.SecureRandom} to get a cryptographically
- * secure pseudo-random number generator for use by
- * security-sensitive applications.
- *
- * @since 14
- */
-
-public interface StreamableRNG extends RandomNumberGenerator {
-    /**
-     * Returns an effectively unlimited stream of objects, each of
-     * which implements the {@link RandomNumberGenerator} interface.  Ideally the
-     * generators in the stream will appear to be statistically
-     * independent.  The new generators should be of the same kind
-     * as this generator.
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @implNote It is permitted to implement this method in a manner
-     *           equivalent to {@code rngs(Long.MAX_VALUE)}.
-     */
-    Stream<RandomNumberGenerator> rngs();
-
-    /**
-     * Returns an effectively unlimited stream of objects, each of
-     * which implements the {@link RandomNumberGenerator} interface.  Ideally the
-     * generators in the stream will appear to be statistically
-     * independent.  The new generators should be of the same kind
-     * as this generator.
-     *
-     * @param streamSize the number of generators to generate
-     *
-     * @return a stream of objects that implement the {@link RandomNumberGenerator} interface
-     *
-     * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     *
-     * @implNote The default implementation calls {@code rngs()} and
-     *           then limits its length to {@code streamSize}.
-     */
-    default Stream<RandomNumberGenerator> rngs(long streamSize) {
-        RNGSupport.checkStreamSize(streamSize);
-        return rngs().limit(streamSize);
-    }
-}
--- a/src/java.base/share/classes/java/util/random/Xoroshiro128Plus.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/Xoroshiro128Plus.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,13 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.LeapableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link Xoroshiro128Plus} implements
- * interfaces {@link RandomNumberGenerator} and {@link LeapableRNG},
+ * interfaces {@link RandomGenerator} and {@link LeapableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new {@link Xoroshiro128Plus} objects
@@ -76,7 +77,7 @@
  *
  * @since 14
  */
-public final class Xoroshiro128Plus implements LeapableRNG {
+public final class Xoroshiro128Plus implements LeapableGenerator {
 
     /*
      * Implementation Overview.
@@ -109,7 +110,7 @@
      *
      * File organization: First the non-public methods that constitute the
      * main algorithm, then the public methods.  Note that many methods are
-     * defined by classes {@link AbstractJumpableRNG} and {@link AbstractRNG}.
+     * defined by classes {@link AbstractJumpableGenerator} and {@link AbstractGenerator}.
      */
 
     /* ---------------- static fields ---------------- */
@@ -117,7 +118,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong defaultGen = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is 2**128 - 1.
@@ -149,8 +150,8 @@
         // If x0 and x1 are both zero, we must choose nonzero values.
         if ((x0 | x1) == 0) {
             // At least one of the two values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(x0 += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = (x0 += RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(x0 += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = (x0 += RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -169,8 +170,8 @@
         //
         // The x values are then filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixStafford13(seed ^= RNGSupport.SILVER_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+        this(RandomSupport.mixStafford13(seed ^= RandomSupport.SILVER_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -181,7 +182,7 @@
      */
     public Xoroshiro128Plus() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(defaultGen.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -193,7 +194,7 @@
      */
     public Xoroshiro128Plus(byte[] seed) {
         // Convert the seed to 2 long values, which are not both zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 2, 2);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 2, 2);
         long x0 = data[0], x1 = data[1];
         this.x0 = x0;
         this.x1 = x1;
--- a/src/java.base/share/classes/java/util/random/Xoroshiro128StarStar.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/Xoroshiro128StarStar.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,13 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.LeapableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link Xoroshiro128StarStar} implements
- * interfaces {@link RandomNumberGenerator} and {@link LeapableRNG},
+ * interfaces {@link RandomGenerator} and {@link LeapableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new {@link Xoroshiro128StarStar} objects
@@ -81,7 +82,7 @@
  *
  * @since 14
  */
-public final class Xoroshiro128StarStar implements LeapableRNG {
+public final class Xoroshiro128StarStar implements LeapableGenerator {
 
     /*
      * Implementation Overview.
@@ -114,7 +115,7 @@
      *
      * File organization: First the non-public methods that constitute the
      * main algorithm, then the public methods.  Note that many methods are
-     * defined by classes {@link AbstractJumpableRNG} and {@link AbstractRNG}.
+     * defined by classes {@link AbstractJumpableGenerator} and {@link AbstractGenerator}.
      */
 
     /* ---------------- static fields ---------------- */
@@ -122,7 +123,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong DEFAULT_GEN = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong DEFAULT_GEN = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is 2**128 - 1.
@@ -154,8 +155,8 @@
         // If x0 and x1 are both zero, we must choose nonzero values.
         if ((x0 | x1) == 0) {
             // At least one of the two values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(x0 += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = (x0 += RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(x0 += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = (x0 += RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -174,8 +175,8 @@
         //
         // The x values are then filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixStafford13(seed ^= RNGSupport.SILVER_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+        this(RandomSupport.mixStafford13(seed ^= RandomSupport.SILVER_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -186,7 +187,7 @@
      */
     public Xoroshiro128StarStar() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(DEFAULT_GEN.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -198,7 +199,7 @@
      */
     public Xoroshiro128StarStar(byte[] seed) {
         // Convert the seed to 2 long values, which are not both zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 2, 2);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 2, 2);
         long x0 = data[0], x1 = data[1];
         this.x0 = x0;
         this.x1 = x1;
--- a/src/java.base/share/classes/java/util/random/Xoshiro256StarStar.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/Xoshiro256StarStar.java	Fri Jul 26 15:37:05 2019 -0300
@@ -27,12 +27,13 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator.LeapableGenerator;
 
 /**
  * A generator of uniform pseudorandom values applicable for use in
  * (among other contexts) isolated parallel computations that may
  * generate subtasks.  Class {@link Xoshiro256StarStar} implements
- * interfaces {@link RandomNumberGenerator} and {@link LeapableRNG},
+ * interfaces {@link RandomGenerator} and {@link LeapableGenerator},
  * and therefore supports methods for producing pseudorandomly chosen
  * numbers of type {@code int}, {@code long}, {@code float}, and {@code double}
  * as well as creating new {@link Xoshiro256StarStar} objects
@@ -89,7 +90,7 @@
  *
  * @since 14
  */
-public final class Xoshiro256StarStar implements LeapableRNG {
+public final class Xoshiro256StarStar implements LeapableGenerator {
 
     /*
      * Implementation Overview.
@@ -128,7 +129,7 @@
     /**
      * The seed generator for default constructors.
      */
-    private static final AtomicLong DEFAULT_GEN = new AtomicLong(RNGSupport.initialSeed());
+    private static final AtomicLong DEFAULT_GEN = new AtomicLong(RandomSupport.initialSeed());
 
     /*
      * The period of this generator, which is 2**256 - 1.
@@ -164,10 +165,10 @@
         // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
         if ((x0 | x1 | x2 | x3) == 0) {
             // At least three of the four values generated here will be nonzero.
-            this.x0 = RNGSupport.mixStafford13(x0 += RNGSupport.GOLDEN_RATIO_64);
-            this.x1 = (x0 += RNGSupport.GOLDEN_RATIO_64);
-            this.x2 = (x0 += RNGSupport.GOLDEN_RATIO_64);
-            this.x3 = (x0 += RNGSupport.GOLDEN_RATIO_64);
+            this.x0 = RandomSupport.mixStafford13(x0 += RandomSupport.GOLDEN_RATIO_64);
+            this.x1 = (x0 += RandomSupport.GOLDEN_RATIO_64);
+            this.x2 = (x0 += RandomSupport.GOLDEN_RATIO_64);
+            this.x3 = (x0 += RandomSupport.GOLDEN_RATIO_64);
         }
     }
 
@@ -186,10 +187,10 @@
         //
         // The x values are then filled in as if by a SplitMix PRNG with
         // GOLDEN_RATIO_64 as the gamma value and Stafford13 as the mixer.
-        this(RNGSupport.mixStafford13(seed ^= RNGSupport.SILVER_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed += RNGSupport.GOLDEN_RATIO_64),
-             RNGSupport.mixStafford13(seed + RNGSupport.GOLDEN_RATIO_64));
+        this(RandomSupport.mixStafford13(seed ^= RandomSupport.SILVER_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+             RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -200,7 +201,7 @@
      */
     public Xoshiro256StarStar() {
         // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
-        this(DEFAULT_GEN.getAndAdd(RNGSupport.GOLDEN_RATIO_64));
+        this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
     }
 
     /**
@@ -212,7 +213,7 @@
      */
     public Xoshiro256StarStar(byte[] seed) {
         // Convert the seed to 4 long values, which are not all zero.
-        long[] data = RNGSupport.convertSeedBytesToLongs(seed, 4, 4);
+        long[] data = RandomSupport.convertSeedBytesToLongs(seed, 4, 4);
         long x0 = data[0], x1 = data[1], x2 = data[2], x3 = data[3];
         this.x0 = x0;
         this.x1 = x1;
--- a/src/java.base/share/classes/module-info.java	Fri Jul 26 15:20:31 2019 -0300
+++ b/src/java.base/share/classes/module-info.java	Fri Jul 26 15:37:05 2019 -0300
@@ -350,7 +350,7 @@
     uses java.time.chrono.AbstractChronology;
     uses java.time.chrono.Chronology;
     uses java.time.zone.ZoneRulesProvider;
-    uses java.util.random.RandomNumberGenerator;
+    uses java.util.random.RandomGenerator;
     uses java.util.spi.CalendarDataProvider;
     uses java.util.spi.CalendarNameProvider;
     uses java.util.spi.CurrencyNameProvider;
@@ -375,7 +375,7 @@
     provides java.nio.file.spi.FileSystemProvider with
         jdk.internal.jrtfs.JrtFileSystemProvider;
 
-    provides java.util.random.RandomNumberGenerator with
+    provides java.util.random.RandomGenerator with
         java.util.random.L128X256MixRandom,
         java.util.random.L32X64MixRandom,
         java.util.random.L64X1024MixRandom,