Back to index...
/*
 * Copyright (c) 2021, 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.security.SecureRandom;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import jdk.internal.util.random.RandomSupport;
import jdk.internal.util.random.RandomSupport.*;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
 * 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 pseudorandomly
 * chosen value, or by invoking a method that returns a stream of
 * pseudorandomly 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 {@code 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, first a value is always chosen uniformly 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>
 * (notice that this set is a <i>subset</i> of the set of
 * <i>all representable floating-point values</i> between 0.0 (inclusive) and 1.0 (exclusive));
 * then if an explicit range was specified, then the chosen number is
 * computationally scaled and translated so as to appear to have been chosen
 * approximately uniformly from that explicit 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
 * pseudorandomly 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 pseudorandom manner from the same range.
 *
 * <p> Every object that implements the {@link RandomGenerator} interface by
 * using a pseudorandom algorithm is assumed to contain a finite amount of
 * state. Using such an object to generate a pseudorandomly chosen value alters
 * its state by computing a new state as a function of the current state,
 * without reference to any information other than the current 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> Objects that implement {@link RandomGenerator} are typically not
 * cryptographically secure. Consider instead using {@link SecureRandom} to get
 * a cryptographically secure pseudorandom number generator for use by
 * security-sensitive applications. Note, however, that {@link SecureRandom}
 * does implement the {@link RandomGenerator} interface, so that instances of
 * {@link SecureRandom} may be used interchangeably with other types of
 * pseudorandom generators in applications that do not require a secure
 * generator.
 *
 * <p>Unless explicit stated otherwise, the use of null for any method argument
 * will cause a NullPointerException.
 *
 * @since 17
 *
 */
public interface RandomGenerator {
     /**
     * Returns an instance of {@link RandomGenerator} that utilizes the
     * {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
     *
     * @param name  Name of random number generator
     *              <a href="package-summary.html#algorithms">algorithm</a>
     *
     * @return An instance of {@link RandomGenerator}
     *
     * @throws NullPointerException if name is null
     * @throws IllegalArgumentException if the named algorithm is not found
     */
    static RandomGenerator of(String name) {
        Objects.requireNonNull(name);
        return RandomGeneratorFactory.of(name, RandomGenerator.class);
    }
    /**
     * Returns a {@link RandomGenerator} meeting the minimal requirement
     * of having an <a href="package-summary.html#algorithms">algorithm</a>
     * whose state bits are greater than or equal 64.
     *
     * @implSpec  Since algorithms will improve over time, there is no
     * guarantee that this method will return the same algorithm over time.
     * <p> The default implementation selects L32X64MixRandom.
     *
     * @return a {@link RandomGenerator}
     */
    static RandomGenerator getDefault() {
        return of("L32X64MixRandom");
    }
    /**
     * Return true if the implementation of RandomGenerator (algorithm) has been
     * marked for deprecation.
     *
     * @implNote Random number generator algorithms evolve over time; new
     * algorithms will be introduced and old algorithms will
     * lose standing. If an older algorithm is deemed unsuitable
     * for continued use, it will be marked as deprecated to indicate
     * that it may be removed at some point in the future.
     *
     * @return true if the implementation of RandomGenerator (algorithm) has been
     *         marked for deprecation
     *
     * @implSpec The default implementation checks for the @Deprecated annotation.
     */
     default boolean isDeprecated() {
        return this.getClass().isAnnotationPresent(Deprecated.class);
     }
    /**
     * 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
     * {@link RandomGenerator#doubles(long) doubles}
     * ({@link Long#MAX_VALUE Long.MAX_VALUE}).
     *
     * @implSpec The default implementation produces a sequential stream
     * that repeatedly calls {@link RandomGenerator#nextDouble 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 not finite,
     *         or {@code randomNumberBound} is not finite, or {@code randomNumberOrigin}
     *         is greater than or equal to {@code randomNumberBound}
     *
     * @implNote It is permitted to implement this method in a manner equivalent to
     * {@link RandomGenerator#doubles(long, double, double) doubles}
     * ({@link Long#MAX_VALUE Long.MAX_VALUE}, randomNumberOrigin, randomNumberBound).
     *
     * @implSpec The default implementation produces a sequential stream that repeatedly
     * calls {@link RandomGenerator#nextDouble(double, double) 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
     *
     * @implSpec The default implementation produces a sequential stream
     * that repeatedly calls {@link RandomGenerator#nextDouble 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 not finite,
     *         or {@code randomNumberBound} is not finite, or {@code randomNumberOrigin}
     *         is greater than or equal to {@code randomNumberBound}
     *
     * @implSpec The default implementation produces a sequential stream that repeatedly
     * calls {@link RandomGenerator#nextDouble(double, double)  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 {@link RandomGenerator#ints(long) ints}
     * ({@link Long#MAX_VALUE Long.MAX_VALUE}).
     *
     * @implSpec The default implementation produces a sequential stream
     * that repeatedly calls {@link RandomGenerator#nextInt() 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
     * {@link RandomGenerator#ints(long, int, int) ints}
     * ({@link Long#MAX_VALUE Long.MAX_VALUE}, randomNumberOrigin, randomNumberBound).
     *
     * @implSpec The default implementation produces a sequential stream that repeatedly
     * calls {@link RandomGenerator#nextInt(int, int) 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
     *
     * @implSpec The default implementation produces a sequential stream
     * that repeatedly calls {@link RandomGenerator#nextInt() 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}
     *
     * @implSpec The default implementation produces a sequential stream that repeatedly
     * calls {@link RandomGenerator#nextInt(int, int) 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 {@link RandomGenerator#longs(long) longs}
     * ({@link Long#MAX_VALUE Long.MAX_VALUE}).
     *
     * @implSpec The default implementation produces a sequential stream
     * that repeatedly calls {@link RandomGenerator#nextLong() 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
     * {@link RandomGenerator#longs(long, long, long) longs}
     * ({@link Long#MAX_VALUE Long.MAX_VALUE}, randomNumberOrigin, randomNumberBound).
     *
     * @implSpec The default implementation produces a sequential stream that repeatedly
     * calls {@link RandomGenerator#nextLong(long, long) 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
     *
     * @implSpec The default implementation produces a sequential stream
     * that repeatedly calls {@link RandomGenerator#nextLong() 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}
     *
     * @implSpec The default implementation produces a sequential stream that repeatedly
     * calls {@link RandomGenerator#nextLong(long, long) 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 {@link RandomGenerator#nextInt() 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
     *
     * @implSpec The default implementation produces a result based on the
     * sign bit of a number generated by {@link nextInt()}.
     */
    default boolean nextBoolean() {
        return nextInt() < 0;
    }
    /**
     * Fills a user-supplied byte array with generated byte values
     * pseudorandomly chosen uniformly from the range of values between -128
     * (inclusive) and 127 (inclusive).
     *
     * @implNote Algorithm used to fill the byte array;
     *           <pre>{@code
     *           void nextBytes(byte[] bytes) {
     *               int i = 0;
     *               int len = bytes.length;
     *               for (int words = len >> 3; words--> 0; ) {
     *                   long rnd = nextLong();
     *                   for (int n = 8; n--> 0; rnd >>>= Byte.SIZE)
     *                       bytes[i++] = (byte)rnd;
     *               }
     *               if (i < len)
     *                   for (long rnd = nextLong(); i < len; rnd >>>= Byte.SIZE)
     *                       bytes[i++] = (byte)rnd;
     *           }}</pre>
     *
     * @param  bytes the byte array to fill with pseudorandom bytes
     * @throws NullPointerException if bytes is null
     *
     * @implSpec The default implementation produces results from repeated calls
     * to {@link nextLong()}.
     */
    default void nextBytes(byte[] bytes) {
        int i = 0;
        int len = bytes.length;
        for (int words = len >> 3; words--> 0; ) {
            long rnd = nextLong();
            for (int n = 8; n--> 0; rnd >>>= Byte.SIZE)
                bytes[i++] = (byte)rnd;
        }
        if (i < len)
            for (long rnd = nextLong(); i < len; rnd >>>= Byte.SIZE)
                bytes[i++] = (byte)rnd;
    }
    /**
     * Returns a pseudorandom {@code float} value between zero (inclusive) and
     * one (exclusive).
     *
     * @return a pseudorandom {@code float} value between zero (inclusive) and one (exclusive)
     *
     * @implSpec The default implementation uses the 24 high-order bits from a call to
     * {@link RandomGenerator#nextInt() nextInt}().
     */
    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
     *         both positive and finite
     *
     * @implSpec The default implementation checks that {@code bound} is a
     * positive finite float. Then invokes {@code nextFloat()}, scaling
     * the result so that the final result lies between {@code 0.0f} (inclusive)
     * and {@code bound} (exclusive).
     */
    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 if {@code origin} is not finite,
     *         or {@code bound} is not finite, or {@code origin}
     *         is greater than or equal to {@code bound}
     *
     * @implSpec The default implementation checks that {@code origin} and
     * {@code bound} are positive finite floats. Then invokes
     * {@code nextFloat()}, scaling and translating the result so that the final
     * result lies between {@code origin} (inclusive) and {@code bound}
     * (exclusive).
     */
    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).
     *
     * @return a pseudorandom {@code double} value between zero (inclusive)
     *         and one (exclusive)
     *
     * @implSpec The default implementation uses the 53 high-order bits from a call to
     * {@link RandomGenerator#nextLong nextLong}().
     */
    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
     *         both positive and finite
     *
     * @implSpec The default implementation checks that {@code bound} is a
     * positive finite double. Then invokes {@code nextDouble()}, scaling
     * the result so that the final result lies between {@code 0.0} (inclusive)
     * and {@code bound} (exclusive).
     */
    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 if {@code origin} is not finite,
     *         or {@code bound} is not finite, or {@code origin}
     *         is greater than or equal to {@code bound}
     *
     * @implSpec The default implementation checks that {@code origin} and
     * {@code bound} are positive finite doubles. Then calls
     * {@code nextDouble()}, scaling and translating the result so that the final
     * result lies between {@code origin} (inclusive) and {@code bound}
     * (exclusive).
     */
    default double nextDouble(double origin, double bound) {
        RandomSupport.checkRange(origin, bound);
        return RandomSupport.boundedNextDouble(this, origin, bound);
    }
    /**
     * Returns a pseudorandomly chosen {@code int} value.
     *
     * @return a pseudorandomly chosen {@code int} value
     *
     * @implSpec The default implementation uses the 32 high-order bits from a call to
     * {@link RandomGenerator#nextLong nextLong}().
     */
    default 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
     *
     * @implSpec The default implementation checks that {@code bound} is a
     * positive {@code int}. Then invokes {@code nextInt()}, limiting the result
     * to be greater than or equal zero and less than {@code bound}. If {@code bound}
     * is a power of two then limiting is a simple masking operation. Otherwise,
     * the result is re-calculated by invoking {@code nextInt()} until the
     * result is greater than or equal zero and less than {@code 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}
     *
     * @implSpec The default implementation checks that {@code origin} and
     * {@code bound} are positive {@code ints}. Then invokes {@code nextInt()},
     * limiting the result to be greater that or equal {@code origin} and less
     * than {@code bound}. If {@code bound} is a power of two then limiting is a
     * simple masking operation. Otherwise, the result is re-calculated  by
     * invoking {@code nextInt()} until the result is greater than or equal
     * {@code origin} and less than {@code 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
     *
     * @implSpec The default implementation checks that {@code bound} is a
     * positive  {@code long}. Then invokes {@code nextLong()}, limiting the
     * result to be greater than or equal zero and less than {@code bound}. If
     * {@code bound} is a power of two then limiting is a simple masking
     * operation. Otherwise, the result is re-calculated by invoking
     * {@code nextLong()} until the result is greater than or equal zero and
     * less than {@code 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}
     *
     * @implSpec The default implementation checks that {@code origin} and
     * {@code bound} are positive {@code longs}. Then invokes {@code nextLong()},
     * limiting the result to be greater than or equal {@code origin} and less
     * than {@code bound}. If {@code bound} is a power of two then limiting is a
     * simple masking operation. Otherwise, the result is re-calculated by
     * invoking {@code nextLong()} until the result is greater than or equal
     * {@code origin} and less than {@code 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
     *
     * @implSpec The default implementation uses 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.
     */
    default double nextGaussian() {
        // See Knuth, TAOCP, Vol. 2, 3rd edition, Section 3.4.1 Algorithm C.
        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
     *
     * @implSpec The default implementation uses 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.
     */
    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
     *
     * @implSpec The default implementation uses 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.
     */
    default double nextExponential() {
        return RandomSupport.computeNextExponential(this);
    }
    /**
     * 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.
     *
     * <p> A generator that implements interface {@link SplittableGenerator} may
     * choose to use its {@link SplittableGenerator#splits splits}() method to
     * implement the {@link StreamableGenerator#rngs rngs}() method required by this
     * interface.
     *
     * <p> A generator that implements interface {@link JumpableGenerator} may
     * choose to use its {@link JumpableGenerator#jumps() jumps}() method to implement the
     * {@link StreamableGenerator#rngs() rngs}() method required by this interface.
     *
     * <p> A generator that implements interface {@link LeapableGenerator} may
     * choose to use its {@link LeapableGenerator#leaps() leaps}() method to
     * implement the {@link StreamableGenerator#rngs() rngs}() method required by this
     * interface.
     *
     * <p> Objects that implement {@link StreamableGenerator} are typically not
     * cryptographically secure. Consider instead using {@link SecureRandom} to
     * get a cryptographically secure pseudo-random number generator for use by
     * security-sensitive applications.
     */
    interface StreamableGenerator extends RandomGenerator {
        /**
         * Returns an instance of {@link StreamableGenerator} that utilizes the
         * {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
         *
         * @param name  Name of random number generator
         *              <a href="package-summary.html#algorithms">algorithm</a>
         *
         * @return An instance of {@link StreamableGenerator}
         *
         * @throws NullPointerException if name is null
         * @throws IllegalArgumentException if the named algorithm is not found
         */
        static StreamableGenerator of(String name) {
            Objects.requireNonNull(name);
            return RandomGeneratorFactory.of(name, StreamableGenerator.class);
        }
        /**
         * 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 are of the same
         * <a href="package-summary.html#algorithms">algorithm</a> 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 {@link StreamableGenerator#rngs(long) rngs}
         *           ({@link Long#MAX_VALUE 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 are of the same
         * <a href="package-summary.html#algorithms">algorithm</a> 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
         *
         * @implSpec The default implementation calls {@link StreamableGenerator#rngs() 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 values and 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> Objects that implement {@link SplittableGenerator} are typically not
     * cryptographically secure. Consider instead using {@link SecureRandom} to
     * get a cryptographically secure pseudo-random number generator for use by
     * security-sensitive applications.
     */
    interface SplittableGenerator extends StreamableGenerator {
        /**
         * Returns an instance of {@link SplittableGenerator} that utilizes the
         * {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
         *
         * @param name  Name of random number generator
         *              <a href="package-summary.html#algorithms">algorithm</a>
         *
         * @return An instance of {@link SplittableGenerator}
         *
         * @throws NullPointerException if name is null
         * @throws IllegalArgumentException if the named algorithm is not found
         */
        static SplittableGenerator of(String name) {
            Objects.requireNonNull(name);
            return RandomGeneratorFactory.of(name, SplittableGenerator.class);
        }
        /**
         * Returns a new pseudorandom number generator, split off from this one,
         * that implements the {@link RandomGenerator} and
         * {@link SplittableGenerator} interfaces.
         *
         * <p> This pseudorandom number generator may be used as a source of
         * pseudorandom bits used to initialize the state of 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
         *
         * @throws NullPointerException if source is null
         */
        SplittableGenerator split(SplittableGenerator source);
        /**
         * Returns an effectively unlimited stream of new pseudorandom number
         * generators, each of which implements the {@link SplittableGenerator}
         * interface.
         *
         * <p> 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 {@link SplittableGenerator#splits(long) splits}
         * ({@link Long#MAX_VALUE Long.MAX_VALUE}).
         *
         * @return a stream of {@link SplittableGenerator} objects
         *
         * @implSpec The default implementation invokes
         * {@link SplittableGenerator#splits(SplittableGenerator) splits(this)}.
         */
        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.
         *
         * <p> 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 {@link SplittableGenerator#splits(long, SplittableGenerator) splits}
         *           ({@link Long#MAX_VALUE Long.MAX_VALUE}, source).
         *
         * @throws NullPointerException if source is null
         */
        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
         * @throws NullPointerException if source is null
         */
        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
         *
         * @implSpec The default implementation calls {@link SplittableGenerator#splits() splits}().
         */
        default Stream<RandomGenerator> rngs() {
            return this.splits().map(x -> 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
         *
         * @implSpec The default implementation calls {@link SplittableGenerator#splits(long) splits}(streamSize).
         */
        default Stream<RandomGenerator> rngs(long streamSize) {
            return this.splits(streamSize).map(x -> x);
        }
    }
    /**
     * This interface is designed to provide a common protocol for objects that
     * generate pseudorandom values and can easily <i>jump</i> forward, by a
     * moderate amount (ex. 2<sup>64</sup>) 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
     * {@link JumpableGenerator#jump jump()} 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 {@link JumpableGenerator#jump jump}() 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
     * {@link JumpableGenerator#jump jump}() on a generator that was itself
     * produced by the {@link JumpableGenerator#jump jump}() method, because the
     * result may be a generator identical to another generator already produce
     * by that call to the {@link JumpableGenerator#jump jump}() method. For
     * this reason, the return type of the {@link JumpableGenerator#jumps jumps}()
     * method is {@link Stream<RandomGenerator>} rather than
     * {@link Stream<JumpableGenerator>}, even though the actual generator
     * objects in that stream likely do also implement the
     * {@link JumpableGenerator} interface.
     *
     * <p> Objects that implement {@link JumpableGenerator} are typically not
     * cryptographically secure. Consider instead using {@link SecureRandom} to
     * get a cryptographically secure pseudo-random number generator for use by
     * security-sensitive applications.
     */
    interface JumpableGenerator extends StreamableGenerator {
        /**
         * Returns an instance of {@link JumpableGenerator} that utilizes the
         * {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
         *
         * @param name  Name of random number generator
         *              <a href="package-summary.html#algorithms">algorithm</a>
         *
         * @return An instance of {@link JumpableGenerator}
         *
         * @throws NullPointerException if name is null
         * @throws IllegalArgumentException if the named algorithm is not found
         */
        static JumpableGenerator of(String name) {
            Objects.requireNonNull(name);
            return RandomGeneratorFactory.of(name, JumpableGenerator.class);
        }
        /**
         * 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
         * {@link JumpableGenerator#jump jump}() method will jump forward within
         * the state cycle of this generator object.
         *
         * @return the default jump distance (as a {@code double} value)
         */
        double jumpDistance();
        /**
         * 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
         * {@link JumpableGenerator#jumps(long) jumps}
         * ({@link Long#MAX_VALUE Long.MAX_VALUE}).
         *
         * @implSpec The default implementation produces a sequential stream that  repeatedly
         * calls {@link JumpableGenerator#copy copy}() and {@link JumpableGenerator#jump 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
         *
         * @implSpec The default implementation produces a sequential stream that  repeatedly
         * calls {@link JumpableGenerator#copy copy}() and {@link JumpableGenerator#jump 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
         *
         * @implSpec The default implementation calls {@link JumpableGenerator#jump jump}().
         */
        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
         *
         * @implSpec The default implementation calls {@link JumpableGenerator#jumps(long) 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
         *
         * @implSpec The default implementation copies this, jumps and then
         * returns the copy.
         */
        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 values and can easily not only jump
     * but also <i>leap</i> forward, by a large amount (ex. 2<sup>128</sup>), to
     * a very distant point in the state cycle.
     *
     * 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 {@link JumpableGenerator#jump() jump}() method of
     * each such generator be called to produce a substream of generator
     * objects.
     *
     * <p> Objects that implement {@link LeapableGenerator} are typically not
     * cryptographically secure. Consider instead using {@link SecureRandom} to
     * get a cryptographically secure pseudo-random number generator for use by
     * security-sensitive applications.
     */
    interface LeapableGenerator extends JumpableGenerator {
        /**
         * Returns an instance of {@link LeapableGenerator} that utilizes the
         * {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
         *
         * @param name  Name of random number generator
         *              <a href="package-summary.html#algorithms">algorithm</a>
         *
         * @return An instance of {@link LeapableGenerator}
         *
         * @throws NullPointerException if name is null
         * @throws IllegalArgumentException if the named algorithm is not found
         */
        static LeapableGenerator of(String name) {
            Objects.requireNonNull(name);
            return RandomGeneratorFactory.of(name, LeapableGenerator.class);
        }
        /**
         * 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
         * {@link LeapableGenerator#leap() leap}() method will leap forward within
         * the state cycle of this generator object.
         *
         * @return the default leap distance (as a {@code double} value)
         */
        double leapDistance();
        /**
         * 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
         * {@link LeapableGenerator#leaps(long) leaps}
         * ({@link  Long#MAX_VALUE Long.MAX_VALUE}).
         *
         * @implSpec The default implementation produces a sequential stream that  repeatedly
         * calls {@link LeapableGenerator#copy() copy}() and {@link LeapableGenerator#leap() 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
         *
         * @implSpec The default implementation produces a sequential stream that  repeatedly
         *           calls {@link LeapableGenerator#copy() copy}() and {@link LeapableGenerator#leap() 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
         *
         * @implSpec The default implementation copies this, leaps and then
         * returns the copy.
         */
        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 values and can easily <i>jump</i>
     * forward, by an arbitrary amount, to a 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 {@link JumpableGenerator#jump() jump}() 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 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
     * {@link JumpableGenerator#jump() jump}() 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> Objects that implement {@link ArbitrarilyJumpableGenerator} are
     * typically not cryptographically secure. Consider instead using
     * {@link SecureRandom} to get a cryptographically secure pseudo-random
     * number generator for use by security-sensitive applications.
     */
    interface ArbitrarilyJumpableGenerator extends LeapableGenerator {
        /**
         * Returns an instance of {@link ArbitrarilyJumpableGenerator} that
         * utilizes the {@code name} <a href="package-summary.html#algorithms">algorithm</a>.
         *
         * @param name  Name of random number generator
         *              <a href="package-summary.html#algorithms">algorithm</a>
         *
         * @return An instance of {@link ArbitrarilyJumpableGenerator}
         *
         * @throws NullPointerException if name is null
         * @throws IllegalArgumentException if the named algorithm is not found
         */
        static ArbitrarilyJumpableGenerator of(String name) {
            Objects.requireNonNull(name);
            return RandomGeneratorFactory.of(name, ArbitrarilyJumpableGenerator.class);
        }
        /**
         * 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
         *                                  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 not greater than
         *                                  or equal to 0.0, or is 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
         * {@link ArbitrarilyJumpableGenerator#jumpDistance() jumpDistance}().
         *
         * @implSpec The default implementation invokes jump(jumpDistance()).
         */
        default void jump() { jump(jumpDistance()); }
        /**
         * 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
         *
         * @throws IllegalArgumentException if {@code distance} is not greater than
         *                                  or equal to 0.0, or is greater than the
         *                                  period of this generator
         *
         * @implSpec The default implementation is equivalent to
         * {@link ArbitrarilyJumpableGenerator#jumps(long) jumps}
         * ({@link Long#MAX_VALUE 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 or if
         *                                  {@code distance} is not greater than
         *                                  or equal to 0.0, or is greater than the
         *                                  period of this generator
         *
         * @implSpec The default implementation is equivalent to
         * jumps(distance).limit(streamSize).
         */
        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
         * {@link ArbitrarilyJumpableGenerator#leapDistance() leapDistance}().
         */
        default void leap() { jump(leapDistance()); }
        /**
         * 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
         *
         * @throws IllegalArgumentException if {@code distance} is not greater than
         *                                  or equal to 0.0, or is greater than the
         *                                  period of this generator
         *
         * @implSpec The default implementation copies this, jumps(distance) and then
         * returns the copy.
         */
        default ArbitrarilyJumpableGenerator copyAndJump(double distance) {
            ArbitrarilyJumpableGenerator result = copy();
            jump(distance);
            return result;
        }
    }
}
Back to index...