diff --git a/src/java.base/share/classes/java/security/SecureRandom.java b/src/java.base/share/classes/java/security/SecureRandom.java index 9f4c87d59655..9f5eae3e36de 100644 --- a/src/java.base/share/classes/java/security/SecureRandom.java +++ b/src/java.base/share/classes/java/security/SecureRandom.java @@ -25,11 +25,13 @@ package java.security; +import java.math.BigInteger; import java.util.*; +import java.util.random.RandomGenerator; import java.util.regex.*; - import java.security.Provider.Service; +import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; import sun.security.provider.SunEntries; @@ -147,6 +149,10 @@ * @since 1.1 */ +@RandomGeneratorProperties( + name = "SecureRandom", + isStochastic = true +) public class SecureRandom extends java.util.Random { private static final Debug pdebug = diff --git a/src/java.base/share/classes/java/util/Random.java b/src/java.base/share/classes/java/util/Random.java index 35540095410a..9c2f1534cf1b 100644 --- a/src/java.base/share/classes/java/util/Random.java +++ b/src/java.base/share/classes/java/util/Random.java @@ -24,21 +24,26 @@ */ package java.util; + import java.io.*; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.DoubleConsumer; -import java.util.function.IntConsumer; -import java.util.function.LongConsumer; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; -import java.util.stream.StreamSupport; + +import jdk.internal.util.random.RandomSupport.AbstractSpliteratorGenerator; +import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties; +import jdk.internal.util.random.RandomSupport.RandomIntsSpliterator; +import jdk.internal.util.random.RandomSupport.RandomLongsSpliterator; +import jdk.internal.util.random.RandomSupport.RandomDoublesSpliterator; +import static jdk.internal.util.random.RandomSupport.*; import jdk.internal.misc.Unsafe; /** * An instance of this class is used to generate a stream of - * pseudorandom numbers. The class uses a 48-bit seed, which is + * pseudorandom numbers; its period is only 248. + * The class uses a 48-bit seed, which is * modified using a linear congruential formula. (See Donald E. Knuth, * The Art of Computer Programming, Volume 2, Third * edition: Seminumerical Algorithms, Section 3.2.1.) @@ -74,7 +79,14 @@ * @author Frank Yellin * @since 1.0 */ -public class Random implements java.io.Serializable { +@SuppressWarnings("exports") +@RandomGeneratorProperties( + name = "Random", + i = 48, j = 0, k = 0, + equidistribution = 0 +) +public class Random extends AbstractSpliteratorGenerator + implements java.io.Serializable { /** use serialVersionUID from JDK 1.1 for interoperability */ @java.io.Serial static final long serialVersionUID = 3905348978240129619L; @@ -92,11 +104,6 @@ public class Random implements java.io.Serializable { private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53) - // IllegalArgumentException messages - static final String BadBound = "bound must be positive"; - static final String BadRange = "bound must be greater than origin"; - static final String BadSize = "size must be non-negative"; - /** * Creates a new random number generator. This constructor sets * the seed of the random number generator to a value very likely @@ -118,17 +125,18 @@ private static long seedUniquifier() { } private static final AtomicLong seedUniquifier - = new AtomicLong(8682522807148012L); + = new AtomicLong(8682522807148012L); /** * Creates a new random number generator using a single {@code long} seed. * The seed is the initial value of the internal state of the pseudorandom * number generator which is maintained by method {@link #next}. * - *
The invocation {@code new Random(seed)} is equivalent to: - *
{@code + * @implSpec The invocation {@code new Random(seed)} is equivalent to: + ** * @param seed the initial seed * @see #setSeed(long) @@ -211,9 +219,9 @@ protected int next(int bits) { * byte array. The number of random bytes produced is equal to * the length of the byte array. * - *{@code * Random rnd = new Random(); - * rnd.setSeed(seed);}+ * rnd.setSeed(seed); + * }
The method {@code nextBytes} is implemented by class {@code Random} - * as if by: - *
{@code + * @implSpec The method {@code nextBytes} is + * implemented by class {@code Random} as if by: + *{@code * public void nextBytes(byte[] bytes) { * for (int i = 0; i < bytes.length; ) * for (int rnd = nextInt(), n = Math.min(bytes.length - i, 4); @@ -225,90 +233,15 @@ protected int next(int bits) { * @throws NullPointerException if the byte array is null * @since 1.1 */ + @Override public void nextBytes(byte[] bytes) { for (int i = 0, len = bytes.length; i < len; ) for (int rnd = nextInt(), - n = Math.min(len - i, Integer.SIZE/Byte.SIZE); + n = Math.min(len - i, Integer.SIZE/Byte.SIZE); n-- > 0; rnd >>= Byte.SIZE) bytes[i++] = (byte)rnd; } - /** - * The form of nextLong used by LongStream Spliterators. If - * origin is greater than bound, acts as unbounded form of - * nextLong, else as bounded form. - * - * @param origin the least value, unless greater than bound - * @param bound the upper bound (exclusive), must not equal origin - * @return a pseudorandom value - */ - final long internalNextLong(long origin, long bound) { - long r = nextLong(); - if (origin < bound) { - long n = bound - origin, m = n - 1; - if ((n & m) == 0L) // power of two - r = (r & m) + origin; - else if (n > 0L) { // reject over-represented candidates - for (long u = r >>> 1; // ensure nonnegative - u + m - (r = u % n) < 0L; // rejection check - u = nextLong() >>> 1) // retry - ; - r += origin; - } - else { // range not representable as long - while (r < origin || r >= bound) - r = nextLong(); - } - } - return r; - } - - /** - * The form of nextInt used by IntStream Spliterators. - * For the unbounded case: uses nextInt(). - * For the bounded case with representable range: uses nextInt(int bound) - * For the bounded case with unrepresentable range: uses nextInt() - * - * @param origin the least value, unless greater than bound - * @param bound the upper bound (exclusive), must not equal origin - * @return a pseudorandom value - */ - final int internalNextInt(int origin, int bound) { - if (origin < bound) { - int n = bound - origin; - if (n > 0) { - return nextInt(n) + origin; - } - else { // range not representable as int - int r; - do { - r = nextInt(); - } while (r < origin || r >= bound); - return r; - } - } - else { - return nextInt(); - } - } - - /** - * The form of nextDouble used by DoubleStream Spliterators. - * - * @param origin the least value, unless greater than bound - * @param bound the upper bound (exclusive), must not equal origin - * @return a pseudorandom value - */ - final double internalNextDouble(double origin, double bound) { - double r = nextDouble(); - if (origin < bound) { - r = r * (bound - origin) + origin; - if (r >= bound) // correct for rounding - r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); - } - return r; - } - /** * Returns the next pseudorandom, uniformly distributed {@code int} * value from this random number generator's sequence. The general @@ -316,9 +249,9 @@ final double internalNextDouble(double origin, double bound) { * pseudorandomly generated and returned. All 232 possible * {@code int} values are produced with (approximately) equal probability. * - *The method {@code nextInt} is implemented by class {@code Random} - * as if by: - *
{@code + * @implSpec The method {@code nextInt} is + * implemented by class {@code Random} as if by: + *{@code * public int nextInt() { * return next(32); * }}@@ -326,6 +259,7 @@ final double internalNextDouble(double origin, double bound) { * @return the next pseudorandom, uniformly distributed {@code int} * value from this random number generator's sequence */ + @Override public int nextInt() { return next(32); } @@ -337,9 +271,11 @@ public int nextInt() { * {@code nextInt} is that one {@code int} value in the specified range * is pseudorandomly generated and returned. All {@code bound} possible * {@code int} values are produced with (approximately) equal - * probability. The method {@code nextInt(int bound)} is implemented by + * probability. + * + * @implSpec The method {@code nextInt(int bound)} is implemented by * class {@code Random} as if by: - *{@code + *{@code * public int nextInt(int bound) { * if (bound <= 0) * throw new IllegalArgumentException("bound must be positive"); @@ -384,15 +320,15 @@ public int nextInt() { * @throws IllegalArgumentException if bound is not positive * @since 1.2 */ + @Override public int nextInt(int bound) { if (bound <= 0) - throw new IllegalArgumentException(BadBound); - + throw new IllegalArgumentException(BAD_BOUND); int r = next(31); int m = bound - 1; if ((bound & m) == 0) // i.e., bound is a power of 2 r = (int)((bound * (long)r) >> 31); - else { + else { // reject over-represented candidates for (int u = r; u - (r = u % bound) + m < 0; u = next(31)) @@ -400,16 +336,15 @@ public int nextInt(int bound) { } return r; } - /** * Returns the next pseudorandom, uniformly distributed {@code long} * value from this random number generator's sequence. The general * contract of {@code nextLong} is that one {@code long} value is * pseudorandomly generated and returned. * - *The method {@code nextLong} is implemented by class {@code Random} + * @implSpec The method {@code nextLong} is implemented by class {@code Random} * as if by: - *
{@code + *{@code * public long nextLong() { * return ((long)next(32) << 32) + next(32); * }}@@ -420,6 +355,7 @@ public int nextInt(int bound) { * @return the next pseudorandom, uniformly distributed {@code long} * value from this random number generator's sequence */ + @Override public long nextLong() { // it's okay that the bottom word remains signed. return ((long)(next(32)) << 32) + next(32); @@ -433,9 +369,9 @@ public long nextLong() { * values {@code true} and {@code false} are produced with * (approximately) equal probability. * - *The method {@code nextBoolean} is implemented by class {@code Random} - * as if by: - *
{@code + * @implSpec The method {@code nextBoolean} is implemented by class + * {@code Random} as if by: + *{@code * public boolean nextBoolean() { * return next(1) != 0; * }}@@ -445,6 +381,7 @@ public long nextLong() { * sequence * @since 1.2 */ + @Override public boolean nextBoolean() { return next(1) != 0; } @@ -462,21 +399,19 @@ public boolean nextBoolean() { * where m is a positive integer less than 224, are * produced with (approximately) equal probability. * - *The method {@code nextFloat} is implemented by class {@code Random} - * as if by: - *
{@code + * @implSpec The method {@code nextFloat} is implemented by class + * {@code Random} as if by: + *{@code * public float nextFloat() { * return next(24) / ((float)(1 << 24)); * }}- * *The hedge "approximately" is used in the foregoing description only * because the next method is only approximately an unbiased source of * independently chosen bits. If it were a perfect source of randomly * chosen bits, then the algorithm shown would choose {@code float} * values from the stated range with perfect uniformity.
* [In early versions of Java, the result was incorrectly calculated as: - *
{@code - * return next(30) / ((float)(1 << 30));}+ *{@code return next(30) / ((float)(1 << 30));}* This might seem to be equivalent, if not better, but in fact it * introduced a slight nonuniformity because of the bias in the rounding * of floating-point numbers: it was slightly more likely that the @@ -486,6 +421,7 @@ public boolean nextBoolean() { * value between {@code 0.0} and {@code 1.0} from this * random number generator's sequence */ + @Override public float nextFloat() { return next(24) / ((float)(1 << 24)); } @@ -500,35 +436,33 @@ public float nextFloat() { * range {@code 0.0d} (inclusive) to {@code 1.0d} (exclusive), is * pseudorandomly generated and returned. * - *The method {@code nextDouble} is implemented by class {@code Random} - * as if by: - *
{@code + * @implSpec The method {@code nextDouble} is implemented by class + * {@code Random} as if by: + *{@code * public double nextDouble() { * return (((long)next(26) << 27) + next(27)) * / (double)(1L << 53); * }}- * *The hedge "approximately" is used in the foregoing description only - * because the {@code next} method is only approximately an unbiased - * source of independently chosen bits. If it were a perfect source of - * randomly chosen bits, then the algorithm shown would choose - * {@code double} values from the stated range with perfect uniformity. + * because the {@code next} method is only approximately an unbiased source + * of independently chosen bits. If it were a perfect source of randomly + * chosen bits, then the algorithm shown would choose {@code double} values + * from the stated range with perfect uniformity. *
[In early versions of Java, the result was incorrectly calculated as: - *
{@code - * return (((long)next(27) << 27) + next(27)) - * / (double)(1L << 54);}+ *{@code return (((long)next(27) << 27) + next(27)) / (double)(1L << 54);}* This might seem to be equivalent, if not better, but in fact it - * introduced a large nonuniformity because of the bias in the rounding - * of floating-point numbers: it was three times as likely that the - * low-order bit of the significand would be 0 than that it would be 1! - * This nonuniformity probably doesn't matter much in practice, but we - * strive for perfection.] + * introduced a large nonuniformity because of the bias in the rounding of + * floating-point numbers: it was three times as likely that the low-order + * bit of the significand would be 0 than that it would be 1! This + * nonuniformity probably doesn't matter much in practice, but we strive + * for perfection.] * * @return the next pseudorandom, uniformly distributed {@code double} * value between {@code 0.0} and {@code 1.0} from this * random number generator's sequence * @see Math#random */ + @Override public double nextDouble() { return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT; } @@ -546,9 +480,9 @@ public double nextDouble() { * normal distribution with mean {@code 0.0} and standard deviation * {@code 1.0}, is pseudorandomly generated and returned. * - *The method {@code nextGaussian} is implemented by class + * @implSpec The method {@code nextGaussian} is implemented by class * {@code Random} as if by a threadsafe version of the following: - *
{@code + *{@code * private double nextNextGaussian; * private boolean haveNextNextGaussian = false; * @@ -569,6 +503,7 @@ public double nextDouble() { * return v1 * multiplier; * } * }}+ * * This uses the polar method of G. E. P. Box, M. E. Muller, and * G. Marsaglia, as described by Donald E. Knuth in The Art of * Computer Programming, Volume 2, third edition: Seminumerical Algorithms, @@ -581,6 +516,7 @@ public double nextDouble() { * standard deviation {@code 1.0} from this random number * generator's sequence */ + @Override public synchronized double nextGaussian() { // See Knuth, TAOCP, Vol. 2, 3rd edition, Section 3.4.1 Algorithm C. if (haveNextNextGaussian) { @@ -600,8 +536,110 @@ public synchronized double nextGaussian() { } } - // stream methods, coded in a way intended to better isolate for - // maintenance purposes the small differences across forms. + /** + * Serializable fields for Random. + * + * @serialField seed long + * seed for random computations + * @serialField nextNextGaussian double + * next Gaussian to be returned + * @serialField haveNextNextGaussian boolean + * nextNextGaussian is valid + */ + @java.io.Serial + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("seed", Long.TYPE), + new ObjectStreamField("nextNextGaussian", Double.TYPE), + new ObjectStreamField("haveNextNextGaussian", Boolean.TYPE) + }; + + /** + * Reconstitute the {@code Random} instance from a stream (that is, + * deserialize it). + * + * @param s the {@code ObjectInputStream} from which data is read + * + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a serialized class cannot be loaded + */ + @java.io.Serial + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + + ObjectInputStream.GetField fields = s.readFields(); + + // The seed is read in as {@code long} for + // historical reasons, but it is converted to an AtomicLong. + long seedVal = fields.get("seed", -1L); + if (seedVal < 0) + throw new java.io.StreamCorruptedException( + "Random: invalid seed"); + resetSeed(seedVal); + nextNextGaussian = fields.get("nextNextGaussian", 0.0); + haveNextNextGaussian = fields.get("haveNextNextGaussian", false); + } + + /** + * Save the {@code Random} instance to a stream. + * + * @param s the {@code ObjectOutputStream} to which data is written + * + * @throws IOException if an I/O error occurs + */ + @java.io.Serial + private synchronized void writeObject(ObjectOutputStream s) + throws IOException { + + // set the values of the Serializable fields + ObjectOutputStream.PutField fields = s.putFields(); + + // The seed is serialized as a long for historical reasons. + fields.put("seed", seed.get()); + fields.put("nextNextGaussian", nextNextGaussian); + fields.put("haveNextNextGaussian", haveNextNextGaussian); + + // save them + s.writeFields(); + } + + // Support for resetting seed while deserializing + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long seedOffset; + static { + try { + seedOffset = unsafe.objectFieldOffset + (Random.class.getDeclaredField("seed")); + } catch (Exception ex) { throw new Error(ex); } + } + private void resetSeed(long seedVal) { + unsafe.putReferenceVolatile(this, seedOffset, new AtomicLong(seedVal)); + } + + // Methods required by class AbstractSpliteratorGenerator + + /** + * @hidden + */ + @Override + public Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) { + return new RandomIntsSpliterator(this, index, fence, origin, bound); + } + + /** + * @hidden + */ + @Override + public Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound) { + return new RandomLongsSpliterator(this, index, fence, origin, bound); + } + + /** + * @hidden + */ + @Override + public Spliterator.OfDouble makeDoublesSpliterator(long index, long fence, double origin, double bound) { + return new RandomDoublesSpliterator(this, index, fence, origin, bound); + } /** * Returns a stream producing the given {@code streamSize} number of @@ -616,13 +654,9 @@ public synchronized double nextGaussian() { * less than zero * @since 1.8 */ + @Override public IntStream ints(long streamSize) { - if (streamSize < 0L) - throw new IllegalArgumentException(BadSize); - return StreamSupport.intStream - (new RandomIntsSpliterator - (this, 0L, streamSize, Integer.MAX_VALUE, 0), - false); + return super.ints(streamSize); } /** @@ -638,11 +672,9 @@ public IntStream ints(long streamSize) { * @return a stream of pseudorandom {@code int} values * @since 1.8 */ + @Override public IntStream ints() { - return StreamSupport.intStream - (new RandomIntsSpliterator - (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0), - false); + return super.ints(); } /** @@ -677,16 +709,9 @@ public IntStream ints() { * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ - public IntStream ints(long streamSize, int randomNumberOrigin, - int randomNumberBound) { - if (streamSize < 0L) - throw new IllegalArgumentException(BadSize); - if (randomNumberOrigin >= randomNumberBound) - throw new IllegalArgumentException(BadRange); - return StreamSupport.intStream - (new RandomIntsSpliterator - (this, 0L, streamSize, randomNumberOrigin, randomNumberBound), - false); + @Override + public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) { + return super.ints(streamSize, randomNumberOrigin, randomNumberBound); } /** @@ -722,13 +747,9 @@ public IntStream ints(long streamSize, int randomNumberOrigin, * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ + @Override public IntStream ints(int randomNumberOrigin, int randomNumberBound) { - if (randomNumberOrigin >= randomNumberBound) - throw new IllegalArgumentException(BadRange); - return StreamSupport.intStream - (new RandomIntsSpliterator - (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), - false); + return super.ints(randomNumberOrigin, randomNumberBound); } /** @@ -744,13 +765,9 @@ public IntStream ints(int randomNumberOrigin, int randomNumberBound) { * less than zero * @since 1.8 */ + @Override public LongStream longs(long streamSize) { - if (streamSize < 0L) - throw new IllegalArgumentException(BadSize); - return StreamSupport.longStream - (new RandomLongsSpliterator - (this, 0L, streamSize, Long.MAX_VALUE, 0L), - false); + return super.longs(streamSize); } /** @@ -766,11 +783,9 @@ public LongStream longs(long streamSize) { * @return a stream of pseudorandom {@code long} values * @since 1.8 */ + @Override public LongStream longs() { - return StreamSupport.longStream - (new RandomLongsSpliterator - (this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L), - false); + return super.longs(); } /** @@ -810,16 +825,9 @@ public LongStream longs() { * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ - public LongStream longs(long streamSize, long randomNumberOrigin, - long randomNumberBound) { - if (streamSize < 0L) - throw new IllegalArgumentException(BadSize); - if (randomNumberOrigin >= randomNumberBound) - throw new IllegalArgumentException(BadRange); - return StreamSupport.longStream - (new RandomLongsSpliterator - (this, 0L, streamSize, randomNumberOrigin, randomNumberBound), - false); + @Override + public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) { + return super.longs(streamSize, randomNumberOrigin, randomNumberBound); } /** @@ -860,13 +868,9 @@ public LongStream longs(long streamSize, long randomNumberOrigin, * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ + @Override public LongStream longs(long randomNumberOrigin, long randomNumberBound) { - if (randomNumberOrigin >= randomNumberBound) - throw new IllegalArgumentException(BadRange); - return StreamSupport.longStream - (new RandomLongsSpliterator - (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), - false); + return super.longs(randomNumberOrigin, randomNumberBound); } /** @@ -883,13 +887,9 @@ public LongStream longs(long randomNumberOrigin, long randomNumberBound) { * less than zero * @since 1.8 */ + @Override public DoubleStream doubles(long streamSize) { - if (streamSize < 0L) - throw new IllegalArgumentException(BadSize); - return StreamSupport.doubleStream - (new RandomDoublesSpliterator - (this, 0L, streamSize, Double.MAX_VALUE, 0.0), - false); + return super.doubles(streamSize); } /** @@ -906,14 +906,12 @@ public DoubleStream doubles(long streamSize) { * @return a stream of pseudorandom {@code double} values * @since 1.8 */ + @Override public DoubleStream doubles() { - return StreamSupport.doubleStream - (new RandomDoublesSpliterator - (this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0), - false); + return super.doubles(); } - /** + /** * Returns a stream producing the given {@code streamSize} number of * pseudorandom {@code double} values, each conforming to the given origin * (inclusive) and bound (exclusive). @@ -934,22 +932,15 @@ public DoubleStream doubles() { * @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} + * @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} * @since 1.8 */ - public DoubleStream doubles(long streamSize, double randomNumberOrigin, - double randomNumberBound) { - if (streamSize < 0L) - throw new IllegalArgumentException(BadSize); - if (!(randomNumberOrigin < randomNumberBound)) - throw new IllegalArgumentException(BadRange); - return StreamSupport.doubleStream - (new RandomDoublesSpliterator - (this, 0L, streamSize, randomNumberOrigin, randomNumberBound), - false); + @Override + public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) { + return super.doubles(streamSize, randomNumberOrigin, randomNumberBound); } /** @@ -979,260 +970,8 @@ public DoubleStream doubles(long streamSize, double randomNumberOrigin, * is greater than or equal to {@code randomNumberBound} * @since 1.8 */ + @Override public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) { - if (!(randomNumberOrigin < randomNumberBound)) - throw new IllegalArgumentException(BadRange); - return StreamSupport.doubleStream - (new RandomDoublesSpliterator - (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), - false); - } - - /** - * Spliterator for int streams. We multiplex the four int - * versions into one class by treating a bound less than origin as - * unbounded, and also by treating "infinite" as equivalent to - * Long.MAX_VALUE. For splits, it uses the standard divide-by-two - * approach. The long and double versions of this class are - * identical except for types. - */ - static final class RandomIntsSpliterator implements Spliterator.OfInt { - final Random rng; - long index; - final long fence; - final int origin; - final int bound; - RandomIntsSpliterator(Random rng, long index, long fence, - int origin, int bound) { - this.rng = rng; this.index = index; this.fence = fence; - this.origin = origin; this.bound = bound; - } - - public RandomIntsSpliterator trySplit() { - long i = index, m = (i + fence) >>> 1; - return (m <= i) ? null : - new RandomIntsSpliterator(rng, i, index = m, origin, bound); - } - - public long estimateSize() { - return fence - index; - } - - public int characteristics() { - return (Spliterator.SIZED | Spliterator.SUBSIZED | - Spliterator.NONNULL | Spliterator.IMMUTABLE); - } - - public boolean tryAdvance(IntConsumer consumer) { - if (consumer == null) throw new NullPointerException(); - long i = index, f = fence; - if (i < f) { - consumer.accept(rng.internalNextInt(origin, bound)); - index = i + 1; - return true; - } - return false; - } - - public void forEachRemaining(IntConsumer consumer) { - if (consumer == null) throw new NullPointerException(); - long i = index, f = fence; - if (i < f) { - index = f; - Random r = rng; - int o = origin, b = bound; - do { - consumer.accept(r.internalNextInt(o, b)); - } while (++i < f); - } - } - } - - /** - * Spliterator for long streams. - */ - static final class RandomLongsSpliterator implements Spliterator.OfLong { - final Random rng; - long index; - final long fence; - final long origin; - final long bound; - RandomLongsSpliterator(Random rng, long index, long fence, - long origin, long bound) { - this.rng = rng; this.index = index; this.fence = fence; - this.origin = origin; this.bound = bound; - } - - public RandomLongsSpliterator trySplit() { - long i = index, m = (i + fence) >>> 1; - return (m <= i) ? null : - new RandomLongsSpliterator(rng, i, index = m, origin, bound); - } - - public long estimateSize() { - return fence - index; - } - - public int characteristics() { - return (Spliterator.SIZED | Spliterator.SUBSIZED | - Spliterator.NONNULL | Spliterator.IMMUTABLE); - } - - public boolean tryAdvance(LongConsumer consumer) { - if (consumer == null) throw new NullPointerException(); - long i = index, f = fence; - if (i < f) { - consumer.accept(rng.internalNextLong(origin, bound)); - index = i + 1; - return true; - } - return false; - } - - public void forEachRemaining(LongConsumer consumer) { - if (consumer == null) throw new NullPointerException(); - long i = index, f = fence; - if (i < f) { - index = f; - Random r = rng; - long o = origin, b = bound; - do { - consumer.accept(r.internalNextLong(o, b)); - } while (++i < f); - } - } - - } - - /** - * Spliterator for double streams. - */ - static final class RandomDoublesSpliterator implements Spliterator.OfDouble { - final Random rng; - long index; - final long fence; - final double origin; - final double bound; - RandomDoublesSpliterator(Random rng, long index, long fence, - double origin, double bound) { - this.rng = rng; this.index = index; this.fence = fence; - this.origin = origin; this.bound = bound; - } - - public RandomDoublesSpliterator trySplit() { - long i = index, m = (i + fence) >>> 1; - return (m <= i) ? null : - new RandomDoublesSpliterator(rng, i, index = m, origin, bound); - } - - public long estimateSize() { - return fence - index; - } - - public int characteristics() { - return (Spliterator.SIZED | Spliterator.SUBSIZED | - Spliterator.NONNULL | Spliterator.IMMUTABLE); - } - - public boolean tryAdvance(DoubleConsumer consumer) { - if (consumer == null) throw new NullPointerException(); - long i = index, f = fence; - if (i < f) { - consumer.accept(rng.internalNextDouble(origin, bound)); - index = i + 1; - return true; - } - return false; - } - - public void forEachRemaining(DoubleConsumer consumer) { - if (consumer == null) throw new NullPointerException(); - long i = index, f = fence; - if (i < f) { - index = f; - Random r = rng; - double o = origin, b = bound; - do { - consumer.accept(r.internalNextDouble(o, b)); - } while (++i < f); - } - } - } - - /** - * Serializable fields for Random. - * - * @serialField seed long - * seed for random computations - * @serialField nextNextGaussian double - * next Gaussian to be returned - * @serialField haveNextNextGaussian boolean - * nextNextGaussian is valid - */ - @java.io.Serial - private static final ObjectStreamField[] serialPersistentFields = { - new ObjectStreamField("seed", Long.TYPE), - new ObjectStreamField("nextNextGaussian", Double.TYPE), - new ObjectStreamField("haveNextNextGaussian", Boolean.TYPE) - }; - - /** - * Reconstitute the {@code Random} instance from a stream (that is, - * deserialize it). - * - * @param s the {@code ObjectInputStream} from which data is read - * @throws IOException if an I/O error occurs - * @throws ClassNotFoundException if a serialized class cannot be loaded - */ - @java.io.Serial - private void readObject(java.io.ObjectInputStream s) - throws java.io.IOException, ClassNotFoundException { - - ObjectInputStream.GetField fields = s.readFields(); - - // The seed is read in as {@code long} for - // historical reasons, but it is converted to an AtomicLong. - long seedVal = fields.get("seed", -1L); - if (seedVal < 0) - throw new java.io.StreamCorruptedException( - "Random: invalid seed"); - resetSeed(seedVal); - nextNextGaussian = fields.get("nextNextGaussian", 0.0); - haveNextNextGaussian = fields.get("haveNextNextGaussian", false); - } - - /** - * Save the {@code Random} instance to a stream. - * - * @param s the {@code ObjectOutputStream} to which data is written - * @throws IOException if an I/O error occurs - */ - @java.io.Serial - private synchronized void writeObject(ObjectOutputStream s) - throws IOException { - - // set the values of the Serializable fields - ObjectOutputStream.PutField fields = s.putFields(); - - // The seed is serialized as a long for historical reasons. - fields.put("seed", seed.get()); - fields.put("nextNextGaussian", nextNextGaussian); - fields.put("haveNextNextGaussian", haveNextNextGaussian); - - // save them - s.writeFields(); - } - - // Support for resetting seed while deserializing - private static final Unsafe unsafe = Unsafe.getUnsafe(); - private static final long seedOffset; - static { - try { - seedOffset = unsafe.objectFieldOffset - (Random.class.getDeclaredField("seed")); - } catch (Exception ex) { throw new Error(ex); } - } - private void resetSeed(long seedVal) { - unsafe.putReferenceVolatile(this, seedOffset, new AtomicLong(seedVal)); + return super.doubles(randomNumberOrigin, randomNumberBound); } } diff --git a/src/java.base/share/classes/java/util/SplittableRandom.java b/src/java.base/share/classes/java/util/SplittableRandom.java index ff33624a00cb..718a00514903 100644 --- a/src/java.base/share/classes/java/util/SplittableRandom.java +++ b/src/java.base/share/classes/java/util/SplittableRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -22,24 +22,24 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package java.util; +import java.math.BigInteger; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.DoubleConsumer; -import java.util.function.IntConsumer; -import java.util.function.LongConsumer; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; -import java.util.stream.StreamSupport; +import java.util.stream.Stream; +import jdk.internal.util.random.RandomSupport; +import jdk.internal.util.random.RandomSupport.AbstractSplittableGenerator; +import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties; /** - * A generator of uniform pseudorandom values applicable for use in - * (among other contexts) isolated parallel computations that may - * generate subtasks. Class {@code SplittableRandom} supports methods for - * producing pseudorandom numbers of type {@code int}, {@code long}, - * and {@code double} with similar usages as for class + * A generator of uniform pseudorandom values (with period 264) + * applicable for use in (among other contexts) isolated parallel + * computations that may generate subtasks. Class {@code SplittableRandom} + * supports methods for producing pseudorandom numbers of type {@code int}, + * {@code long}, and {@code double} with similar usages as for class * {@link java.util.Random} but differs in the following ways: * *
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. + * + *
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 + * 2w values between 0.0 (inclusive) and 1.0 (exclusive), + * where w is 23 for {@code float} values and 52 for {@code double} + * values, such that adjacent values differ by 2−w + * (notice that this set is a subset of the set of + * all representable floating-point values 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. + * + *
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. + * + *
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 period. + * (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.) + * + *
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. + * + *
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. + * + *
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} algorithm. + * + * @param name Name of random number generator + * algorithm + * + * @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 algorithm + * 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. + *
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. + * + *
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; + *
{@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; + * }}+ * + * @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 simply calls + * {@link RandomSupport#checkBound checkBound}(bound) and then + * {@link RandomSupport#boundedNextFloat 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 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 simply calls + * {@link RandomSupport#checkBound checkBound}(bound) and then + * {@link RandomSupport#boundedNextFloat boundedNextFloat}(this, 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). + * + * @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 simply calls + * {@link RandomSupport#checkBound checkBound}(bound) and then + * {@link RandomSupport#boundedNextDouble 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 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 simply calls + * {@link RandomSupport#checkBound checkBound}(bound) and then + * {@link RandomSupport#boundedNextDouble boundedNextDouble}(this, 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. + * + * @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 simply calls + * {@link RandomSupport#checkBound checkBound}(bound) and then + * {@link RandomSupport#boundedNextInt 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} + * + * @implSpec The default implementation simply calls + * {@link RandomSupport#checkBound(long) checkBound}(bound) and then + * {@link RandomSupport#boundedNextInt(RandomGenerator, int) boundedNextInt}(this, 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 simply calls + * {@link RandomSupport#checkBound checkBound}(bound) and then + * {@link RandomSupport#boundedNextLong 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} + * + * @implSpec The default implementation simply calls + * {@link RandomSupport#checkBound checkBound}(bound) and then + * {@link RandomSupport#boundedNextLong boundedNextLong}(this, 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. + * + *
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. + * + *
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. + * + *
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. + * + *
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} algorithm.
+ *
+ * @param name Name of random number generator
+ * algorithm
+ *
+ * @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
+ * algorithm 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 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.
+ *
+ * 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).
+ *
+ * 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} algorithm.
+ *
+ * @implNote Availability is determined by RandomGeneratorFactory using the
+ * service provider API to locate implementations of the RandomGenerator
+ * interface and filtering on the SplittableGenerator interface.
+ *
+ * @param name Name of random number generator
+ * algorithm
+ *
+ * @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.
+ *
+ * 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.
+ *
+ * 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 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 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 264 or the square root of its
+ * period. Implementors are advised to use algorithms whose period is at
+ * least 2127.
+ *
+ * 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 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} algorithm.
+ *
+ * @param name Name of random number generator
+ * algorithm
+ *
+ * @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 264 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 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
+ * 264. Implementors are advised to use algorithms whose period
+ * is at least 2191.
+ *
+ * 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.
+ *
+ * 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} algorithm.
+ *
+ * @param name Name of random number generator
+ * algorithm
+ *
+ * @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 296 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 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 2127.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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} algorithm.
+ *
+ * @param name Name of random number generator
+ * algorithm
+ *
+ * @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{@code logDistance} 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{@code logDistance} 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 264 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 These classes and interfaces support the definition and use of "random
+ * generators", a term covering what have traditionally been called "random
+ * number generators" as well as generators of other sorts of randomly chosen
+ * values (eg. booleans). These classes and interfaces cover not only
+ * deterministic (pseudorandom) algorithms but also generators of values that
+ * use some "truly random" physical source (stochastic algorithms perhaps making
+ * use of thermal noise, for example, or quantum-mechanical effects).
+ *
+ * The principal interface is {@link RandomGenerator}, which provides
+ * methods for requesting individual values of type {@code int}, {@code long},
+ * {@code float}, {@code double}, or {@code boolean} chosen pseudorandomly
+ * from a uniform distribution; methods for requesting values of type
+ * {@code double} chosen pseudorandomly from a normal distribution or from an
+ * exponential distribution; and methods for creating streams of values of type
+ * {@code int}, {@code long}, or {@code double} chosen pseudorandomly from a
+ * uniform distribution (such streams are spliterator-based, allowing for
+ * parallel processing of their elements). There are also static factory methods
+ * for creating an instance of a specific random number generator algorithm
+ * given its name.
+ *
+ * The principal supporting class is {@link RandomGeneratorFactory}. This
+ * can be used to generate multiple random number generators for a specific
+ * algorithm. {@link RandomGeneratorFactory} also provides methods for
+ * selecting random number generator algorithms. RandomGeneratorFactory
+ * registers implementations of {@link RandomGenerator} interface using the
+ * service provider API.
+ *
+ * An important subsidiary interface is
+ * {@link RandomGenerator.StreamableGenerator}, which provides methods for
+ * creating spliterator-based streams of {@link RandomGenerator} objects,
+ * allowing for parallel processing of these objects using multiple threads.
+ * Unlike {@link java.util.Random}, most implementations of
+ * {@link RandomGenerator} are not thread-safe. The intent is that
+ * instances should not be shared among threads; rather, each thread should have
+ * its own random generator(s) to use. The various pseudorandom algorithms
+ * provided by this package are designed so that multiple instances will (with
+ * very high probability) behave as if statistically independent.
+ *
+ * For many purposes, these are the only two interfaces that a consumer of
+ * pseudorandom values will need. There are also some more specialized
+ * interfaces that describe more specialized categories of random number
+ * generators {@link RandomGenerator.SplittableGenerator SplittableGenerator},
+ * {@link RandomGenerator.JumpableGenerator JumpableGenerator},
+ * {@link RandomGenerator.LeapableGenerator LeapableGenerator}, and
+ * {@link RandomGenerator.ArbitrarilyJumpableGenerator ArbitrarilyJumpableGenerator}
+ * that have specific strategies for creating statistically independent instances.
+ *
+ * For a multi-threaded application, one can repeat the preceding steps
+ * to create additional {@linkplain RandomGenerator RandomGenerators}, but
+ * often it is preferable to use methods of the one single initially
+ * created generator to create others like it. (One reason is that some
+ * generator algorithms, if asked to create a new set of generators all at
+ * once, can make a special effort to ensure that the new generators are
+ * statistically independent.) If the initial generator implements the
+ * interface {@link RandomGenerator.StreamableGenerator}, then the method
+ * {@link RandomGenerator.StreamableGenerator#rngs rngs()} can be used to
+ * create a stream of generators. If this is a parallel stream, then it is
+ * easy to get parallel execution by using the
+ * {@link java.util.stream.Stream#map map()} method on the stream.
+ * For a multi-threaded application that forks new threads dynamically,
+ * another approach is to use an initial generator that implements the interface
+ * {@link RandomGenerator.SplittableGenerator}, which is then considered to
+ * "belong" to the initial thread for its exclusive use; then whenever any
+ * thread needs to fork a new thread, it first uses the
+ * {@link RandomGenerator.SplittableGenerator#split split()} method of its own
+ * generator to create a new generator, which is then passed to the newly
+ * created thread for exclusive use by that new thread.
+ *
+ *
+ * There are three groups of random number generator algorithm provided
+ * in Java; Legacy group, LXM group and Xoroshiro/Xoshiro group.
+ *
+ * The legacy group includes random number generators that existed
+ * before JDK 17; Random, ThreadLocalRandom, SplittableRandom and
+ * SecureRandom. Random (LCG) is the weakest of available algorithms and it
+ * is recommended that users migrate to newer algorithms. If an application
+ * requires a random number generator algorithm that is cryptographically
+ * secure, then it should continue to use an instance of the class {@link
+ * java.security.SecureRandom}.
+ *
+ * The algorithms in the LXM group use a similar algorithm. The parameters
+ * of the algorithm can be found in algorithm name. The numbers indicate the
+ * number of bits in the lower and upper state bits respectively. Mix indicates
+ * the algorithm uses mix congruency. StarStar indicates use a double
+ * multiplier.
+ *
+ * The algorithms in the Xoroshiro/Xoshiro are more traditional algorithms
+ * where the number in the name indicates the period.
+ *
+ * For applications (such as physical simulation, machine learning, and
+ * games) that do not require a cryptographically secure algorithm, this package
+ * provides multiple implementations of interface {@link RandomGenerator} that
+ * provide trade-offs among speed, space, period, accidental correlation, and
+ * equidistribution properties.
+ *
+ * For applications with no special requirements,
+ * {@code L64X128MixRandom} has a good balance among speed, space,
+ * and period, and is suitable for both single-threaded and multi-threaded
+ * applications when used properly (a separate instance for each thread).
+ *
+ * If the application uses only a single thread, then
+ * {@code Xoroshiro128PlusPlus} is even smaller and faster, and
+ * certainly has a sufficiently long period.
+ *
+ * For an application running in a 32-bit hardware environment and using
+ * only one thread or a small number of threads, {@code L32X64MixRandom} may be a good
+ * choice.
+ *
+ * For an application that uses many threads that are allocated in one batch
+ * at the start of the computation, either a "jumpable" generator such as
+ * {@code Xoroshiro128PlusPlus} or
+ * {@code Xoshiro256PlusPlus} may be used, or a "splittable"
+ * generator such as {@code L64X128MixRandom} or
+ * {@code L64X256MixRandom} may be used.
+ *
+ * For an application that creates many threads dynamically, perhaps through
+ * the use of spliterators, a "splittable" generator such as
+ * {@code L64X128MixRandom} or {@code L64X256MixRandom} is
+ * recommended. If the number of generators created dynamically may
+ * be very large (millions or more), then using generators such as
+ * {@code L128X128MixRandom} or {@code L128X256MixRandom},
+ * which use a 128-bit parameter rather than a 64-bit parameter for their LCG
+ * subgenerator, will make it much less likely that two instances use the same
+ * state cycle.
+ *
+ * For an application that uses tuples of consecutively generated values, it
+ * may be desirable to use a generator that is k-equidistributed such
+ * that k is at least as large as the length of the tuples being
+ * generated. The generator {@code L64X256MixRandom} is provably
+ * 4-equidistributed, and {@code L64X1024MixRandom} is provably
+ * 16-equidistributed.
+ *
+ * For applications that generate large permutations, it may be best to use
+ * a generator whose period is much larger than the total number of possible
+ * permutations; otherwise it will be impossible to generate some of the
+ * intended permutations. For example, if the goal is to shuffle a deck of 52
+ * cards, the number of possible permutations is 52! (52 factorial), which is
+ * larger than 2225 (but smaller than 2226), so it may be
+ * best to use a generator whose period at least 2256, such as
+ * {@code L64X256MixRandom} or {@code L64X1024MixRandom}
+ * or {@code L128X256MixRandom} or
+ * {@code L128X1024MixRandom}. (It is of course also necessary to
+ * provide sufficiently many seed bits when the generator is initialized, or
+ * else it will still be impossible to generate some of the intended
+ * permutations.)
+ *
+ *
+ * In addition, as another life-cycle phase, an algorithm may be {@linkplain
+ * RandomGeneratorFactory#isDeprecated() deprecated}. A deprecated algorithm is
+ * not recommended for use. If a required algorithm is deprecated, it may be
+ * removed in a future release. Due to advances in random number generator
+ * algorithm development and analysis, an algorithm may be deprecated during the
+ * lifetime of a particular Java SE release. Changing the deprecation status of
+ * an algorithm is not a specification change.
+ *
+ * * ThreadLocalRandom can only be accessed via
+ * {@link java.util.concurrent.ThreadLocalRandom#current()}.
+ *
+ * A more recent category of "splittable" pseudorandom generator algorithms
+ * uses a large family of state cycles and makes some attempt to ensure that
+ * distinct instances use different state cycles; but even if two instances
+ * "accidentally" use the same state cycle, they are highly likely to traverse
+ * different regions parts of that shared state cycle. This strategy is
+ * supported by the interface {@link RandomGenerator.SplittableGenerator}.
+ * In this package, implementations of this interface include
+ * "L32X64MixRandom",
+ * "L64X128StarStarRandom",
+ * "L64X128MixRandom",
+ * "L64X256MixRandom",
+ * "L64X1024MixRandom",
+ * "L128X128MixRandom",
+ * "L128X256MixRandom", and
+ * "L128X1024MixRandom"; note that the class
+ * {@link java.util.SplittableRandom} also implements this interface.
+ *
+ *
+ * The LCG subgenerator has an update step of the form {@code s = m*s + a},
+ * where {@code s}, {@code m}, and {@code a} are all binary integers of the same
+ * size, each having p bits; {@code s} is the mutable state, the
+ * multiplier {@code m} is fixed (the same for all instances of a class) and the
+ * addend {@code a} is a parameter (a final field of the instance). The
+ * parameter {@code a} is required to be odd (this allows the LCG to have the
+ * maximal period, namely 2p); therefore there are
+ * 2p−1 distinct choices of parameter. (When the size of
+ * {@code s} is 128 bits, then we use the name "{@code sh}" below to refer to
+ * the high half of {@code s}, that is, the high-order 64 bits of {@code s}.)
+ *
+ * The Xorshift subgenerator can in principle be any one of a wide variety
+ * of xorshift algorithms; in this package it is always either
+ * {@code xoroshiro128}, {@code xoshiro256}, or {@code xoroshiro1024}, in each
+ * case without any final scrambler such as "+" or "**". Its state consists of
+ * some fixed number of {@code int} or {@code long} fields, generally named
+ * {@code x0}, {@code x1}, and so on, which can take on any values provided that
+ * they are not all zero. The collective total size of these fields is q
+ * bits; therefore the period of this subgenerator is
+ * 2q−1.
+ *
+ * Because the periods 2p and 2q−1
+ * of the two subgenerators are relatively prime, the period of any
+ * single instance of an LXM algorithm (the length of the series of generated
+ * values before it repeats) is the product of the periods of the subgenerators,
+ * that is, 2p(2q−1), which is just
+ * slightly smaller than 2(p+q). Moreover, if two
+ * distinct instances of the same LXM algorithm have different {@code a}
+ * parameters, then their cycles of produced values will be different.
+ *
+ * Generally speaking, among the "{@code L}p{@code X}q"
+ * generators, the memory required for an instance is 2p+q bits.
+ * (If q is 1024 or larger, the Xorshift state is represented as an
+ * array, so additional bits are needed for the array object header, and another
+ * 32 bits are used for an array index.)
+ *
+ * Larger values of p imply a lower probability that two distinct
+ * instances will traverse the same state cycle, and larger values of q
+ * imply that the generator is equidistributed in a larger number of dimensions
+ * (this is provably true when p is 64, and conjectured to be
+ * approximately true when p is 128). A class with "{@code Mix}" in its
+ * name uses a fairly strong mixing function with excellent avalanche
+ * characteristics; a class with "{@code StarStar}" in its name uses a weaker
+ * but faster mixing function.
+ *
+ * The specific LXM algorithms used in this package are all chosen so that
+ * the 64-bit values produced by the {@link RandomGenerator#nextLong nextLong()}
+ * method are exactly equidistributed (for example, for any specific instance of
+ * "L64X128MixRandom", over the course of its cycle each of the
+ * 264 possible {@code long} values will be produced
+ * 2128−1 times). The values produced by the
+ * {@link RandomGenerator#nextInt nextInt()},
+ * {@link RandomGenerator#nextFloat nextFloat()}, and
+ * {@link RandomGenerator#nextDouble nextDouble()} methods are likewise exactly
+ * equidistributed. Some algorithms provide a further guarantee of
+ * k-equidistribution for some k greater than 1, meaning that successive
+ * non-overlapping k-tuples of 64-bit values produced by the
+ * {@link RandomGenerator#nextLong nextLong()} method are exactly
+ * equidistributed (equally likely to occur).
+ *
+ * The following table gives the period, state size (in bits), parameter
+ * size (in bits, including the low-order bit that is required always to be a
+ * 1-bit), and equidistribution property for each of the specific LXM algorithms
+ * used in this package.
+ *
+ * For the algorithms listed above whose names begin with {@code L64} or
+ * {@code L128}, the 64-bit values produced by the
+ * {@link RandomGenerator#nextLong nextLong()} method are exactly
+ * equidistributed: every instance, over the course of its cycle, will
+ * produce each of the 264 possible {@code long} values exactly the
+ * same number of times. For example, any specific instance of
+ * "L64X256MixRandom", over the course of its cycle each of the
+ * 264 possible {@code long} values will be produced
+ * 2256−1 times. The values produced by the
+ * {@link RandomGenerator#nextInt nextInt()},
+ * {@link RandomGenerator#nextFloat nextFloat()}, and
+ * {@link RandomGenerator#nextDouble nextDouble()} methods are likewise exactly
+ * equidistributed.
+ *
+ * In addition, for the algorithms listed above whose names begin with
+ * {@code L64}, the 64-bit values produced by the
+ * {@link RandomGenerator#nextLong nextLong()} method are
+ * k-equidistributed (but not exactly k-equidistributed). To be
+ * precise, and taking "L64X256MixRandom" as an example: for
+ * any specific instance of "L64X256MixRandom", consider the
+ * (overlapping) length-4 subsequences of the cycle of 64-bit values produced by
+ * {@link RandomGenerator#nextLong nextLong()} (assuming no other methods are
+ * called that would affect the state). There are
+ * 264(2256−1) such subsequences, and each
+ * subsequence, which consists of 4 64-bit values, can have one of
+ * 2256 values. Of those 2256 subsequence values, nearly
+ * all of them (2256%minus;264) occur 264 times
+ * over the course of the entire cycle, and the other 264 subsequence
+ * values occur only 264−1 times. So the ratio of the
+ * probability of getting any specific one of the less common subsequence values
+ * and the probability of getting any specific one of the more common
+ * subsequence values is 1−2-64. (Note that the set of
+ * 264 less-common subsequence values will differ from one instance
+ * of "L64X256MixRandom" to another, as a function of the
+ * additive parameter of the LCG.) The values produced by the
+ * {@link RandomGenerator#nextInt nextInt()},
+ * {@link RandomGenerator#nextFloat nextFloat()}, and
+ * {@link RandomGenerator#nextDouble nextDouble()} methods are likewise
+ * 4-equidistributed (but not exactly 4-equidistributed).
+ *
+ * The next table gives the LCG multiplier value, the name of the specific
+ * Xorshift algorithm used, the specific numeric parameters for that Xorshift
+ * algorithm, and the mixing function for each of the specific LXM algorithms
+ * used in this package. (Note that the multiplier used for the 128-bit LCG
+ * cases is 65 bits wide, so the constant {@code 0x1d605bbb58c8abbfdL} shown in
+ * the table cannot actually be used in code; instead, only the 64 low-order
+ * bits {@code 0xd605bbb58c8abbfdL} are represented in the source code, and the
+ * missing 1-bit is handled through special coding of the multiply-add algorithm
+ * used in the LCG.)
+ *
+ * This class is mostly for library writers creating specific
+ * implementations of the interface {@link RandomGenerator}. As an
+ * internal package it is not intended for general use.
+ *
+ * @since 17
+ * @hidden
+ *
+ */
+public class RandomSupport {
+ /**
+ * Annotation providing RandomGenerator properties.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public @interface RandomGeneratorProperties {
+ /**
+ * Name of algorithm.
+ */
+ String name();
+
+ /**
+ * Category of algorithm.
+ */
+ String group() default "Legacy";
+
+ /**
+ * Algorithm period defined as:
+ *
+ * BigInteger.ONE.shiftLeft(i)
+ * .subtract(j)
+ * .shiftLeft(k)
+ */
+ int i() default 0;
+ int j() default 0;
+ int k() default 0;
+
+ /**
+ * The equidistribution of the algorithm.
+ */
+ int equidistribution() default Integer.MAX_VALUE;
+
+ /**
+ * Is the algorithm based on entropy (true random.)
+ */
+ boolean isStochastic() default false;
+
+ /**
+ * Is the algorithm assisted by hardware (fast true random.)
+ */
+ boolean isHardware() default false;
+ }
+
+ /*
+ * Implementation Overview.
+ *
+ * This class provides utility methods and constants frequently
+ * useful in the implementation 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
+ public static final String BAD_SIZE = "size must be non-negative";
+ public static final String BAD_DISTANCE = "jump distance must be finite, positive, and an exact integer";
+ public static final String BAD_BOUND = "bound must be positive";
+ public static final String BAD_FLOATING_BOUND = "bound must be finite and positive";
+ public static final String BAD_RANGE = "bound must be greater than origin";
+
+ /* ---------------- explicit constructor ---------------- */
+
+ /**
+ * Explicit constructor.
+ */
+ protected RandomSupport() {
+ }
+
+ /* ---------------- 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);
+ }
+ }
+
+ /**
+ * Checks a {@code float} upper bound value for validity.
+ *
+ * @param bound the upper bound (exclusive)
+ *
+ * @throws IllegalArgumentException if {@code bound} fails to be 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} fails to be 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 if {@code origin} is not finite, {@code bound} is not finite,
+ * or {@code bound - origin} is not 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 if {@code origin} is not finite, {@code bound} is not finite,
+ * or {@code bound - origin} is not 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 {@link RandomGenerator#nextLong() nextLong}() used by
+ * a {@link LongStream} {@link Spliterator} and by the public method
+ * {@link RandomGenerator#nextLong(long, long) nextLong}(origin, bound). If
+ * {@code origin} is greater than {@code bound}, then this method simply
+ * calls the unbounded version of
+ * {@link RandomGenerator#nextLong() nextLong}(), choosing pseudorandomly
+ * from among all 264 possible {@code long} values}, and
+ * otherwise uses one or more calls to
+ * {@link RandomGenerator#nextLong() 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 264
+ * possible {@code long} values (that is, each of the 264
+ * 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).
+ *
+ * The implementation considers four cases:
+ * 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);
+ }
+ }
+
+ /**
+ * Spliterators for int streams. These are based on abstract spliterator
+ * classes provided by class AbstractSpliteratorGenerator. Each one needs to
+ * define only a constructor and two methods.
+ */
+ public static class RandomIntsSpliterator extends RandomSupport.RandomSpliterator
+ implements Spliterator.OfInt {
+ final AbstractSpliteratorGenerator generatingGenerator;
+ final int origin;
+ final int bound;
+
+ /**
+ * RandomIntsSpliterator constructor.
+ *
+ * @param generatingGenerator base AbstractSpliteratorGenerator
+ * @param index the (inclusive) lower bound on traversal positions
+ * @param fence the (exclusive) upper bound on traversal positions
+ * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
+ * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
+ */
+ public 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) {
+ Objects.requireNonNull(consumer);
+ 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) {
+ Objects.requireNonNull(consumer);
+ 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.
+ */
+ public static class RandomLongsSpliterator extends RandomSupport.RandomSpliterator
+ implements Spliterator.OfLong {
+ final AbstractSpliteratorGenerator generatingGenerator;
+ final long origin;
+ final long bound;
+
+ /**
+ * RandomLongsSpliterator constructor.
+ *
+ * @param generatingGenerator base AbstractSpliteratorGenerator
+ * @param index the (inclusive) lower bound on traversal positions
+ * @param fence the (exclusive) upper bound on traversal positions
+ * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
+ * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
+ */
+ public 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) {
+ Objects.requireNonNull(consumer);
+ 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) {
+ Objects.requireNonNull(consumer);
+ 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.
+ */
+ public static class RandomDoublesSpliterator extends RandomSupport.RandomSpliterator
+ implements Spliterator.OfDouble {
+ final AbstractSpliteratorGenerator generatingGenerator;
+ final double origin;
+ final double bound;
+
+ /**
+ * RandomDoublesSpliterator constructor.
+ *
+ * @param generatingGenerator base AbstractSpliteratorGenerator
+ * @param index the (inclusive) lower bound on traversal positions
+ * @param fence the (exclusive) upper bound on traversal positions
+ * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
+ * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
+ */
+ public 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) {
+ Objects.requireNonNull(consumer);
+ 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) {
+ Objects.requireNonNull(consumer);
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Implementation support for the {@code nextExponential} method of
+ * {@link java.util.random.RandomGenerator}.
+ *
+ * Certain details of the algorithm used in this method may depend critically
+ * on the quality of the low-order bits delivered by {@code nextLong()}. This method
+ * 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.
+ *
+ * @implNote The reference 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.
+ *
+ * @param rng an instance of {@code RandomGenerator}, used to generate uniformly
+ * pseudorandomly chosen {@code long} values
+ *
+ * @return a nonnegative {@code double} value chosen pseudorandomly
+ * from an exponential distribution whose mean is 1
+ */
+ public static double computeNextExponential(RandomGenerator rng) {
+ /*
+ * The tables themselves, as well as a number of associated parameters, are
+ * defined in class 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 algorithm, 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
+ *
+ */
+ 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 the {@code nextGaussian} methods of
+ * {@link java.util.random.RandomGenerator}.
+ *
+ * Certain details of the algorithm used in this method may depend critically
+ * on the quality of the low-order bits delivered by {@code nextLong()}. This method
+ * 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.
+ *
+ * @implNote The reference 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.
+ *
+ * @param rng an instance of {@code RandomGenerator}, used to generate uniformly
+ * pseudorandomly chosen {@code long} values
+ *
+ * @return a nonnegative {@code double} value chosen pseudorandomly
+ * from a Gaussian (normal) distribution whose mean is 0 and whose
+ * standard deviation is 1.
+ */
+ public static double computeNextGaussian(RandomGenerator rng) {
+ /*
+ * 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 algorithm, 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
+ *
+ */
+ 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
+ * {@link RandomGenerator#ints() ints}()) in class {@link RandomGenerator}
+ * 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
+ * {@link RandomGenerator#nextInt() nextInt}(),
+ * {@link RandomGenerator#nextLong() nextLong}(),
+ * {@link AbstractSpliteratorGenerator#makeIntsSpliterator(long, long, int, int) makeIntsSpliterator}(index, fence, origin, bound),
+ * {@link AbstractSpliteratorGenerator#makeLongsSpliterator(long, long, long, long) makeLongsSpliterator}(index, fence, origin, bound),
+ * and
+ * {@link AbstractSpliteratorGenerator#makeDoublesSpliterator(long, long, double, double) makeDoublesSpliterator}(index, fence, origin, bound).
+ *
+ * This class is not public; it provides shared code to the public
+ * classes {@link AbstractSplittableGenerator}, and
+ * {@link AbstractArbitrarilyJumpableGenerator}.
+ *
+ * @since 17
+ * @hidden
+ */
+ 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.
+ */
+
+ /**
+ * Explicit constructor.
+ */
+ protected AbstractSpliteratorGenerator() {
+ }
+
+ /**
+ * Create an instance of {@link Spliterator.OfInt} that for each
+ * traversal position between the specified index (inclusive) and the
+ * specified fence (exclusive) generates a pseudorandomly chosen
+ * {@code int} value between the specified origin (inclusive) and the
+ * specified bound (exclusive).
+ *
+ * @param index the (inclusive) lower bound on traversal positions
+ * @param fence the (exclusive) upper bound on traversal positions
+ * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
+ * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
+ *
+ * @return an instance of {@link Spliterator.OfInt}
+ *
+ * @hidden
+ */
+ public abstract Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound);
+
+ /**
+ * Create an instance of {@link Spliterator.OfLong} that for each
+ * traversal position between the specified index (inclusive) and the
+ * specified fence (exclusive) generates a pseudorandomly chosen
+ * {@code long} value between the specified origin (inclusive) and the
+ * specified bound (exclusive).
+ *
+ * @param index the (inclusive) lower bound on traversal positions
+ * @param fence the (exclusive) upper bound on traversal positions
+ * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
+ * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
+ *
+ * @return an instance of {@link Spliterator.OfLong}
+ *
+ * @hidden
+ */
+ public abstract Spliterator.OfLong makeLongsSpliterator(long index, long fence, long origin, long bound);
+
+ /**
+ * Create an instance of {@link Spliterator.OfDouble} that for each
+ * traversal position between the specified index (inclusive) and the
+ * specified fence (exclusive) generates a pseudorandomly chosen
+ * {@code double} value between the specified origin (inclusive) and the
+ * specified bound (exclusive).
+ *
+ * @param index the (inclusive) lower bound on traversal positions
+ * @param fence the (exclusive) upper bound on traversal positions
+ * @param origin the (inclusive) lower bound on the pseudorandom values to be generated
+ * @param bound the (exclusive) upper bound on the pseudorandom values to be generated
+ *
+ * @return an instance of {@link Spliterator.OfDouble}
+ *
+ * @hidden
+ */
+ 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);
+ }
+
+ @Override
+ public IntStream ints(long streamSize) {
+ RandomSupport.checkStreamSize(streamSize);
+ return intStream(makeIntsSpliterator(0L, streamSize, Integer.MAX_VALUE, 0));
+ }
+
+ @Override
+ public IntStream ints() {
+ return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0));
+ }
+
+ @Override
+ public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) {
+ RandomSupport.checkStreamSize(streamSize);
+ RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+ return intStream(makeIntsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
+ }
+
+ @Override
+ public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
+ RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+ return intStream(makeIntsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound));
+ }
+
+ @Override
+ public LongStream longs(long streamSize) {
+ RandomSupport.checkStreamSize(streamSize);
+ return longStream(makeLongsSpliterator(0L, streamSize, Long.MAX_VALUE, 0L));
+ }
+
+ @Override
+ public LongStream longs() {
+ return longStream(makeLongsSpliterator(0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L));
+ }
+
+ @Override
+ public LongStream longs(long streamSize, long randomNumberOrigin,
+ long randomNumberBound) {
+ RandomSupport.checkStreamSize(streamSize);
+ RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+ return longStream(makeLongsSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
+ }
+
+ @Override
+ public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
+ RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+ return StreamSupport.longStream
+ (makeLongsSpliterator(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
+ false);
+ }
+
+ @Override
+ public DoubleStream doubles(long streamSize) {
+ RandomSupport.checkStreamSize(streamSize);
+ return doubleStream(makeDoublesSpliterator(0L, streamSize, Double.MAX_VALUE, 0.0));
+ }
+
+ @Override
+ public DoubleStream doubles() {
+ return doubleStream(makeDoublesSpliterator(0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0));
+ }
+
+ @Override
+ public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) {
+ RandomSupport.checkStreamSize(streamSize);
+ RandomSupport.checkRange(randomNumberOrigin, randomNumberBound);
+ return doubleStream(makeDoublesSpliterator(0L, streamSize, randomNumberOrigin, randomNumberBound));
+ }
+
+ @Override
+ 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 RandomGenerator#nextInt() nextInt}(),
+ * {@link RandomGenerator#nextLong() nextLong}(),
+ * {@link ArbitrarilyJumpableGenerator#copy() copy}(),
+ * {@link JumpableGenerator#jumps(long) jumps}(long),
+ * {@link ArbitrarilyJumpableGenerator#jumpPowerOfTwo(int) jumpPowerOfTwo}(logDistance),
+ * {@link JumpableGenerator#jumpDistance() jumpDistance}(),
+ * and
+ * {@link LeapableGenerator#leapDistance() leapDistance}().
+ *
+ * (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 {@link RandomSupport#initialSeed() 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 {@link RandomGenerator#ints() ints}()
+ * and {@link SplittableGenerator#splits() 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.
+ *
+ * An implementation of the {@link AbstractArbitrarilyJumpableGenerator}
+ * class must provide concrete definitions for the methods
+ * {@link RandomGenerator#nextInt() nextInt}(),
+ * {@link RandomGenerator#nextLong() nextLong}(),
+ * {@link AbstractArbitrarilyJumpableGenerator#jumps(double) jumps}(double),
+ * {@link JumpableGenerator#jumpDistance() jumpDistance}(),
+ * and
+ * {@link LeapableGenerator#leapDistance() leapDistance}().
+ * 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 17
+ * @hidden
+ */
+ 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.
+ */
+
+ /**
+ * Explicit constructor.
+ */
+ protected AbstractArbitrarilyJumpableGenerator() {
+ }
+
+ // 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 To implement a pseudorandom number generator, the programmer needs
+ * only to extend this class and provide implementations for the methods
+ * {@link RandomGenerator#nextInt() nextInt}(),
+ * {@link RandomGenerator#nextLong() nextLong}(),
+ * {@link SplittableGenerator#split(SplittableGenerator) split}(splittable).
+ *
+ * (If the pseudorandom number generator also has the ability to jump
+ * an arbitrary specified distance, then the programmer may wish to consider
+ * instead extending the class {@link AbstractArbitrarilyJumpableGenerator}.
+ * See also the class {@link AbstractSplittableWithBrineGenerator}.)
+ *
+ * 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 {@link RandomSupport#initialSeed() 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 {@link RandomGenerator#ints() ints}()
+ * and {@link SplittableGenerator#splits() 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 17
+ * @hidden
+ */
+ 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 SplittableGenerator. Most of these methods
+ * are in turn inherited from AbstractGenerator and the non-public class
+ * AbstractSpliteratorGenerator; this class provides two versions of the
+ * splits 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.
+ */
+
+ /**
+ * Explicit constructor.
+ */
+ protected AbstractSplittableGenerator() {
+ }
+
+ 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 To implement a pseudorandom number generator, the programmer needs
+ * only to extend this class and provide implementations for the methods
+ * {@link RandomGenerator#nextInt() nextInt}(),
+ * {@link RandomGenerator#nextLong() nextLong}(),
+ * {@link RandomSplitsSpliteratorWithSalt#split(SplittableGenerator, long) split}(splittable, brine).
+ *
+ * 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 {@link RandomSupport#initialSeed() 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 {@link RandomGenerator#ints() ints}()
+ * and {@link SplittableGenerator#splits() 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 17
+ * @hidden
+ */
+ public abstract static class AbstractSplittableWithBrineGenerator
+ extends AbstractSplittableGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * This class provides most of the "user API" methods needed to
+ * satisfy the interface SplittableGenerator. Most of these methods
+ * are in turn inherited from AbstractSplittableGenerator and the non-public class
+ * AbstractSpliteratorGenerator; this class provides four versions of the
+ * splits method and defines the spliterators necessary to support
+ * them.
+ *
+ * File organization: First the non-public methods needed by the class
+ * AbstractSplittableWithBrineGenerator, then the main public methods,
+ * followed by some custom spliterator classes needed for stream methods.
+ */
+
+ /**
+ * Explicit constructor.
+ */
+ protected AbstractSplittableWithBrineGenerator() {
+ }
+
+ // The salt consists groups of bits each SALT_SHIFT in size, starting from
+ // the left-hand (high-order) end of the word. We can regard them as
+ // digits base (1 << SALT_SHIFT). If SALT_SHIFT does not divide 64
+ // evenly, then any leftover bits at the low end of the word are zero.
+ // The lowest digit of the salt is set to the largest possible digit
+ // (all 1-bits, or ((1 << SALT_SHIFT) - 1)); all other digits are set
+ // to a randomly chosen value less than that largest possible digit.
+ // The salt may be shifted left by SALT_SHIFT any number of times.
+ // If any salt remains in the word, its right-hand end can be identified
+ // by searching from left to right for an occurrence of a digit that is
+ // all 1-bits (not that we ever do that; this is simply a proof that one
+ // can identify the boundary between the salt and the index if any salt
+ // remains in the word). The idea is that before computing the bitwise OR
+ // of an index and the salt, one can first check to see whether the
+ // bitwise AND is nonzero; if so, one can shift the salt left by
+ // SALT_SHIFT and try again. In this way, when the bitwise OR is
+ // computed, if the salt is nonzero then its rightmost 1-bit is to the
+ // left of the leftmost 1-bit of the index.
+
+ // We need 2 <= SALT_SHIFT <= 63 (3 through 8 are good values; 4 is probably best)
+ static final int SALT_SHIFT = 4;
+
+ // Methods required by class AbstractSpliteratorGenerator (override)
+ Spliterator This differs from
+ * {@link AbstractSplittableGenerator.RandomSplitsSpliterator} in that it
+ * provides a brine argument (a mixture of salt and an index) when
+ * calling the {@link SplittableGenerator#split() split}() method.
+ */
+ static class RandomSplitsSpliteratorWithSalt
+ extends RandomSpliterator implements Spliterator This Java class was generated automatically by a program
+ * `create_ziggurat_tables.c`.
+ *
+ * Fraction of the area under the curve that lies outside the layer
+ * boxes: 0.0156 Fraction of non-box area that lies in the tail of the
+ * distribution: 0.0330
+ */
+ static final class DoubleZigguratTables {
+
+ static final int exponentialNumberOfLayers = 252;
+ static final int exponentialLayerMask = 0xff;
+ static final int exponentialAliasMask = 0xff;
+ static final int exponentialSignCorrectionMask = 0xff;
+ static final double exponentialX0 = 7.56927469414806264;
+ static final long exponentialConvexMargin = 853965788476313645L; // unscaled convex margin = 0.0926
+
+ // exponential_X[i] = length of ziggurat layer i for exponential distribution, scaled by 2**(-63)
+ static final double[] exponentialX = { // 253 entries, which is exponential_number_of_layers+1
+ 8.2066240675348816e-19, 7.3973732351607284e-19, 6.9133313377915293e-19, 6.5647358820964533e-19,
+ 6.2912539959818508e-19, 6.0657224129604964e-19, 5.8735276103737269e-19, 5.7058850528536941e-19,
+ 5.5570945691622390e-19, 5.4232438903743953e-19, 5.3015297696508776e-19, 5.1898739257708062e-19,
+ 5.0866922617998330e-19, 4.9907492938796469e-19, 4.9010625894449536e-19, 4.8168379010649187e-19,
+ 4.7374238653644714e-19, 4.6622795807196824e-19, 4.5909509017784048e-19, 4.5230527790658154e-19,
+ 4.4582558816353960e-19, 4.3962763126368381e-19, 4.3368675967106470e-19, 4.2798143618469714e-19,
+ 4.2249273027064889e-19, 4.1720391253464110e-19, 4.1210012522465616e-19, 4.0716811225869233e-19,
+ 4.0239599631006903e-19, 3.9777309342877357e-19, 3.9328975785334499e-19, 3.8893725129310323e-19,
+ 3.8470763218720385e-19, 3.8059366138180143e-19, 3.7658872138544730e-19, 3.7268674692030177e-19,
+ 3.6888216492248162e-19, 3.6516984248800068e-19, 3.6154504153287473e-19, 3.5800337915318032e-19,
+ 3.5454079284533432e-19, 3.5115350988784242e-19, 3.4783802030030962e-19, 3.4459105288907336e-19,
+ 3.4140955396563316e-19, 3.3829066838741162e-19, 3.3523172262289001e-19, 3.3223020958685874e-19,
+ 3.2928377502804472e-19, 3.2639020528202049e-19, 3.2354741622810815e-19, 3.2075344331080789e-19,
+ 3.1800643250478609e-19, 3.1530463211820845e-19, 3.1264638534265134e-19, 3.1003012346934211e-19,
+ 3.0745435970137301e-19, 3.0491768350005559e-19, 3.0241875541094565e-19, 2.9995630232144550e-19,
+ 2.9752911310742592e-19, 2.9513603463113224e-19, 2.9277596805684267e-19, 2.9044786545442563e-19,
+ 2.8815072666416712e-19, 2.8588359639906928e-19, 2.8364556156331615e-19, 2.8143574876779799e-19,
+ 2.7925332202553125e-19, 2.7709748061152879e-19, 2.7496745707320232e-19, 2.7286251537873397e-19,
+ 2.7078194919206054e-19, 2.6872508026419050e-19, 2.6669125693153442e-19, 2.6467985271278891e-19,
+ 2.6269026499668434e-19, 2.6072191381359757e-19, 2.5877424068465143e-19, 2.5684670754248168e-19,
+ 2.5493879571835479e-19, 2.5305000499077481e-19, 2.5117985269112710e-19, 2.4932787286227806e-19,
+ 2.4749361546638660e-19, 2.4567664563848669e-19, 2.4387654298267842e-19, 2.4209290090801527e-19,
+ 2.4032532600140538e-19, 2.3857343743505147e-19, 2.3683686640614648e-19, 2.3511525560671253e-19,
+ 2.3340825872163284e-19, 2.3171553995306794e-19, 2.3003677356958333e-19, 2.2837164347843482e-19,
+ 2.2671984281957174e-19, 2.2508107358001938e-19, 2.2345504622739592e-19, 2.2184147936140775e-19,
+ 2.2024009938224424e-19, 2.1865064017486842e-19, 2.1707284280826716e-19, 2.1550645524878675e-19,
+ 2.1395123208673778e-19, 2.1240693427550640e-19, 2.1087332888245875e-19, 2.0935018885097035e-19,
+ 2.0783729277295508e-19, 2.0633442467130712e-19, 2.0484137379170616e-19, 2.0335793440326865e-19,
+ 2.0188390560756090e-19, 2.0041909115551697e-19, 1.9896329927183254e-19, 1.9751634248643090e-19,
+ 1.9607803747261946e-19, 1.9464820489157862e-19, 1.9322666924284314e-19, 1.9181325872045647e-19,
+ 1.9040780507449479e-19, 1.8901014347767504e-19, 1.8762011239677479e-19, 1.8623755346860768e-19,
+ 1.8486231138030984e-19, 1.8349423375370566e-19, 1.8213317103353295e-19, 1.8077897637931708e-19,
+ 1.7943150556069476e-19, 1.7809061685599652e-19, 1.7675617095390567e-19, 1.7542803085801941e-19,
+ 1.7410606179414531e-19, 1.7279013112017240e-19, 1.7148010823836362e-19, 1.7017586450992059e-19,
+ 1.6887727317167824e-19, 1.6758420925479093e-19, 1.6629654950527621e-19, 1.6501417230628659e-19,
+ 1.6373695760198277e-19, 1.6246478682288560e-19, 1.6119754281258616e-19, 1.5993510975569615e-19,
+ 1.5867737310692309e-19, 1.5742421952115544e-19, 1.5617553678444595e-19, 1.5493121374578016e-19,
+ 1.5369114024951992e-19, 1.5245520706841019e-19, 1.5122330583703858e-19, 1.4999532898563561e-19,
+ 1.4877116967410352e-19, 1.4755072172615974e-19, 1.4633387956347966e-19, 1.4512053813972103e-19,
+ 1.4391059287430991e-19, 1.4270393958586506e-19, 1.4150047442513381e-19, 1.4030009380730888e-19,
+ 1.3910269434359025e-19, 1.3790817277185197e-19, 1.3671642588626657e-19, 1.3552735046573446e-19,
+ 1.3434084320095729e-19, 1.3315680061998685e-19, 1.3197511901207148e-19, 1.3079569434961214e-19,
+ 1.2961842220802957e-19, 1.2844319768333099e-19, 1.2726991530715219e-19, 1.2609846895903523e-19,
+ 1.2492875177568625e-19, 1.2376065605693940e-19, 1.2259407316813331e-19, 1.2142889343858445e-19,
+ 1.2026500605581765e-19, 1.1910229895518744e-19, 1.1794065870449425e-19, 1.1677997038316715e-19,
+ 1.1562011745554883e-19, 1.1446098163777869e-19, 1.1330244275772562e-19, 1.1214437860737343e-19,
+ 1.1098666478700728e-19, 1.0982917454048923e-19, 1.0867177858084351e-19, 1.0751434490529747e-19,
+ 1.0635673859884002e-19, 1.0519882162526621e-19, 1.0404045260457141e-19, 1.0288148657544097e-19,
+ 1.0172177474144965e-19, 1.0056116419943559e-19, 9.9399497648346677e-20, 9.8236613076667446e-20,
+ 9.7072343426320094e-20, 9.5906516230690634e-20, 9.4738953224154196e-20, 9.3569469920159036e-20,
+ 9.2397875154569468e-20, 9.1223970590556472e-20, 9.0047550180852874e-20, 8.8868399582647627e-20,
+ 8.7686295519767450e-20, 8.6501005086071005e-20, 8.5312284983141187e-20, 8.4119880684385214e-20,
+ 8.2923525516513420e-20, 8.1722939648034506e-20, 8.0517828972839211e-20, 7.9307883875099226e-20,
+ 7.8092777859524425e-20, 7.6872166028429042e-20, 7.5645683383965122e-20, 7.4412942930179128e-20,
+ 7.3173533545093332e-20, 7.1927017587631075e-20, 7.0672928197666785e-20, 6.9410766239500362e-20,
+ 6.8139996829256425e-20, 6.6860045374610234e-20, 6.5570293040210081e-20, 6.4270071533368528e-20,
+ 6.2958657080923559e-20, 6.1635263438143136e-20, 6.0299033732151700e-20, 5.8949030892850181e-20,
+ 5.7584226359885930e-20, 5.6203486669597397e-20, 5.4805557413499315e-20, 5.3389043909003295e-20,
+ 5.1952387717989917e-20, 5.0493837866338355e-20, 4.9011415222629489e-20, 4.7502867933366117e-20,
+ 4.5965615001265455e-20, 4.4396673897997565e-20, 4.2792566302148588e-20, 4.1149193273430015e-20,
+ 3.9461666762606287e-20, 3.7724077131401685e-20, 3.5929164086204360e-20, 3.4067836691100565e-20,
+ 3.2128447641564046e-20, 3.0095646916399994e-20, 2.7948469455598328e-20, 2.5656913048718645e-20,
+ 2.3175209756803909e-20, 2.0426695228251291e-20, 1.7261770330213485e-20, 1.3281889259442578e-20,
+ 0.0000000000000000e+00 };
+
+ // exponential_Y[i] = value of the exponential distribution function at exponential_X[i], scaled by 2**(-63)
+ static final double[] exponentialY = { // 253 entries, which is exponential_number_of_layers+1
+ 5.5952054951127360e-23, 1.1802509982703313e-22, 1.8444423386735829e-22, 2.5439030466698309e-22,
+ 3.2737694311509334e-22, 4.0307732132706715e-22, 4.8125478319495115e-22, 5.6172914896583308e-22,
+ 6.4435820540443526e-22, 7.2902662343463681e-22, 8.1563888456321941e-22, 9.0411453683482223e-22,
+ 9.9438488486399206e-22, 1.0863906045969114e-21, 1.1800799775461269e-21, 1.2754075534831208e-21,
+ 1.3723331176377290e-21, 1.4708208794375214e-21, 1.5708388257440445e-21, 1.6723581984374566e-21,
+ 1.7753530675030514e-21, 1.8797999785104595e-21, 1.9856776587832504e-21, 2.0929667704053244e-21,
+ 2.2016497009958240e-21, 2.3117103852306179e-21, 2.4231341516125464e-21, 2.5359075901420891e-21,
+ 2.6500184374170538e-21, 2.7654554763660391e-21, 2.8822084483468604e-21, 3.0002679757547711e-21,
+ 3.1196254936130377e-21, 3.2402731888801749e-21, 3.3622039464187092e-21, 3.4854113007409036e-21,
+ 3.6098893927859475e-21, 3.7356329310971768e-21, 3.8626371568620053e-21, 3.9908978123552837e-21,
+ 4.1204111123918948e-21, 4.2511737184488913e-21, 4.3831827151633737e-21, 4.5164355889510656e-21,
+ 4.6509302085234806e-21, 4.7866648071096003e-21, 4.9236379662119969e-21, 5.0618486007478993e-21,
+ 5.2012959454434732e-21, 5.3419795423648946e-21, 5.4838992294830959e-21, 5.6270551301806347e-21,
+ 5.7714476436191935e-21, 5.9170774358950678e-21, 6.0639454319177027e-21, 6.2120528079531677e-21,
+ 6.3614009847804375e-21, 6.5119916214136427e-21, 6.6638266093481696e-21, 6.8169080672926277e-21,
+ 6.9712383363524377e-21, 7.1268199756340822e-21, 7.2836557582420336e-21, 7.4417486676430174e-21,
+ 7.6011018943746355e-21, 7.7617188330775411e-21, 7.9236030798322572e-21, 8.0867584297834842e-21,
+ 8.2511888750363333e-21, 8.4168986028103258e-21, 8.5838919938383098e-21, 8.7521736209986459e-21,
+ 8.9217482481700712e-21, 9.0926208292996504e-21, 9.2647965076751277e-21, 9.4382806153938292e-21,
+ 9.6130786730210328e-21, 9.7891963894314161e-21, 9.9666396618278840e-21, 1.0145414575932636e-20,
+ 1.0325527406345955e-20, 1.0506984617068672e-20, 1.0689792862184811e-20, 1.0873958986701341e-20,
+ 1.1059490027542400e-20, 1.1246393214695825e-20, 1.1434675972510121e-20, 1.1624345921140471e-20,
+ 1.1815410878142659e-20, 1.2007878860214202e-20, 1.2201758085082226e-20, 1.2397056973538040e-20,
+ 1.2593784151618565e-20, 1.2791948452935152e-20, 1.2991558921150600e-20, 1.3192624812605428e-20,
+ 1.3395155599094805e-20, 1.3599160970797774e-20, 1.3804650839360727e-20, 1.4011635341137284e-20,
+ 1.4220124840587164e-20, 1.4430129933836705e-20, 1.4641661452404201e-20, 1.4854730467093280e-20,
+ 1.5069348292058084e-20, 1.5285526489044050e-20, 1.5503276871808626e-20, 1.5722611510726402e-20,
+ 1.5943542737583543e-20, 1.6166083150566702e-20, 1.6390245619451956e-20, 1.6616043290999594e-20,
+ 1.6843489594561079e-20, 1.7072598247904713e-20, 1.7303383263267072e-20, 1.7535858953637607e-20,
+ 1.7770039939284241e-20, 1.8005941154528286e-20, 1.8243577854777398e-20, 1.8482965623825808e-20,
+ 1.8724120381431627e-20, 1.8967058391181452e-20, 1.9211796268653192e-20, 1.9458350989888484e-20,
+ 1.9706739900186868e-20, 1.9956980723234356e-20, 2.0209091570579904e-20, 2.0463090951473895e-20,
+ 2.0718997783083593e-20, 2.0976831401101350e-20, 2.1236611570762130e-20, 2.1498358498287976e-20,
+ 2.1762092842777868e-20, 2.2027835728562592e-20, 2.2295608758045219e-20, 2.2565434025049041e-20,
+ 2.2837334128696004e-20, 2.3111332187840010e-20, 2.3387451856080863e-20, 2.3665717337386111e-20,
+ 2.3946153402349610e-20, 2.4228785405117410e-20, 2.4513639301013211e-20, 2.4800741664897764e-20,
+ 2.5090119710298442e-20, 2.5381801309347597e-20, 2.5675815013570500e-20, 2.5972190075566336e-20,
+ 2.6270956471628253e-20, 2.6572144925351523e-20, 2.6875786932281841e-20, 2.7181914785659148e-20,
+ 2.7490561603315974e-20, 2.7801761355793055e-20, 2.8115548895739172e-20, 2.8431959988666534e-20,
+ 2.8751031345137833e-20, 2.9072800654466307e-20, 2.9397306620015486e-20, 2.9724588996191657e-20,
+ 3.0054688627228112e-20, 3.0387647487867642e-20, 3.0723508726057078e-20, 3.1062316707775905e-20,
+ 3.1404117064129991e-20, 3.1748956740850969e-20, 3.2096884050352357e-20, 3.2447948726504914e-20,
+ 3.2802201982306013e-20, 3.3159696570631373e-20, 3.3520486848272230e-20, 3.3884628843476888e-20,
+ 3.4252180327233346e-20, 3.4623200888548644e-20, 3.4997752014001677e-20, 3.5375897171869060e-20,
+ 3.5757701901149035e-20, 3.6143233905835799e-20, 3.6532563154827400e-20, 3.6925761987883572e-20,
+ 3.7322905228086981e-20, 3.7724070301302117e-20, 3.8129337363171041e-20, 3.8538789434235234e-20,
+ 3.8952512543827862e-20, 3.9370595883442399e-20, 3.9793131970351439e-20, 4.0220216822325769e-20,
+ 4.0651950144388133e-20, 4.1088435528630944e-20, 4.1529780668232712e-20, 4.1976097586926582e-20,
+ 4.2427502885307452e-20, 4.2884118005513604e-20, 4.3346069515987453e-20, 4.3813489418210257e-20,
+ 4.4286515477520838e-20, 4.4765291580372353e-20, 4.5249968120658306e-20, 4.5740702418054417e-20,
+ 4.6237659171683015e-20, 4.6741010952818368e-20, 4.7250938740823415e-20, 4.7767632507051219e-20,
+ 4.8291291852069895e-20, 4.8822126702292804e-20, 4.9360358072933852e-20, 4.9906218905182021e-20,
+ 5.0459954986625539e-20, 5.1021825965285324e-20, 5.1592106469178258e-20, 5.2171087345169234e-20,
+ 5.2759077033045284e-20, 5.3356403093325858e-20, 5.3963413910399511e-20, 5.4580480596259246e-20,
+ 5.5207999124535584e-20, 5.5846392729873830e-20, 5.6496114614193770e-20, 5.7157651009290713e-20,
+ 5.7831524654956632e-20, 5.8518298763794323e-20, 5.9218581558791713e-20, 5.9933031488338700e-20,
+ 6.0662363246796887e-20, 6.1407354758435000e-20, 6.2168855320499763e-20, 6.2947795150103727e-20,
+ 6.3745196643214394e-20, 6.4562187737537985e-20, 6.5400017881889097e-20, 6.6260077263309343e-20,
+ 6.7143920145146620e-20, 6.8053293447301698e-20, 6.8990172088133000e-20, 6.9956803158564498e-20,
+ 7.0955761794878430e-20, 7.1990022788945080e-20, 7.3063053739105458e-20, 7.4178938266266893e-20,
+ 7.5342542134173124e-20, 7.6559742171142969e-20, 7.7837749863412850e-20, 7.9185582674029512e-20,
+ 8.0614775537353300e-20, 8.2140502769818073e-20, 8.3783445978280519e-20, 8.5573129249678161e-20,
+ 8.7554459669590100e-20, 8.9802388057706877e-20, 9.2462471421151086e-20, 9.5919641344951721e-20,
+ 1.0842021724855044e-19 };
+
+ // alias_threshold[j] is a threshold for the probability mass function that has been
+ // scaled by (2**64 - 1), translated by -(2**63), and represented as a long value;
+ // in this way it can be directly compared to a randomly chosen long value.
+ static final long[] exponentialAliasThreshold = { // 256 entries
+ 9223372036854775807L, 1623796909450829958L, 2664290944894281002L, 7387971354164055035L,
+ 6515064486552722205L, 8840508362680707094L, 6099647593382923818L, 7673130333659514446L,
+ 6220332867583438718L, 5045979640552814279L, 4075305837223956071L, 3258413672162525964L,
+ 2560664887087763045L, 1957224924672900129L, 1429800935350578000L, 964606309710808688L,
+ 551043923599587587L, 180827629096889062L, -152619738120023316L, -454588624410291246L,
+ -729385126147774679L, -980551509819444511L, -1211029700667463575L, -1423284293868546830L,
+ -1619396356369066372L, -1801135830956194794L, -1970018048575634032L, -2127348289059688469L,
+ -2274257249303687482L, -2411729520096654942L, -2540626634159182211L, -2661705860113406183L,
+ -2775635634532464842L, -2883008316030448462L, -2984350790383654449L, -3080133339198118132L,
+ -3170777096303105047L, -3256660348483802362L, -3338123885075135933L, -3415475560473298752L,
+ -3488994201966444258L, -3558932970354456420L, -3625522261068040742L, -3688972217741991689L,
+ -3749474917563779627L, -3807206277531072172L, -3862327722496826830L, -3914987649156779312L,
+ -3965322714631864882L, -4013458973776911635L, -4059512885612766613L, -4103592206186240662L,
+ -4145796782586127736L, -4186219260694346585L, -4224945717447274810L, -4262056226866285147L,
+ -4297625367836519229L, -4331722680528536958L, -4364413077437472159L, -4395757214229421760L,
+ -4425811824915119137L, -4454630025296932322L, -4482261588141294467L, -4508753193105275908L,
+ -4534148654077813412L, -4558489126279965349L, -4581813295192216486L, -4604157549138252679L,
+ -4625556137145250151L, -4646041313519109096L, -4665643470413305673L, -4684391259530342697L,
+ -4702311703971745066L, -4719430301145102986L, -4735771117539946027L, -4751356876102086987L,
+ -4766209036859150188L, -4780347871385996716L, -4793792531638885869L, -4806561113635132333L,
+ -4818670716409312334L, -4830137496634465358L, -4840976719260854030L, -4851202804490332239L,
+ -4860829371376476047L, -4869869278311650511L, -4878334660640770576L, -4886236965617426832L,
+ -4893586984900802224L, -4900394884772702384L, -4906670234238884945L, -4912422031164489009L,
+ -4917658726580135697L, -4922388247283531793L, -4926618016851042065L, -4930354975163351025L,
+ -4933605596540650674L, -4936375906575303186L, -4938671497741357106L, -4940497543854583186L,
+ -4941858813449628882L, -4942759682136114354L, -4943204143989086194L, -4943195822025527282L,
+ -4942737977813222130L, -4941833520255011698L, -4940485013586759090L, -4938694684624342322L,
+ -4936464429291795314L, -4933795818458824946L, -4930690103114057265L, -4927148218896863345L,
+ -4923170790008291569L, -4918758132519196401L, -4913910257091661489L, -4908626871126522161L,
+ -4902907380349538608L, -4896750889844272240L, -4890156204540530416L, -4883121829162570096L,
+ -4875645967641780528L, -4867726521994909999L, -4859361090668119087L, -4850546966345102383L,
+ -4841281133215538414L, -4831560263698491374L, -4821380714613452974L, -4810738522790065581L,
+ -4799629400105481389L, -4788048727936296621L, -4775991551010524588L, -4763452570642113772L,
+ -4750426137329493931L, -4736906242696388587L, -4722886510751367403L, -4708360188440104938L,
+ -4693320135461420394L, -4677758813316098089L, -4661668273553495721L, -4645040145179234152L,
+ -4627865621182771687L, -4610135444140936871L, -4591839890849352486L, -4572968755929944934L,
+ -4553511334358213029L, -4533456402849109028L, -4512792200036270244L, -4491506405372580067L,
+ -4469586116675401954L, -4447017826233099938L, -4423787395382284961L, -4399880027458416864L,
+ -4375280239014124063L, -4349971829190464606L, -4323937847117722654L, -4297160557210942813L,
+ -4269621402214950684L, -4241300963840750107L, -4212178920821854874L, -4182234004204445017L,
+ -4151443949668869272L, -4119785446662323159L, -4087234084103169942L, -4053764292396165205L,
+ -4019349281473092435L, -3983960974549686930L, -3947569937258414993L, -3910145301787337104L,
+ -3871654685619049615L, -3832064104425389837L, -3791337878631529676L, -3749438533114328651L,
+ -3706326689447979465L, -3661960950051859912L, -3616297773528542022L, -3569291340409179909L,
+ -3520893408440947267L, -3471053156460649921L, -3419717015797783872L, -3366828488034801534L,
+ -3312327947826461820L, -3256152429334023226L, -3198235394669709240L, -3138506482563174262L,
+ -3076891235255164340L, -3013310801389715890L, -2947681612411392816L, -2879915029671670702L,
+ -2809916959107519276L, -2737587429961855017L, -2662820133571332903L, -2585501917733374884L,
+ -2505512231579392929L, -2422722515205190175L, -2336995527534106140L, -2248184604988712345L,
+ -2156132842510782614L, -2060672187261016979L, -1961622433929380112L, -1858790108950090508L,
+ -1751967229002904073L, -1640929916937134981L, -1525436855617591297L, -1405227557075245821L,
+ -1280020420662651897L, -1149510549536605301L, -1013367289578706928L, -871231448632089708L,
+ -722712146453677415L, -567383236774421729L, -404779231966956764L, -234390647591531478L,
+ -55658667960121553L, 132030985907831093L, 329355128892817467L, 537061298001091010L,
+ 755977262693561929L, 987022116608030929L, 1231219266829437401L, 1489711711346524770L,
+ 1763780090187559275L, 2054864117341782772L, 2364588157623782527L, 2694791916990482441L,
+ 3047567482883491349L, 3425304305830820514L, 3830744187097285423L, 4267048975685836605L,
+ 4737884547990014029L, 5247525842199011422L, 5800989391535342064L, 6404202162993303300L,
+ 7064218894258526746L, 7789505049452354354L, 8590309807749425484L, 7643763810684501605L,
+ 8891950541491453167L, 5457384281016234818L, 9083704440929285914L, 7976211653914461751L,
+ 8178631350487124609L, 2821287825726757492L, 6322989683301736617L, 4309503753387630347L,
+ 4685170734960191673L, 8404845967535252693L, 7330522972447610419L, 1960945799077061994L,
+ 4742910674644933674L, -751799822533438695L, 7023456603742021660L, 3843116882594755262L,
+ 3927231442413889375L, -9223372036854775807L, -9223372036854775807L, -9223372036854775807L };
+
+ static final byte[] exponentialAliasMap = { // 256 entries
+ (byte) 0, (byte) 0, (byte) 1, (byte)235, (byte) 3, (byte) 4, (byte) 5, (byte) 0,
+ (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
+ (byte) 0, (byte) 0, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 2, (byte) 2,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251,
+ (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)251, (byte)250, (byte)250,
+ (byte)250, (byte)250, (byte)250, (byte)250, (byte)250, (byte)249, (byte)249, (byte)249,
+ (byte)249, (byte)249, (byte)249, (byte)248, (byte)248, (byte)248, (byte)248, (byte)247,
+ (byte)247, (byte)247, (byte)247, (byte)246, (byte)246, (byte)246, (byte)245, (byte)245,
+ (byte)244, (byte)244, (byte)243, (byte)243, (byte)242, (byte)241, (byte)241, (byte)240,
+ (byte)239, (byte)237, (byte) 3, (byte) 3, (byte) 4, (byte) 4, (byte) 6, (byte) 0,
+ (byte) 0, (byte) 0, (byte) 0, (byte)236, (byte)237, (byte)238, (byte)239, (byte)240,
+ (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248,
+ (byte)249, (byte)250, (byte)251, (byte)252, (byte) 2, (byte) 0, (byte) 0, (byte) 0 };
+
+ // Implementation support for modified-ziggurat implementation of nextGaussian()
+
+ // Fraction of the area under the curve that lies outside the layer boxes: 0.0117
+ // Fraction of non-box area that lies in the tail of the distribution: 0.0236
+
+ static final int normalNumberOfLayers = 253;
+ static final int normalLayerMask = 0xff;
+ static final int normalAliasMask = 0xff;
+ static final int normalSignCorrectionMask = 0xff;
+ static final double normalX0 = 3.63600662550094578;
+ static final int normalInflectionIndex = 204;
+ static final long normalConvexMargin = 760463704284035183L; // unscaled convex margin = 0.0824
+ static final long normalConcaveMargin = 2269182951627976012L; // unscaled concave margin = 0.2460
+
+ // normal_X[i] = length of ziggurat layer i for normal distribution, scaled by 2**(-63)
+ static final double[] normalX = { // 254 entries, which is normal_number_of_layers+1
+ 3.9421662825398133e-19, 3.7204945004119012e-19, 3.5827024480628678e-19, 3.4807476236540249e-19,
+ 3.3990177171882136e-19, 3.3303778360340139e-19, 3.2709438817617550e-19, 3.2183577132495100e-19,
+ 3.1710758541840432e-19, 3.1280307407034065e-19, 3.0884520655804019e-19, 3.0517650624107352e-19,
+ 3.0175290292584600e-19, 2.9853983440705320e-19, 2.9550967462801797e-19, 2.9263997988491663e-19,
+ 2.8991225869977476e-19, 2.8731108780226291e-19, 2.8482346327101335e-19, 2.8243831535194389e-19,
+ 2.8014613964727031e-19, 2.7793871261807797e-19, 2.7580886921411212e-19, 2.7375032698308758e-19,
+ 2.7175754543391047e-19, 2.6982561247538484e-19, 2.6795015188771505e-19, 2.6612724730440033e-19,
+ 2.6435337927976633e-19, 2.6262537282028438e-19, 2.6094035335224142e-19, 2.5929570954331002e-19,
+ 2.5768906173214726e-19, 2.5611823497719608e-19, 2.5458123593393361e-19, 2.5307623292372459e-19,
+ 2.5160153867798400e-19, 2.5015559533646191e-19, 2.4873696135403158e-19, 2.4734430003079206e-19,
+ 2.4597636942892726e-19, 2.4463201347912450e-19, 2.4331015411139206e-19, 2.4200978427132955e-19,
+ 2.4072996170445879e-19, 2.3946980340903347e-19, 2.3822848067252674e-19, 2.3700521461931801e-19,
+ 2.3579927220741330e-19, 2.3460996262069972e-19, 2.3343663401054455e-19, 2.3227867054673840e-19,
+ 2.3113548974303765e-19, 2.3000654002704238e-19, 2.2889129852797606e-19, 2.2778926905921897e-19,
+ 2.2669998027527321e-19, 2.2562298398527416e-19, 2.2455785360727260e-19, 2.2350418274933911e-19,
+ 2.2246158390513294e-19, 2.2142968725296249e-19, 2.2040813954857555e-19, 2.1939660310297601e-19,
+ 2.1839475483749618e-19, 2.1740228540916853e-19, 2.1641889840016519e-19, 2.1544430956570613e-19,
+ 2.1447824613540345e-19, 2.1352044616350571e-19, 2.1257065792395107e-19, 2.1162863934653125e-19,
+ 2.1069415749082026e-19, 2.0976698805483467e-19, 2.0884691491567363e-19, 2.0793372969963634e-19,
+ 2.0702723137954107e-19, 2.0612722589717129e-19, 2.0523352580895635e-19, 2.0434594995315797e-19,
+ 2.0346432313698148e-19, 2.0258847584216418e-19, 2.0171824394771313e-19, 2.0085346846857531e-19,
+ 1.9999399530912015e-19, 1.9913967503040585e-19, 1.9829036263028144e-19, 1.9744591733545175e-19,
+ 1.9660620240469857e-19, 1.9577108494251485e-19, 1.9494043572246307e-19, 1.9411412901962161e-19,
+ 1.9329204245152935e-19, 1.9247405682708168e-19, 1.9166005600287074e-19, 1.9084992674649826e-19,
+ 1.9004355860642340e-19, 1.8924084378793725e-19, 1.8844167703488436e-19, 1.8764595551677749e-19,
+ 1.8685357872097450e-19, 1.8606444834960934e-19, 1.8527846822098793e-19, 1.8449554417517928e-19,
+ 1.8371558398354868e-19, 1.8293849726199566e-19, 1.8216419538767393e-19, 1.8139259141898448e-19,
+ 1.8062360001864453e-19, 1.7985713737964743e-19, 1.7909312115393845e-19, 1.7833147038364200e-19,
+ 1.7757210543468428e-19, 1.7681494793266395e-19, 1.7605992070083140e-19, 1.7530694770004409e-19,
+ 1.7455595397057217e-19, 1.7380686557563475e-19, 1.7305960954655264e-19, 1.7231411382940904e-19,
+ 1.7157030723311378e-19, 1.7082811937877138e-19, 1.7008748065025788e-19, 1.6934832214591352e-19,
+ 1.6861057563126349e-19, 1.6787417349268046e-19, 1.6713904869190636e-19, 1.6640513472135291e-19,
+ 1.6567236556010242e-19, 1.6494067563053266e-19, 1.6420999975549115e-19, 1.6348027311594532e-19,
+ 1.6275143120903661e-19, 1.6202340980646725e-19, 1.6129614491314931e-19, 1.6056957272604589e-19,
+ 1.5984362959313479e-19, 1.5911825197242491e-19, 1.5839337639095554e-19, 1.5766893940370800e-19,
+ 1.5694487755235889e-19, 1.5622112732380261e-19, 1.5549762510837070e-19, 1.5477430715767271e-19,
+ 1.5405110954198330e-19, 1.5332796810709688e-19, 1.5260481843056974e-19, 1.5188159577726683e-19,
+ 1.5115823505412761e-19, 1.5043467076406199e-19, 1.4971083695888395e-19, 1.4898666719118714e-19,
+ 1.4826209446506113e-19, 1.4753705118554365e-19, 1.4681146910669830e-19, 1.4608527927820112e-19,
+ 1.4535841199031451e-19, 1.4463079671711862e-19, 1.4390236205786415e-19, 1.4317303567630177e-19,
+ 1.4244274423783481e-19, 1.4171141334433217e-19, 1.4097896746642792e-19, 1.4024532987312287e-19,
+ 1.3951042255849034e-19, 1.3877416616527576e-19, 1.3803647990516385e-19, 1.3729728147547174e-19,
+ 1.3655648697200824e-19, 1.3581401079782068e-19, 1.3506976556752901e-19, 1.3432366200692418e-19,
+ 1.3357560884748263e-19, 1.3282551271542047e-19, 1.3207327801488087e-19, 1.3131880680481524e-19,
+ 1.3056199866908076e-19, 1.2980275057923788e-19, 1.2904095674948608e-19, 1.2827650848312727e-19,
+ 1.2750929400989213e-19, 1.2673919831340482e-19, 1.2596610294799512e-19, 1.2518988584399374e-19,
+ 1.2441042110056523e-19, 1.2362757876504165e-19, 1.2284122459762072e-19, 1.2205121982017852e-19,
+ 1.2125742084782245e-19, 1.2045967900166973e-19, 1.1965784020118020e-19, 1.1885174463419555e-19,
+ 1.1804122640264091e-19, 1.1722611314162064e-19, 1.1640622560939109e-19, 1.1558137724540874e-19,
+ 1.1475137369333185e-19, 1.1391601228549047e-19, 1.1307508148492592e-19, 1.1222836028063025e-19,
+ 1.1137561753107903e-19, 1.1051661125053526e-19, 1.0965108783189755e-19, 1.0877878119905372e-19,
+ 1.0789941188076655e-19, 1.0701268599703640e-19, 1.0611829414763286e-19, 1.0521591019102928e-19,
+ 1.0430518990027552e-19, 1.0338576948035472e-19, 1.0245726392923699e-19, 1.0151926522209310e-19,
+ 1.0057134029488235e-19, 9.9613028799672809e-20, 9.8643840599459914e-20, 9.7663252964755816e-20,
+ 9.6670707427623454e-20, 9.5665606240866670e-20, 9.4647308380433213e-20, 9.3615125017323508e-20,
+ 9.2568314370887282e-20, 9.1506075837638774e-20, 9.0427543267725716e-20, 8.9331777233763680e-20,
+ 8.8217756102327883e-20, 8.7084365674892319e-20, 8.5930387109612162e-20, 8.4754482764244349e-20,
+ 8.3555179508462343e-20, 8.2330848933585364e-20, 8.1079683729129853e-20, 7.9799669284133864e-20,
+ 7.8488549286072745e-20, 7.7143783700934692e-20, 7.5762496979467566e-20, 7.4341413578485329e-20,
+ 7.2876776807378431e-20, 7.1364245443525374e-20, 6.9798760240761066e-20, 6.8174368944799054e-20,
+ 6.6483992986198539e-20, 6.4719110345162767e-20, 6.2869314813103699e-20, 6.0921687548281263e-20,
+ 5.8859873575576818e-20, 5.6662675116090981e-20, 5.4301813630894571e-20, 5.1738171744494220e-20,
+ 4.8915031722398545e-20, 4.5744741890755301e-20, 4.2078802568583416e-20, 3.7625986722404761e-20,
+ 3.1628589805881879e-20, 0.0000000000000000e+00 };
+
+ // normal_Y[i] = value of the normal distribution function at normal_X[i], scaled by 2**(-63)
+ static final double[] normalY = { // 254 entries, which is normal_number_of_layers+1
+ 1.4598410796619063e-22, 3.0066613427942797e-22, 4.6129728815103466e-22, 6.2663350049234362e-22,
+ 7.9594524761881544e-22, 9.6874655021705039e-22, 1.1446877002379439e-21, 1.3235036304379167e-21,
+ 1.5049857692053131e-21, 1.6889653000719298e-21, 1.8753025382711626e-21, 2.0638798423695191e-21,
+ 2.2545966913644708e-21, 2.4473661518801799e-21, 2.6421122727763533e-21, 2.8387681187879908e-21,
+ 3.0372742567457284e-21, 3.2375775699986589e-21, 3.4396303157948780e-21, 3.6433893657997798e-21,
+ 3.8488155868912312e-21, 4.0558733309492775e-21, 4.2645300104283590e-21, 4.4747557422305067e-21,
+ 4.6865230465355582e-21, 4.8998065902775257e-21, 5.1145829672105489e-21, 5.3308305082046173e-21,
+ 5.5485291167031758e-21, 5.7676601252690476e-21, 5.9882061699178461e-21, 6.2101510795442221e-21,
+ 6.4334797782257209e-21, 6.6581781985713897e-21, 6.8842332045893181e-21, 7.1116325227957095e-21,
+ 7.3403646804903092e-21, 7.5704189502886418e-21, 7.8017853001379744e-21, 8.0344543481570017e-21,
+ 8.2684173217333118e-21, 8.5036660203915022e-21, 8.7401927820109521e-21, 8.9779904520281901e-21,
+ 9.2170523553061439e-21, 9.4573722703928820e-21, 9.6989444059269430e-21, 9.9417633789758424e-21,
+ 1.0185824195119818e-20, 1.0431122230114770e-20, 1.0677653212987396e-20, 1.0925413210432004e-20,
+ 1.1174398612392891e-20, 1.1424606118728715e-20, 1.1676032726866302e-20, 1.1928675720361027e-20,
+ 1.2182532658289373e-20, 1.2437601365406785e-20, 1.2693879923010674e-20, 1.2951366660454145e-20,
+ 1.3210060147261461e-20, 1.3469959185800733e-20, 1.3731062804473644e-20, 1.3993370251385596e-20,
+ 1.4256880988463136e-20, 1.4521594685988369e-20, 1.4787511217522902e-20, 1.5054630655196170e-20,
+ 1.5322953265335218e-20, 1.5592479504415048e-20, 1.5863210015310328e-20, 1.6135145623830982e-20,
+ 1.6408287335525592e-20, 1.6682636332737932e-20, 1.6958193971903124e-20, 1.7234961781071113e-20,
+ 1.7512941457646084e-20, 1.7792134866331487e-20, 1.8072544037271070e-20, 1.8354171164377277e-20,
+ 1.8637018603838945e-20, 1.8921088872801004e-20, 1.9206384648209468e-20, 1.9492908765815636e-20,
+ 1.9780664219333857e-20, 2.0069654159747839e-20, 2.0359881894760859e-20, 2.0651350888385696e-20,
+ 2.0944064760670539e-20, 2.1238027287557466e-20, 2.1533242400870487e-20, 2.1829714188430474e-20,
+ 2.2127446894294597e-20, 2.2426444919118270e-20, 2.2726712820637798e-20, 2.3028255314272276e-20,
+ 2.3331077273843558e-20, 2.3635183732413286e-20, 2.3940579883236352e-20, 2.4247271080830277e-20,
+ 2.4555262842160330e-20, 2.4864560847940368e-20, 2.5175170944049622e-20, 2.5487099143065929e-20,
+ 2.5800351625915997e-20, 2.6114934743643687e-20, 2.6430855019297323e-20, 2.6748119149937411e-20,
+ 2.7066734008766247e-20, 2.7386706647381193e-20, 2.7708044298153558e-20, 2.8030754376735269e-20,
+ 2.8354844484695747e-20, 2.8680322412291631e-20, 2.9007196141372126e-20, 2.9335473848423219e-20,
+ 2.9665163907753988e-20, 2.9996274894828624e-20, 3.0328815589748056e-20, 3.0662794980885287e-20,
+ 3.0998222268678760e-20, 3.1335106869588609e-20, 3.1673458420220558e-20, 3.2013286781622988e-20,
+ 3.2354602043762612e-20, 3.2697414530184806e-20, 3.3041734802864950e-20, 3.3387573667257349e-20,
+ 3.3734942177548938e-20, 3.4083851642125208e-20, 3.4434313629256243e-20, 3.4786339973011376e-20,
+ 3.5139942779411164e-20, 3.5495134432826171e-20, 3.5851927602632460e-20, 3.6210335250134172e-20,
+ 3.6570370635764384e-20, 3.6932047326575882e-20, 3.7295379204034252e-20, 3.7660380472126401e-20,
+ 3.8027065665798284e-20, 3.8395449659736649e-20, 3.8765547677510167e-20, 3.9137375301086406e-20,
+ 3.9510948480742172e-20, 3.9886283545385430e-20, 4.0263397213308566e-20, 4.0642306603393541e-20,
+ 4.1023029246790967e-20, 4.1405583099096438e-20, 4.1789986553048817e-20, 4.2176258451776819e-20,
+ 4.2564418102621759e-20, 4.2954485291566197e-20, 4.3346480298300118e-20, 4.3740423911958146e-20,
+ 4.4136337447563716e-20, 4.4534242763218286e-20, 4.4934162278076256e-20, 4.5336118991149025e-20,
+ 4.5740136500984466e-20, 4.6146239026271279e-20, 4.6554451427421133e-20, 4.6964799229185088e-20,
+ 4.7377308644364938e-20, 4.7792006598684169e-20, 4.8208920756888113e-20, 4.8628079550147814e-20,
+ 4.9049512204847653e-20, 4.9473248772842596e-20, 4.9899320163277674e-20, 5.0327758176068971e-20,
+ 5.0758595537153414e-20, 5.1191865935622696e-20, 5.1627604062866059e-20, 5.2065845653856416e-20,
+ 5.2506627530725194e-20, 5.2949987648783448e-20, 5.3395965145159426e-20, 5.3844600390237576e-20,
+ 5.4295935042099358e-20, 5.4750012104183868e-20, 5.5206875986405073e-20, 5.5666572569983821e-20,
+ 5.6129149276275792e-20, 5.6594655139902476e-20, 5.7063140886520563e-20, 5.7534659015596918e-20,
+ 5.8009263888591218e-20, 5.8487011822987583e-20, 5.8967961192659803e-20, 5.9452172535103471e-20,
+ 5.9939708666122605e-20, 6.0430634802618929e-20, 6.0925018694200531e-20, 6.1422930764402860e-20,
+ 6.1924444262401531e-20, 6.2429635426193939e-20, 6.2938583658336214e-20, 6.3451371715447563e-20,
+ 6.3968085912834963e-20, 6.4488816345752736e-20, 6.5013657128995346e-20, 6.5542706656731714e-20,
+ 6.6076067884730717e-20, 6.6613848637404196e-20, 6.7156161942412980e-20, 6.7703126395950580e-20,
+ 6.8254866562246408e-20, 6.8811513411327825e-20, 6.9373204799659681e-20, 6.9940085998959109e-20,
+ 7.0512310279279503e-20, 7.1090039553397167e-20, 7.1673445090644796e-20, 7.2262708309655784e-20,
+ 7.2858021661057338e-20, 7.3459589613035800e-20, 7.4067629754967553e-20, 7.4682374037052817e-20,
+ 7.5304070167226666e-20, 7.5932983190698547e-20, 7.6569397282483754e-20, 7.7213617789487678e-20,
+ 7.7865973566417016e-20, 7.8526819659456755e-20, 7.9196540403850560e-20, 7.9875553017037968e-20,
+ 8.0564311788901630e-20, 8.1263312996426176e-20, 8.1973100703706304e-20, 8.2694273652634034e-20,
+ 8.3427493508836792e-20, 8.4173494807453416e-20, 8.4933097052832066e-20, 8.5707219578230905e-20,
+ 8.6496899985930695e-20, 8.7303317295655327e-20, 8.8127821378859504e-20, 8.8971970928196666e-20,
+ 8.9837583239314064e-20, 9.0726800697869543e-20, 9.1642181484063544e-20, 9.2586826406702765e-20,
+ 9.3564561480278864e-20, 9.4580210012636175e-20, 9.5640015550850358e-20, 9.6752334770503130e-20,
+ 9.7928851697808831e-20, 9.9186905857531331e-20, 1.0055456271343397e-19, 1.0208407377305566e-19,
+ 1.0390360993240711e-19, 1.0842021724855044e-19 };
+
+ // alias_threshold[j] is a threshold for the probability mass function that has been
+ // scaled by (2**64 - 1), translated by -(2**63), and represented as a long value;
+ // in this way it can be directly compared to a randomly chosen long value.
+ static final long[] normalAliasThreshold = { // 256 entries
+ 9223372036854775732L, 1100243796470199922L, 7866600928967318259L, 6788754710669718688L,
+ 9022865200207136940L, 6522434035182564354L, 4723064097388367094L, 3360495653202227820L,
+ 2289663232347306830L, 1423968905585875379L, 708364817795238883L, 106102487338962592L,
+ -408333464668584328L, -853239722790494085L, -1242095211827090004L, -1585059631108655444L,
+ -1889943050267333598L, -2162852901996526266L, -2408637386596951353L, -2631196530256993348L,
+ -2833704942542501760L, -3018774289008775598L, -3188573753501888049L, -3344920681670389334L,
+ -3489349705095933019L, -3623166100045386711L, -3747487436861293578L, -3863276422709141026L,
+ -3971367044055496571L, -4072485557008423504L, -4167267476835653997L, -4256271432259158584L,
+ -4339990541931699221L, -4418861817116128356L, -4493273980399812066L, -4563574004455583972L,
+ -4630072609765608272L, -4693048910437239656L, -4752754358851355990L, -4809416110064308151L,
+ -4863239903553549801L, -4914412541525462120L, -4963104028438393907L, -5009469424783376781L,
+ -5053650458852410933L, -5095776932714599237L, -5135967952538787362L, -5174333008440005397L,
+ -5210972924976812191L, -5245980700089102084L, -5279442247516610920L, -5311437055455710870L,
+ -5342038772315685218L, -5371315728848281940L, -5399331404596850615L, -5426144845492958401L,
+ -5451811038482575296L, -5476381248268660540L, -5499903320574200237L, -5522421955754019296L,
+ -5543978956088644891L, -5564613449670076120L, -5584362093426489951L, -5603259257517942559L,
+ -5621337193067953247L, -5638626184957155131L, -5655154691206501482L, -5670949470299055313L,
+ -5686035697633988263L, -5700437072176015065L, -5714175914241450413L, -5727273255262198220L,
+ -5739748920276454057L, -5751621603817308582L, -5762908939796390234L, -5773627565922293024L,
+ -5783793183134813122L, -5793420610488485693L, -5802523835876777512L, -5811116062947540603L,
+ -5819209754528321254L, -5826816672847738703L, -5833947916812588598L, -5840613956576464230L,
+ -5846824665611918318L, -5852589350480860931L, -5857916778478181241L, -5862815203308620040L,
+ -5867292388942958035L, -5871355631785040459L, -5875011781271709877L, -5878267259014830525L,
+ -5881128076587168793L, -5883599852042383670L, -5885687825255517495L, -5887396872158140520L,
+ -5888731517940791413L, -5889695949285098191L, -5890294025685452079L, -5890529289913339019L,
+ -5890404977673728891L, -5889924026498433105L, -5889089083917111413L, -5887902514943630556L,
+ -5886366408911444323L, -5884482585689698188L, -5882252601307215732L, -5879677753010810505L,
+ -5876759083779777633L, -5873497386319005871L, -5869893206546653493L, -5865946846595933526L,
+ -5861658367342436656L, -5857027590471882377L, -5852054100098427498L, -5846737243942430862L,
+ -5841076134076202917L, -5835069647242632620L, -5828716424752710909L, -5822014871963881822L,
+ -5814963157341321336L, -5807559211102860368L, -5799800723445392235L, -5791685142351319976L,
+ -5783209670970726741L, -5774371264573181466L, -5765166627063894671L, -5755592207054728713L,
+ -5745644193480823967L, -5735318510752045177L, -5724610813425415465L, -5713516480385581414L,
+ -5702030608515423737L, -5690148005840583288L, -5677863184127162093L, -5665170350911168791L,
+ -5652063400935782694L, -5638535906971010691L, -5624581109986711207L, -5610191908648783765L,
+ -5595360848105231304L, -5580080108024969737L, -5564341489852042876L, -5548136403231016978L,
+ -5531455851558564459L, -5514290416611714856L, -5496630242199355791L, -5478465016777918644L,
+ -5459783954970839371L, -5440575777921757436L, -5420828692410297267L, -5400530368650229789L,
+ -5379667916685479525L, -5358227861290596404L, -5336196115276119372L, -5313557951090901350L,
+ -5290297970603367798L, -5266400072934326313L, -5241847420204395031L, -5216622401044877639L,
+ -5190706591710560934L, -5164080714616987256L, -5136724594109421094L, -5108617109256031912L,
+ -5079736143434386281L, -5050058530465123570L, -5019559997019987907L, -4988215101007960589L,
+ -4955997165616088151L, -4922878208649305943L, -4888828866781574127L, -4853818314291958392L,
+ -4817814175818125756L, -4780782432613346925L, -4742687321741700014L, -4703491227589533028L,
+ -4663154565006030194L, -4621635653315226847L, -4578890580363657638L, -4534873055674290590L,
+ -4489534251682380820L, -4442822631912146606L, -4394683764829968681L, -4345060121963632469L,
+ -4293890858720706245L, -4241111576152819891L, -4186654061709945180L, -4130446006793453666L,
+ -4072410698652140640L, -4012466683862855933L, -3950527400292573339L, -3886500774045756804L,
+ -3820288777448438119L, -3751786943603804843L, -3680883832458819395L, -3607460442634330728L,
+ -3531389562479403081L, -3452535052892669800L, -3370751053387208615L, -3285881101636362572L,
+ -3197757155290696249L, -3106198503163967069L, -3011010550898974052L, -2911983463889090176L,
+ -2808890647471134035L, -2701487041141521265L, -2589507199668960785L, -2472663129352313038L,
+ -2350641842148622058L, -2223102583752258356L, -2089673683718520949L, -1949948966041670625L,
+ -1803483646850545328L, -1649789631543398131L, -1488330106106063370L, -1318513295716695859L,
+ -1139685236949889721L, -951121376566993538L, -752016768187462359L, -541474585679321485L,
+ -318492605702529265L, -81947227237782935L, 169425512586600501L, 437052607251310002L,
+ 722551297576808029L, 1027761939321803391L, 1354787941562529921L, 1706044619231670700L,
+ 2084319374410687061L, 2492846399585974279L, 2935400169364870493L, 3416413484632185639L,
+ 3941127949845221101L, 4515787798750242711L, 5147892401460631081L, 5846529325404347588L,
+ 6622819682189677227L, 7490522659877439279L, 8466869998300400224L, 8216968526327386835L,
+ 4550693915429835301L, 7628019504075715697L, 6605080500885794707L, 7121156327618549405L,
+ 2484871780310660533L, 7179104797025802172L, 7066086283790288107L, 1516500120772178463L,
+ 216305945406470492L, 6295963418490399062L, 2889316805640753770L, -2712587580563247199L,
+ 6562498853480442900L, 7975754821117214681L, -9223372036854775807L, -9223372036854775807L };
+
+ static final byte[] normalAliasMap = { // 256 entries
+ (byte) 0, (byte) 0, (byte)239, (byte) 2, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
+ (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 1, (byte) 1, (byte) 1, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253, (byte)253,
+ (byte)253, (byte)253, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252, (byte)252,
+ (byte)252, (byte)252, (byte)252, (byte)252, (byte)251, (byte)251, (byte)251, (byte)251,
+ (byte)251, (byte)251, (byte)251, (byte)250, (byte)250, (byte)250, (byte)250, (byte)250,
+ (byte)249, (byte)249, (byte)249, (byte)248, (byte)248, (byte)248, (byte)247, (byte)247,
+ (byte)247, (byte)246, (byte)246, (byte)245, (byte)244, (byte)244, (byte)243, (byte)242,
+ (byte)240, (byte) 2, (byte) 2, (byte) 3, (byte) 3, (byte) 0, (byte) 0, (byte)240,
+ (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248,
+ (byte)249, (byte)250, (byte)251, (byte)252, (byte)253, (byte) 1, (byte) 0, (byte) 0 };
+
+ }
+
+}
diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java
index 7a53a645ba19..7c5fa8d341bc 100644
--- a/src/java.base/share/classes/module-info.java
+++ b/src/java.base/share/classes/module-info.java
@@ -113,6 +113,7 @@
exports java.util.concurrent.locks;
exports java.util.function;
exports java.util.jar;
+ exports java.util.random;
exports java.util.regex;
exports java.util.spi;
exports java.util.stream;
@@ -248,6 +249,8 @@
jdk.jfr;
exports jdk.internal.util.xml.impl to
jdk.jfr;
+ exports jdk.internal.util.random to
+ jdk.random;
exports sun.net to
java.net.http,
jdk.naming.dns;
@@ -356,7 +359,6 @@
exports jdk.internal.invoke to
jdk.incubator.foreign;
-
// the service types defined by the APIs in this module
uses java.lang.System.LoggerFinder;
@@ -377,6 +379,7 @@
uses java.time.chrono.AbstractChronology;
uses java.time.chrono.Chronology;
uses java.time.zone.ZoneRulesProvider;
+ uses java.util.random.RandomGenerator;
uses java.util.spi.CalendarDataProvider;
uses java.util.spi.CalendarNameProvider;
uses java.util.spi.CurrencyNameProvider;
@@ -400,4 +403,10 @@
provides java.nio.file.spi.FileSystemProvider with
jdk.internal.jrtfs.JrtFileSystemProvider;
+
+ provides java.util.random.RandomGenerator with
+ java.security.SecureRandom,
+ java.util.Random,
+ java.util.SplittableRandom;
+
}
diff --git a/src/java.base/share/native/random/create_ziggurat_tables.c b/src/java.base/share/native/random/create_ziggurat_tables.c
new file mode 100644
index 000000000000..c660be9208b1
--- /dev/null
+++ b/src/java.base/share/native/random/create_ziggurat_tables.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This program computes the parameters and arrays needed by the modified-ziggurat algorithm
+// for sampling from either an exponential distribution with mean 1 or a normal distribution
+// with mean 0 and standad deviation 1. The four arrays needed for either kind of sampler are:
+//
+// X[i] is the horizontal width of ziggurat layer i
+// Y[i] is f(X[i]), where f is the function for the exponential or normal curve
+// alias_threshold is the table of probability mass thresholds for Walker's alias method,
+// with one entry for the tail of the distributon and one entry for each overhang region
+// alias_map is the table of forwarding indices used for Walker's alias method
+//
+// The four parameters needed by the exponential sampler are:
+//
+// exponential_number_of_layers the number of layers in the ziggurat
+// exponential_X_0 the width of the box in layer 0 (which is the x-coordinate of the left end of the tail)
+// exponential_convex_margin the maximum discrepancy between the curve and a certain diagonal line above it
+//
+// The five parameters needed by the normal sampler are:
+//
+// normal_number_of_layers the number of layers in the ziggurat
+// normal_X_0 the width of the box in layer 0 (which is the x-coordinate of the left end of the tail)
+// normal_inflection_index the index of the layer containing the inflection point
+// normal_convex_margin the maximum discrepancy between the curve and a certain diagonal line above it
+// normal_concave_margin the maximum discrepancy between the curve and a certain diagonal line below it
+//
+// After computing the parameters and tables, the program prints (to standard output)
+// a complete Java source code file for a class named either FloatZigguratTables or
+// DoubleZigguratTables, according to which precision has been requested.
+
+// The only reason this program has been written as C code rather than Java code is that
+// most of the calculations need to be performed in long double precision in order to
+// be able to calculate double values of sufficient accuracy. This code relies on
+// long double math functions sqrtl, powl, expl, logl, log2l, erfl, ceill, and copysignl.
+
+// The overall modified ziggurat algorithm closely follows the description in:
+//
+// 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).
+//
+// This paper in turn refers to code available at https://bitbucket.org/cdmcfarland/fast_prng.
+// This includes a file create_layers.py of Python code for constructing the tables.
+// The C code here loosely follows the organization of that Python code. However, the Python
+// code appears to contain a number of errors and infelicities that have been corrected here:
+//
+// (1) On line 211, 1 is added to i_inflection, causing the value 205 to be printed when
+// table size is 256. Adding 1 is not correct; the correct value for printing is 204.
+//
+// (2) On line 203, 3 values are dropped from the front of the array E when computing iE_max,
+// with no explanation given. We believe this is incorrect; E[3:] should be simply E.
+//
+// (3) When the table elements are converted to printable strings using "map(str,data)",
+// precision is lost because the Python str function produces only 12 decimal digits.
+// In this C code, we print table entries using 17 decimal digits (format %23.16e),
+// because 17 decimal digits suffice to preserve the value of any double precision
+// value (and 16 decimal digits do not always suffice).
+//
+// (4) At lines 215-223, the Python code computes only a single E value for the
+// rectangle containing the inflection point of the normal distribution curve.
+// We believe it is conceptually more correct to compute two such E values,
+// one for the concave part of the curve (to the left of the inflection point)
+// and one for the convex part of the curve (to the right of the inflection point).
+//
+// We also observe that the McFarland paper asserts that the solver uses Brent's method,
+// but the solver in the Python code does not implement Brent's method. A proper
+// implementation of Brent's method (or its predecessor, Dekker's method) alternates
+// between use of the Secant Method and use of the Bisection Method according to various
+// criteria, but the Python code merely tries the Secant Method for a fixed number of
+// iterations and then switches to the Bisection Method for a calculated number of iterations.
+// Here we have translated Brent's Method into C from the Algol code in Brent's original paper.
+
+#include The {@link L128X1024MixRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L128X1024MixRandom}
+ * has 1152 bits of state plus one 128-bit instance-specific parameter.
+ *
+ * If two instances of {@link L128X1024MixRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L128X1024MixRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL128X1024MixRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L128X1024MixRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L128X1024MixRandom",
+ group = "LXM",
+ i = 1024, j = 1, k = 128,
+ equidistribution = 1
+)
+public final class L128X1024MixRandom extends AbstractSplittableWithBrineGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * The 128-bit parameter `a` is represented as two long fields `ah` and `al`.
+ * The 128-bit state variable `s` is represented as two long fields `sh` and `sl`.
+ *
+ * The split operation uses the current generator to choose 20
+ * new 64-bit long values that are then used to initialize the
+ * parameters `ah` and `al`, the state variables `sh`, `sl`,
+ * and the array `x` for a newly constructed generator.
+ *
+ * With extremely high probability, no two generators so chosen
+ * will have the same `a` parameter, and testing has indicated
+ * that the values generated by two instances of {@link L128X1024MixRandom}
+ * will be (approximately) independent if have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate 20 new 64-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /*
+ * The length of the array x.
+ */
+
+ private static final int N = 16;
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * Low half of multiplier used in the LCG portion of the algorithm;
+ * the overall multiplier is (2**64 + ML).
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL
+ * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493].
+ */
+
+ private static final long ML = 0xd605bbb58c8abbfdL;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd (therefore al must be odd).
+ */
+ private final long ah, al;
+
+ /**
+ * The per-instance state: sh and sl for the LCG; the array x for the xorshift;
+ * p is the rotating pointer into the array x.
+ * At least one of the 16 elements of the array x must be nonzero.
+ */
+ private long sh, sl;
+ private final long[] x;
+ private int p = N - 1;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param ah high half of the additive parameter for the LCG
+ * @param al low half of the additive parameter for the LCG
+ * @param sh high half of the initial state for the LCG
+ * @param sl low half of the initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ * @param x2 third word of the initial state for the xorshift generator
+ * @param x3 fourth word of the initial state for the xorshift generator
+ * @param x4 fifth word of the initial state for the xorshift generator
+ * @param x5 sixth word of the initial state for the xorshift generator
+ * @param x6 seventh word of the initial state for the xorshift generator
+ * @param x7 eight word of the initial state for the xorshift generator
+ * @param x8 ninth word of the initial state for the xorshift generator
+ * @param x9 tenth word of the initial state for the xorshift generator
+ * @param x10 eleventh word of the initial state for the xorshift generator
+ * @param x11 twelfth word of the initial state for the xorshift generator
+ * @param x12 thirteenth word of the initial state for the xorshift generator
+ * @param x13 fourteenth word of the initial state for the xorshift generator
+ * @param x14 fifteenth word of the initial state for the xorshift generator
+ * @param x15 sixteenth word of the initial state for the xorshift generator
+ */
+ public L128X1024MixRandom(long ah, long al, long sh, long sl,
+ long x0, long x1, long x2, long x3,
+ long x4, long x5, long x6, long x7,
+ long x8, long x9, long x10, long x11,
+ long x12, long x13, long x14, long x15) {
+ // Force a to be odd.
+ this.ah = ah;
+ this.al = al | 1;
+ this.sh = sh;
+ this.sl = sl;
+ this.x = new long[N];
+ this.x[0] = x0;
+ this.x[1] = x1;
+ this.x[2] = x2;
+ this.x[3] = x3;
+ this.x[4] = x4;
+ this.x[5] = x5;
+ this.x[6] = x6;
+ this.x[7] = x7;
+ this.x[8] = x8;
+ this.x[9] = x9;
+ this.x[10] = x10;
+ this.x[11] = x11;
+ this.x[12] = x12;
+ this.x[13] = x13;
+ this.x[14] = x14;
+ this.x[15] = x15;
+ // 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) {
+ long v = sh;
+ // At least fifteen of the sixteen values generated here will be nonzero.
+ for (int j = 0; j < N; j++) {
+ this.x[j] = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ }
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L128X1024MixRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L128X1024MixRandom} created with the same seed in the same
+ * program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L128X1024MixRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The seed is hashed by mixMurmur64 to produce the `a` parameter.
+ // The seed is hashed by mixStafford13 to produce the initial `x[0]`,
+ // 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 mixStafford13 as the mixer.
+ this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+ RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64),
+ 0,
+ 1,
+ 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));
+ }
+
+ /**
+ * Creates a new instance of {@link L128X1024MixRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L128X1024MixRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L128X1024MixRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L128X1024MixRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L128X1024MixRandom(byte[] seed) {
+ // Convert the seed to 20 long values, of which the last 16 are not all zero.
+ long[] data = RandomSupport.convertSeedBytesToLongs(seed, 20, 16);
+ long ah = data[0], al = data[1], sh = data[2], sl = data[3];
+ // Force a to be odd.
+ this.ah = ah;
+ this.al = al | 1;
+ this.sh = sh;
+ this.sl = sl;
+ this.x = new long[N];
+ for (int j = 0; j < N; j++) {
+ this.x[j] = data[4+j];
+ }
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use the brine for (the low half of) `a`.
+ return new L128X1024MixRandom(source.nextLong(), brine << 1,
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong());
+ }
+
+ @Override
+ public long nextLong() {
+ // First part of xoroshiro1024: fetch array data
+ final int q = p;
+ final long s0 = x[p = (p + 1) & (N - 1)];
+ long s15 = x[q];
+
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = RandomSupport.mixLea64(sh + s0);
+
+ // Update the LCG subgenerator
+ // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic.
+ final long u = ML * sl;
+
+ // Note that Math.multiplyHigh computes the high half of the product of signed values,
+ // but what we need is the high half of the product of unsigned values; for this we use the
+ // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)";
+ // in effect, each operand is added to the result iff the sign bit of the other operand is 1.
+ // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013),
+ // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.)
+ // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become:
+ // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah;
+ // and this entire comment can be deleted.
+ sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah;
+ sl = u + al;
+ if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half.
+
+ // Second part of xoroshiro1024: update array data
+ s15 ^= s0;
+ x[q] = Long.rotateLeft(s0, 25) ^ s15 ^ (s15 << 27);
+ x[p] = Long.rotateLeft(s15, 36);
+
+ return result;
+ }
+
+}
diff --git a/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java b/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java
new file mode 100644
index 000000000000..6dbe8a2b6dfd
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java
@@ -0,0 +1,277 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "splittable" pseudorandom number generator (PRNG) whose period
+ * is roughly 2256. Class {@link L128X128MixRandom} implements
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new split-off {@link L128X128MixRandom}
+ * objects or streams of such objects.
+ *
+ * The {@link L128X128MixRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L128X128MixRandom}
+ * has 256 bits of state plus one 128-bit instance-specific parameter.
+ *
+ * If two instances of {@link L128X128MixRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L128X128MixRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL128X128MixRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L128X128MixRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L128X128MixRandom",
+ group = "LXM",
+ i = 128, j = 1, k = 128,
+ equidistribution = 1
+)
+public final class L128X128MixRandom extends AbstractSplittableWithBrineGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * The split operation uses the current generator to choose four new 64-bit
+ * long values that are then used to initialize the parameter `a` and the
+ * state variables `s`, `x0`, and `x1` for a newly constructed generator.
+ *
+ * With extremely high probability, no two generators so chosen
+ * will have the same `a` parameter, and testing has indicated
+ * that the values generated by two instances of {@link L128X128MixRandom}
+ * will be (approximately) independent if have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate four new 64-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * Low half of multiplier used in the LCG portion of the algorithm;
+ * the overall multiplier is (2**64 + ML).
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL
+ * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493].
+ */
+
+ private static final long ML = 0xd605bbb58c8abbfdL;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd (therefore al must be odd).
+ */
+ private final long ah, al;
+
+ /**
+ * The per-instance state: sh and sl for the LCG; x0 and x1 for the xorshift.
+ * At least one of x0 and x1 must be nonzero.
+ */
+ private long sh, sl, x0, x1;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param ah high half of the additive parameter for the LCG
+ * @param al low half of the additive parameter for the LCG
+ * @param sh high half of the initial state for the LCG
+ * @param sl low half of the initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ */
+ public L128X128MixRandom(long ah, long al, long sh, long sl, long x0, long x1) {
+ // Force a to be odd.
+ this.ah = ah;
+ this.al = al | 1;
+ this.sh = sh;
+ this.sl = sl;
+ this.x0 = x0;
+ this.x1 = x1;
+ // If x0 and x1 are both zero, we must choose nonzero values.
+ if ((x0 | x1) == 0) {
+ long v = sh;
+ // At least one of the two values generated here will be nonzero.
+ this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x1 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64);
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L128X128MixRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L128X128MixRandom} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L128X128MixRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The seed is hashed by mixMurmur64 to produce the `a` parameter.
+ // The seed is hashed by mixStafford13 to produce the initial `x0`,
+ // 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 mixStafford13 as the mixer.
+ this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+ RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64),
+ 0,
+ 1,
+ RandomSupport.mixStafford13(seed),
+ RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L128X128MixRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L128X128MixRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L128X128MixRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L128X128MixRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L128X128MixRandom(byte[] seed) {
+ // Convert the seed to 6 long values, of which the last 2 are not all zero.
+ long[] data = RandomSupport.convertSeedBytesToLongs(seed, 6, 2);
+ long ah = data[0], al = data[1], sh = data[2], sl = data[3], x0 = data[4], x1 = data[5];
+ // Force a to be odd.
+ this.ah = ah;
+ this.al = al | 1;
+ this.sh = sh;
+ this.sl = sl;
+ this.x0 = x0;
+ this.x1 = x1;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use the brine for (the low half of) `a`.
+ return new L128X128MixRandom(source.nextLong(), brine << 1,
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong());
+ }
+
+ @Override
+ public long nextLong() {
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = RandomSupport.mixLea64(sh + x0);
+
+ // Update the LCG subgenerator
+ // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic.
+ final long u = ML * sl;
+ // Note that Math.multiplyHigh computes the high half of the product of signed values,
+ // but what we need is the high half of the product of unsigned values; for this we use the
+ // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)";
+ // in effect, each operand is added to the result iff the sign bit of the other operand is 1.
+ // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013),
+ // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.)
+ // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become:
+ // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah;
+ // and this entire comment can be deleted.
+ sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah;
+ sl = u + al;
+ if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half.
+
+ long q0 = x0, q1 = x1;
+ // Update the Xorshift subgenerator
+ { // xoroshiro128v1_0
+ q1 ^= q0;
+ q0 = Long.rotateLeft(q0, 24);
+ q0 = q0 ^ q1 ^ (q1 << 16);
+ q1 = Long.rotateLeft(q1, 37);
+ }
+ x0 = q0; x1 = q1;
+
+ return result;
+ }
+
+}
diff --git a/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java b/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java
new file mode 100644
index 000000000000..1500771351ef
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java
@@ -0,0 +1,301 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "splittable" pseudorandom number generator (PRNG) whose period
+ * is roughly 2384. Class {@link L128X256MixRandom} implements
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new split-off {@link L128X256MixRandom}
+ * objects or streams of such objects.
+ *
+ * The {@link L128X256MixRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L128X256MixRandom}
+ * has 384 bits of state plus one 128-bit instance-specific parameter.
+ *
+ * If two instances of {@link L128X256MixRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L128X256MixRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL128X256MixRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L128X256MixRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L128X256MixRandom",
+ group = "LXM",
+ i = 256, j = 1, k = 128,
+ equidistribution = 1
+)
+public final class L128X256MixRandom extends AbstractSplittableWithBrineGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * The 128-bit parameter `a` is represented as two long fields `ah` and `al`.
+ * The 128-bit state variable `s` is represented as two long fields `sh` and `sl`.
+ *
+ * The split operation uses the current generator to choose eight
+ * new 64-bit long values that are then used to initialize the
+ * parameters `ah` and `al` and the state variables `sh`, `sl`,
+ * `x0`, `x1`, `x2`, and `x3` for a newly constructed generator.
+ *
+ * With extremely high probability, no two generators so chosen
+ * will have the same `a` parameter, and testing has indicated
+ * that the values generated by two instances of {@link L128X256MixRandom}
+ * will be (approximately) independent if have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate eight new 64-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * The equidistribution of the algorithm.
+ */
+ private static final int EQUIDISTRIBUTION = 1;
+
+ /*
+ * Low half of multiplier used in the LCG portion of the algorithm;
+ * the overall multiplier is (2**64 + ML).
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0x1d605bbb58c8abbfdLL
+ * are [0.991889, 0.907938, 0.830964, 0.837980, 0.780378, 0.797464, 0.761493].
+ */
+
+ private static final long ML = 0xd605bbb58c8abbfdL;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd (therefore al must be odd).
+ */
+ private final long ah, al;
+
+ /**
+ * The per-instance state: sh and sl for the LCG; x0, x1, x2, and x3 for the xorshift.
+ * At least one of the four fields x0, x1, x2, and x3 must be nonzero.
+ */
+ private long sh, sl, x0, x1, x2, x3;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param ah high half of the additive parameter for the LCG
+ * @param al low half of the additive parameter for the LCG
+ * @param sh high half of the initial state for the LCG
+ * @param sl low half of the initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ * @param x2 third word of the initial state for the xorshift generator
+ * @param x3 fourth word of the initial state for the xorshift generator
+ */
+ public L128X256MixRandom(long ah, long al, long sh, long sl, long x0, long x1, long x2, long x3) {
+ // Force a to be odd.
+ this.ah = ah;
+ this.al = al | 1;
+ this.sh = sh;
+ this.sl = sl;
+ this.x0 = x0;
+ this.x1 = x1;
+ this.x2 = x2;
+ this.x3 = x3;
+ // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
+ if ((x0 | x1 | x2 | x3) == 0) {
+ long v = sh;
+ // At least three of the four values generated here will be nonzero.
+ this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x1 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x2 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x3 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64);
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L128X256MixRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L128X256MixRandom} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L128X256MixRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The seed is hashed by mixMurmur64 to produce the `a` parameter.
+ // The seed is hashed by mixStafford13 to produce the initial `x0`,
+ // 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 mixStafford13 as the mixer.
+ this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+ RandomSupport.mixMurmur64(seed += RandomSupport.GOLDEN_RATIO_64),
+ 0,
+ 1,
+ RandomSupport.mixStafford13(seed),
+ RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+ RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+ RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L128X256MixRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L128X256MixRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L128X256MixRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L128X256MixRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L128X256MixRandom(byte[] seed) {
+ // Convert the seed to 6 long values, of which the last 4 are not all zero.
+ 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;
+ this.al = al | 1;
+ this.sh = sh;
+ this.sl = sl;
+ this.x0 = x0;
+ this.x1 = x1;
+ this.x2 = x2;
+ this.x3 = x3;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use the brine for (the low half of) `a`.
+ return new L128X256MixRandom(source.nextLong(), brine << 1,
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong());
+ }
+
+ @Override
+ public long nextLong() {
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = RandomSupport.mixLea64(sh + x0);
+
+ // Update the LCG subgenerator
+ // The LCG is, in effect, s = ((1LL << 64) + ML) * s + a, if only we had 128-bit arithmetic.
+ final long u = ML * sl;
+ // Note that Math.multiplyHigh computes the high half of the product of signed values,
+ // but what we need is the high half of the product of unsigned values; for this we use the
+ // formula "unsignedMultiplyHigh(a, b) = multiplyHigh(a, b) + ((a >> 63) & b) + ((b >> 63) & a)";
+ // in effect, each operand is added to the result iff the sign bit of the other operand is 1.
+ // (See Henry S. Warren, Jr., _Hacker's Delight_ (Second Edition), Addison-Wesley (2013),
+ // Section 8-3, p. 175; or see the First Edition, Addison-Wesley (2003), Section 8-3, p. 133.)
+ // If Math.unsignedMultiplyHigh(long, long) is ever implemented, the following line can become:
+ // sh = (ML * sh) + Math.unsignedMultiplyHigh(ML, sl) + sl + ah;
+ // and this entire comment can be deleted.
+ sh = (ML * sh) + (Math.multiplyHigh(ML, sl) + ((ML >> 63) & sl) + ((sl >> 63) & ML)) + sl + ah;
+ sl = u + al;
+ if (Long.compareUnsigned(sl, u) < 0) ++sh; // Handle the carry propagation from low half to high half.
+
+ // Update the Xorshift subgenerator
+ long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
+ { // xoshiro256 1.0
+ long t = q1 << 17;
+ q2 ^= q0;
+ q3 ^= q1;
+ q1 ^= q2;
+ q0 ^= q3;
+ q2 ^= t;
+ q3 = Long.rotateLeft(q3, 45);
+ }
+ x0 = q0; x1 = q1; x2 = q2; x3 = q3;
+
+ return result;
+ }
+
+}
diff --git a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java b/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java
new file mode 100644
index 000000000000..7d5aae94a1c8
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java
@@ -0,0 +1,256 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "splittable" pseudorandom number generator (PRNG) whose period
+ * is roughly 296. Class {@link L32X64MixRandom} implements
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new split-off {@link L32X64MixRandom}
+ * objects or streams of such objects.
+ *
+ * The {@link L32X64MixRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L32X64MixRandom}
+ * has 96 bits of state plus one 32-bit instance-specific parameter.
+ *
+ * If two instances of {@link L32X64MixRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L32X64MixRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL32X64MixRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L32X64MixRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L32X64MixRandom",
+ group = "LXM",
+ i = 64, j = 1, k = 32,
+ equidistribution = 1
+)
+public final class L32X64MixRandom extends AbstractSplittableWithBrineGenerator {
+ /*
+ * Implementation Overview.
+ *
+ * The split operation uses the current generator to choose four new 32-bit
+ * int values that are then used to initialize the parameter `a` and the
+ * state variables `s`, `x0`, and `x1` for a newly constructed generator.
+ *
+ * With high probability, no two generators so chosen will have the same
+ * `a` parameter, and testing has indicated that the values generated by
+ * two instances of {@link L32X64MixRandom} will be (approximately)
+ * independent if the two instances have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate four new 32-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * Multiplier used in the LCG portion of the algorithm.
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0xadb4a92d
+ * are [0.975884, 0.936244, 0.755793, 0.877642, 0.751300, 0.789333, 0.728869].
+ */
+
+ private static final int M = 0xadb4a92d;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd.
+ */
+ private final int a;
+
+ /**
+ * The per-instance state: s for the LCG; x0 and x1 for the xorshift.
+ * At least one of x0 and x1 must be nonzero.
+ */
+ private int s, x0, x1;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param a additive parameter for the LCG
+ * @param s initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ */
+ public L32X64MixRandom(int a, int s, int x0, int x1) {
+ // Force a to be odd.
+ this.a = a | 1;
+ this.s = s;
+ // If x0 and x1 are both zero, we must choose nonzero values.
+ if ((x0 | x1) == 0) {
+ int v = s;
+ // At least one of the two values generated here will be nonzero.
+ this.x0 = RandomSupport.mixMurmur32(v += RandomSupport.GOLDEN_RATIO_32);
+ this.x1 = RandomSupport.mixMurmur32(v + RandomSupport.GOLDEN_RATIO_32);
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L32X64MixRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L32X64MixRandom} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L32X64MixRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The high half of the seed is hashed by mixMurmur32 to produce the `a` parameter.
+ // The low half of the seed is hashed by mixLea32 to produce the initial `x0`,
+ // 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 mixLea32 as the mixer.
+ this(RandomSupport.mixMurmur32((int)((seed ^= RandomSupport.SILVER_RATIO_64) >>> 32)),
+ 1,
+ RandomSupport.mixLea32((int)(seed)),
+ RandomSupport.mixLea32((int)(seed) + RandomSupport.GOLDEN_RATIO_32));
+ }
+
+ /**
+ * Creates a new instance of {@link L32X64MixRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L32X64MixRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L32X64MixRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L32X64MixRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L32X64MixRandom(byte[] seed) {
+ // Convert the seed to 4 int values, of which the last 2 are not all zero.
+ 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;
+ this.s = s;
+ this.x0 = x0;
+ this.x1 = x1;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use (the low 31 bits of) the brine for `a`.
+ return new L32X64MixRandom((int)brine << 1, source.nextInt(),
+ source.nextInt(), source.nextInt());
+ }
+
+ @Override
+ public int nextInt() {
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final int result = RandomSupport.mixLea32(s + x0);
+
+ // Update the LCG subgenerator
+ s = M * s + a;
+
+ // Update the Xorshift subgenerator
+ int q0 = x0, q1 = x1;
+ { // xoroshiro64
+ q1 ^= q0;
+ q0 = Integer.rotateLeft(q0, 26);
+ q0 = q0 ^ q1 ^ (q1 << 9);
+ q1 = Integer.rotateLeft(q1, 13);
+ }
+ x0 = q0; x1 = q1;
+
+ return result;
+ }
+
+ @Override
+ public long nextLong() {
+ return ((long)nextInt() << 32) ^ (long)nextInt();
+ }
+
+}
diff --git a/src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java b/src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java
new file mode 100644
index 000000000000..1dbe762e0300
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java
@@ -0,0 +1,321 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "splittable" pseudorandom number generator (PRNG) whose period
+ * is roughly 21088. Class {@link L64X1024MixRandom} implements
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new split-off {@link L64X1024MixRandom}
+ * objects or streams of such objects.
+ *
+ * The {@link L64X1024MixRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L64X1024MixRandom}
+ * has 1088 bits of state plus one 64-bit instance-specific parameter.
+ *
+ * If two instances of {@link L64X1024MixRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L64X1024MixRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL64X1024MixRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L64X1024MixRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L64X1024MixRandom",
+ group = "LXM",
+ i = 1024, j = 1, k = 64,
+ equidistribution = 16
+)
+public final class L64X1024MixRandom extends AbstractSplittableWithBrineGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * The split() operation uses the current generator to choose 18 new 64-bit
+ * long values that are then used to initialize the parameter `a`, the
+ * state variable `s`, and the array `x` for a newly constructed generator.
+ *
+ * With extremely high probability, no two generators so chosen
+ * will have the same `a` parameter, and testing has indicated
+ * that the values generated by two instances of {@link L64X1024MixRandom}
+ * will be (approximately) independent if have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate 18 new 64-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /*
+ * The length of the array x.
+ */
+
+ private static final int N = 16;
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * Multiplier used in the LCG portion of the algorithm.
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95
+ * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215].
+ */
+
+ private static final long M = 0xd1342543de82ef95L;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd.
+ */
+ private final long a;
+
+ /**
+ * The per-instance state: s for the LCG; the array x for the xorshift;
+ * p is the rotating pointer into the array x.
+ * At least one of the 16 elements of the array x must be nonzero.
+ */
+ private long s;
+ private final long[] x;
+ private int p = N - 1;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param a additive parameter for the LCG
+ * @param s initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ * @param x2 third word of the initial state for the xorshift generator
+ * @param x3 fourth word of the initial state for the xorshift generator
+ * @param x4 fifth word of the initial state for the xorshift generator
+ * @param x5 sixth word of the initial state for the xorshift generator
+ * @param x6 seventh word of the initial state for the xorshift generator
+ * @param x7 eight word of the initial state for the xorshift generator
+ * @param x8 ninth word of the initial state for the xorshift generator
+ * @param x9 tenth word of the initial state for the xorshift generator
+ * @param x10 eleventh word of the initial state for the xorshift generator
+ * @param x11 twelfth word of the initial state for the xorshift generator
+ * @param x12 thirteenth word of the initial state for the xorshift generator
+ * @param x13 fourteenth word of the initial state for the xorshift generator
+ * @param x14 fifteenth word of the initial state for the xorshift generator
+ * @param x15 sixteenth word of the initial state for the xorshift generator
+ */
+ public L64X1024MixRandom(long a, long s,
+ long x0, long x1, long x2, long x3,
+ long x4, long x5, long x6, long x7,
+ long x8, long x9, long x10, long x11,
+ long x12, long x13, long x14, long x15) {
+ // Force a to be odd.
+ this.a = a | 1;
+ this.s = s;
+ this.x = new long[N];
+ this.x[0] = x0;
+ this.x[1] = x1;
+ this.x[2] = x2;
+ this.x[3] = x3;
+ this.x[4] = x4;
+ this.x[5] = x5;
+ this.x[6] = x6;
+ this.x[7] = x7;
+ this.x[8] = x8;
+ this.x[9] = x9;
+ this.x[10] = x10;
+ this.x[11] = x11;
+ this.x[12] = x12;
+ this.x[13] = x13;
+ this.x[14] = x14;
+ this.x[15] = x15;
+ // 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) {
+ long v = s;
+ // At least fifteen of the sixteen values generated here will be nonzero.
+ for (int j = 0; j < N; j++) {
+ this.x[j] = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ }
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L64X1024MixRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L64X1024MixRandom} created with the same seed in the same
+ * program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X1024MixRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The seed is hashed by mixMurmur64 to produce the `a` parameter.
+ // The seed is hashed by mixStafford13 to produce the initial `x[0]`,
+ // 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 mixStafford13 as the mixer.
+ this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+ 1,
+ 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));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X1024MixRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L64X1024MixRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X1024MixRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L64X1024MixRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X1024MixRandom(byte[] seed) {
+ // Convert the seed to 18 long values, of which the last 16 are not all zero.
+ long[] data = RandomSupport.convertSeedBytesToLongs(seed, 18, 16);
+ long a = data[0], s = data[1];
+ // Force a to be odd.
+ this.a = a | 1;
+ this.s = s;
+ this.x = new long[N];
+ for (int j = 0; j < N; j++) {
+ this.x[j] = data[2+j];
+ }
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use the brine for `a`.
+ return new L64X1024MixRandom(brine << 1, source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong());
+ }
+
+ @Override
+ public long nextLong() {
+ // First part of xoroshiro1024: fetch array data
+ final int q = p;
+ final long s0 = x[p = (p + 1) & (N - 1)];
+ long s15 = x[q];
+
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+
+ final long result = RandomSupport.mixLea64(s + s0);
+
+ // Update the LCG subgenerator
+ s = M * s + a; // LCG
+
+ // Second part of xoroshiro1024: update array data
+ s15 ^= s0;
+ x[q] = Long.rotateLeft(s0, 25) ^ s15 ^ (s15 << 27);
+ x[p] = Long.rotateLeft(s15, 36);
+
+ return result;
+ }
+
+}
diff --git a/src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java b/src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java
new file mode 100644
index 000000000000..35f3322e59cb
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java
@@ -0,0 +1,254 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "splittable" pseudorandom number generator (PRNG) whose period
+ * is roughly 2192. Class {@link L64X128MixRandom} implements
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new split-off {@link L64X128MixRandom}
+ * objects or streams of such objects.
+ *
+ * The {@link L64X128MixRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L64X128MixRandom}
+ * has 192 bits of state plus one 64-bit instance-specific parameter.
+ *
+ * If two instances of {@link L64X128MixRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L64X128MixRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL64X128MixRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L64X128MixRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L64X128MixRandom",
+ group = "LXM",
+ i = 128, j = 1, k = 64,
+ equidistribution = 1
+)
+public final class L64X128MixRandom extends AbstractSplittableWithBrineGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * The split operation uses the current generator to choose four new 64-bit
+ * long values that are then used to initialize the parameter `a` and the
+ * state variables `s`, `x0`, and `x1` for a newly constructed generator.
+ *
+ * With extremely high probability, no two generators so chosen
+ * will have the same `a` parameter, and testing has indicated
+ * that the values generated by two instances of {@link L64X128MixRandom}
+ * will be (approximately) independent if have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate four new 64-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * Multiplier used in the LCG portion of the algorithm.
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95L
+ * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215].
+ */
+
+ private static final long M = 0xd1342543de82ef95L;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd.
+ */
+ private final long a;
+
+ /**
+ * The per-instance state: s for the LCG; x0 and x1 for the xorshift.
+ * At least one of x0 and x1 must be nonzero.
+ */
+ private long s, x0, x1;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param a additive parameter for the LCG
+ * @param s initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ */
+ public L64X128MixRandom(long a, long s, long x0, long x1) {
+ // Force a to be odd.
+ this.a = a | 1;
+ this.s = s;
+ this.x0 = x0;
+ this.x1 = x1;
+ // If x0 and x1 are both zero, we must choose nonzero values.
+ if ((x0 | x1) == 0) {
+ long v = s;
+ // At least one of the two values generated here will be nonzero.
+ this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x1 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64);
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L64X128MixRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L64X128MixRandom} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X128MixRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The seed is hashed by mixMurmur64 to produce the `a` parameter.
+ // The seed is hashed by mixStafford13 to produce the initial `x0`,
+ // 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 mixStafford13 as the mixer.
+ this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+ 1,
+ RandomSupport.mixStafford13(seed),
+ RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X128MixRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L64X128MixRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X128MixRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L64X128MixRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X128MixRandom(byte[] seed) {
+ // Convert the seed to 4 long values, of which the last 2 are not all zero.
+ 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;
+ this.s = s;
+ this.x0 = x0;
+ this.x1 = x1;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use the brine for `a`.
+ return new L64X128MixRandom(brine << 1, source.nextLong(),
+ source.nextLong(), source.nextLong());
+ }
+
+ @Override
+ public long nextLong() {
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = RandomSupport.mixLea64(s + x0);
+
+ // Update the LCG subgenerator
+ s = M * s + a;
+
+ // Update the Xorshift subgenerator
+ long q0 = x0, q1 = x1;
+ { // xoroshiro128v1_0
+ q1 ^= q0;
+ q0 = Long.rotateLeft(q0, 24);
+ q0 = q0 ^ q1 ^ (q1 << 16);
+ q1 = Long.rotateLeft(q1, 37);
+ }
+ x0 = q0; x1 = q1;
+
+ return result;
+ }
+
+}
diff --git a/src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java b/src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java
new file mode 100644
index 000000000000..d0eb4daa4f16
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java
@@ -0,0 +1,254 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "splittable" pseudorandom number generator (PRNG) whose period
+ * is roughly 2192. Class {@link L64X128StarStarRandom} implements
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new split-off {@link L64X128StarStarRandom}
+ * objects or streams of such objects.
+ *
+ * The {@link L64X128StarStarRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L64X128StarStarRandom}
+ * has 192 bits of state plus one 64-bit instance-specific parameter.
+ *
+ * If two instances of {@link L64X128StarStarRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L64X128StarStarRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL64X128StarStarRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L64X128StarStarRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L64X128StarStarRandom",
+ group = "LXM",
+ i = 128, j = 1, k = 64,
+ equidistribution = 1
+)
+public final class L64X128StarStarRandom extends AbstractSplittableWithBrineGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * The split operation uses the current generator to choose four new 64-bit
+ * long values that are then used to initialize the parameter `a` and the
+ * state variables `s`, `x0`, and `x1` for a newly constructed generator.
+ *
+ * With extremely high probability, no two generators so chosen
+ * will have the same `a` parameter, and testing has indicated
+ * that the values generated by two instances of {@link L64X128StarStarRandom}
+ * will be (approximately) independent if have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate four new 64-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * Multiplier used in the LCG portion of the algorithm.
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95
+ * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215].
+ */
+
+ private static final long M = 0xd1342543de82ef95L;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd.
+ */
+ private final long a;
+
+ /**
+ * The per-instance state: s for the LCG; x0 and x1 for the xorshift.
+ * At least one of x0 and x1 must be nonzero.
+ */
+ private long s, x0, x1;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param a additive parameter for the LCG
+ * @param s initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ */
+ public L64X128StarStarRandom(long a, long s, long x0, long x1) {
+ // Force a to be odd.
+ this.a = a | 1;
+ this.s = s;
+ this.x0 = x0;
+ this.x1 = x1;
+ // If x0 and x1 are both zero, we must choose nonzero values.
+ if ((x0 | x1) == 0) {
+ long v = s;
+ // At least one of the two values generated here will be nonzero.
+ this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x1 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64);
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L64X128StarStarRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L64X128StarStarRandom} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X128StarStarRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The seed is hashed by mixMurmur64 to produce the `a` parameter.
+ // The seed is hashed by mixStafford13 to produce the initial `x0`,
+ // 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 mixStafford13 as the mixer.
+ this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+ 1,
+ RandomSupport.mixStafford13(seed),
+ RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X128StarStarRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L64X128StarStarRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X128StarStarRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L64X128StarStarRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X128StarStarRandom(byte[] seed) {
+ // Convert the seed to 4 long values, of which the last 2 are not all zero.
+ 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;
+ this.s = s;
+ this.x0 = x0;
+ this.x1 = x1;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use the brine for `a`.
+ return new L64X128StarStarRandom(brine << 1, source.nextLong(),
+ source.nextLong(), source.nextLong());
+ }
+
+ @Override
+ public long nextLong() {
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = Long.rotateLeft((s + x0) * 5, 7) * 9; // "starstar" scrambler
+
+ // Update the LCG subgenerator
+ s = M * s + a;
+
+ // Update the Xorshift subgenerator
+ long q0 = x0, q1 = x1;
+ { // xoroshiro128v1_0
+ q1 ^= q0;
+ q0 = Long.rotateLeft(q0, 24);
+ q0 = q0 ^ q1 ^ (q1 << 16);
+ q1 = Long.rotateLeft(q1, 37);
+ }
+ x0 = q0; x1 = q1;
+
+ return result;
+ }
+
+}
diff --git a/src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java b/src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java
new file mode 100644
index 000000000000..4e40a0b93814
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java
@@ -0,0 +1,269 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.AbstractSplittableWithBrineGenerator;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "splittable" pseudorandom number generator (PRNG) whose period
+ * is roughly 2320. Class {@link L64X256MixRandom} implements
+ * interfaces {@link RandomGenerator} and {@link SplittableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new split-off {@link L64X256MixRandom}
+ * objects or streams of such objects.
+ *
+ * The {@link L64X256MixRandom} algorithm is a specific member of
+ * the LXM family of algorithms for pseudorandom number generators;
+ * for more information, see the documentation for package
+ * {@link jdk.random}. Each instance of {@link L64X256MixRandom}
+ * has 320 bits of state plus one 64-bit instance-specific parameter.
+ *
+ * If two instances of {@link L64X256MixRandom} are created with
+ * the same seed within the same program execution, and the same
+ * sequence of method calls is made for each, they will generate and
+ * return identical sequences of values.
+ *
+ * As with {@link java.util.SplittableRandom}, instances of
+ * {@link L64X256MixRandom} are not thread-safe. They are
+ * designed to be split, not shared, across threads (see the {@link #split}
+ * method). For example, a {@link java.util.concurrent.ForkJoinTask}
+ * fork/join-style computation using random numbers might include a
+ * construction of the form
+ * {@code new Subtask(someL64X256MixRandom.split()).fork()}.
+ *
+ * This class provides additional methods for generating random
+ * streams, that employ the above techniques when used in
+ * {@code stream.parallel()} mode.
+ *
+ * Instances of {@link L64X256MixRandom} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "L64X256MixRandom",
+ group = "LXM",
+ i = 256, j = 1, k = 64,
+ equidistribution = 4
+)
+public final class L64X256MixRandom extends AbstractSplittableWithBrineGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * The split operation uses the current generator to choose six new 64-bit
+ * long values that are then used to initialize the parameter `a` and the
+ * state variables `s`, `x0`, `x1`, `x2`, and `x3` for a newly constructed
+ * generator.
+ *
+ * With extremely high probability, no two generators so chosen
+ * will have the same `a` parameter, and testing has indicated
+ * that the values generated by two instances of {@link L64X256MixRandom}
+ * will be (approximately) independent if have different values for `a`.
+ *
+ * The default (no-argument) constructor, in essence, uses
+ * "defaultGen" to generate six new 64-bit values for the same
+ * purpose. Multiple generators created in this way will certainly
+ * differ in their `a` parameters. The defaultGen state must be accessed
+ * in a thread-safe manner, so we use an AtomicLong to represent
+ * this state. To bootstrap the defaultGen, we start off using a
+ * seed based on current time unless the
+ * java.util.secureRandomSeed property is set. This serves as a
+ * slimmed-down (and insecure) variant of SecureRandom that also
+ * avoids stalls that may occur when using /dev/random.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /*
+ * Multiplier used in the LCG portion of the algorithm.
+ * Chosen based on research by Sebastiano Vigna and Guy Steele (2019).
+ * The spectral scores for dimensions 2 through 8 for the multiplier 0xd1342543de82ef95
+ * are [0.958602, 0.937479, 0.870757, 0.822326, 0.820405, 0.813065, 0.760215].
+ */
+
+ private static final long M = 0xd1342543de82ef95L;
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The parameter that is used as an additive constant for the LCG.
+ * Must be odd.
+ */
+ private final long a;
+
+ /**
+ * The per-instance state: s for the LCG; x0, x1, x2, and x3 for the xorshift.
+ * At least one of the four fields x0, x1, x2, and x3 must be nonzero.
+ */
+ private long s, x0, x1, x2, x3;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param a additive parameter for the LCG
+ * @param s initial state for the LCG
+ * @param x0 first word of the initial state for the xorshift generator
+ * @param x1 second word of the initial state for the xorshift generator
+ * @param x2 third word of the initial state for the xorshift generator
+ * @param x3 fourth word of the initial state for the xorshift generator
+ */
+ public L64X256MixRandom(long a, long s, long x0, long x1, long x2, long x3) {
+ // Force a to be odd.
+ this.a = a | 1;
+ this.s = s;
+ this.x0 = x0;
+ this.x1 = x1;
+ this.x2 = x2;
+ this.x3 = x3;
+ // If x0, x1, x2, and x3 are all zero, we must choose nonzero values.
+ if ((x0 | x1 | x2 | x3) == 0) {
+ long v = s;
+ // At least three of the four values generated here will be nonzero.
+ this.x0 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x1 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x2 = RandomSupport.mixStafford13(v += RandomSupport.GOLDEN_RATIO_64);
+ this.x3 = RandomSupport.mixStafford13(v + RandomSupport.GOLDEN_RATIO_64);
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link L64X256MixRandom} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link L64X256MixRandom} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X256MixRandom(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // The seed is hashed by mixMurmur64 to produce the `a` parameter.
+ // The seed is hashed by mixStafford13 to produce the initial `x0`,
+ // 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 mixStafford13 as the mixer.
+ this(RandomSupport.mixMurmur64(seed ^= RandomSupport.SILVER_RATIO_64),
+ 1,
+ RandomSupport.mixStafford13(seed),
+ RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+ RandomSupport.mixStafford13(seed += RandomSupport.GOLDEN_RATIO_64),
+ RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X256MixRandom} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public L64X256MixRandom() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link L64X256MixRandom} using the specified array of
+ * initial seed bytes. Instances of {@link L64X256MixRandom} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public L64X256MixRandom(byte[] seed) {
+ // Convert the seed to 6 long values, of which the last 4 are not all zero.
+ 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;
+ this.s = s;
+ this.x0 = x0;
+ this.x1 = x1;
+ this.x2 = x2;
+ this.x3 = x3;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ @Override
+ public SplittableGenerator split(SplittableGenerator source, long brine) {
+ // Pick a new instance "at random", but use the brine for `a`.
+ return new L64X256MixRandom(brine << 1, source.nextLong(),
+ source.nextLong(), source.nextLong(),
+ source.nextLong(), source.nextLong());
+ }
+
+ @Override
+ public long nextLong() {
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = RandomSupport.mixLea64(s + x0);
+
+ // Update the LCG subgenerator
+ s = M * s + a;
+
+ // Update the Xorshift subgenerator
+ long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
+ { // xoshiro256 1.0
+ long t = q1 << 17;
+ q2 ^= q0;
+ q3 ^= q1;
+ q1 ^= q2;
+ q0 ^= q3;
+ q2 ^= t;
+ q3 = Long.rotateLeft(q3, 45);
+ }
+ x0 = q0; x1 = q1; x2 = q2; x3 = q3;
+
+ return result;
+ }
+
+ }
diff --git a/src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java b/src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java
new file mode 100644
index 000000000000..cc9ea8014532
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java
@@ -0,0 +1,284 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGenerator.LeapableGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "jumpable and leapable" pseudorandom number generator (PRNG) whose period
+ * is roughly 2128. Class {@link Xoroshiro128PlusPlus} implements
+ * 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 Xoroshiro128PlusPlus} objects
+ * by "jumping" or "leaping".
+ *
+ * The class {@link Xoroshiro128PlusPlus} uses the {@code xoroshiro128} algorithm
+ * (parameters 49, 21, 28) with the "++" scrambler that computes
+ * {@code Long.rotateLeft(s0 + s1, 17) + s0}.
+ * Its state consists of two {@code long} fields {@code x0} and {@code x1},
+ * which can take on any values provided that they are not both zero.
+ * The period of this generator is 2128-1.
+ *
+ * The 64-bit values produced by the {@code nextLong()} method are equidistributed.
+ * To be precise, over the course of the cycle of length 2128-1,
+ * each nonzero {@code long} value is generated 264 times,
+ * but the value 0 is generated only 264-1 times.
+ * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()}
+ * methods are likewise equidistributed.
+ *
+ * Instances {@link Xoroshiro128PlusPlus} are not thread-safe.
+ * They are designed to be used so that each thread as its own instance.
+ * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps}
+ * can be used to construct new instances of {@link Xoroshiro128PlusPlus} that traverse
+ * other parts of the state cycle.
+ *
+ * Instances of {@link Xoroshiro128PlusPlus} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "Xoroshiro128PlusPlus",
+ group = "Xoroshiro",
+ i = 128, j = 1, k = 0,
+ equidistribution = 2
+)
+public final class Xoroshiro128PlusPlus implements LeapableGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * This is an implementation of the xoroshiro128++ algorithm version 1.0,
+ * written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org).
+ * See http://xoshiro.di.unimi.it and these two papers:
+ *
+ * Sebastiano Vigna. 2016. An Experimental Exploration of Marsaglia's
+ * xorshift Generators, Scrambled. ACM Transactions on Mathematical
+ * Software 42, 4, Article 30 (June 2016), 23 pages.
+ * https://doi.org/10.1145/2845077
+ *
+ * David Blackman and Sebastiano Vigna. 2018. Scrambled Linear
+ * Pseudorandom Number Generators. Computing Research Repository (CoRR).
+ * http://arxiv.org/abs/1805.01407
+ *
+ * The jump operation moves the current generator forward by 2*64
+ * steps; this has the same effect as calling nextLong() 2**64
+ * times, but is much faster. Similarly, the leap operation moves
+ * the current generator forward by 2*96 steps; this has the same
+ * effect as calling nextLong() 2**96 times, but is much faster.
+ * The copy method may be used to make a copy of the current
+ * generator. Thus one may repeatedly and cumulatively copy and
+ * jump to produce a sequence of generators whose states are well
+ * spaced apart along the overall state cycle (indeed, the jumps()
+ * and leaps() methods each produce a stream of such generators).
+ * The generators can then be parceled out to other threads.
+ *
+ * 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 AbstractJumpableGenerator} and {@link AbstractGenerator}.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * Group name.
+ */
+ private static final String GROUP = "Xoroshiro";
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong defaultGen = new AtomicLong(RandomSupport.initialSeed());
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The per-instance state.
+ * At least one of the two fields x0 and x1 must be nonzero.
+ */
+ private long x0, x1;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param x0 first word of the initial state
+ * @param x1 second word of the initial state
+ */
+ public Xoroshiro128PlusPlus(long x0, long x1) {
+ this.x0 = x0;
+ this.x1 = x1;
+ // If x0 and x1 are both zero, we must choose nonzero values.
+ if ((x0 | x1) == 0) {
+ this.x0 = RandomSupport.GOLDEN_RATIO_64;
+ this.x1 = RandomSupport.SILVER_RATIO_64;
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link Xoroshiro128PlusPlus} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link Xoroshiro128PlusPlus} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public Xoroshiro128PlusPlus(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // 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(RandomSupport.mixStafford13(seed ^= RandomSupport.SILVER_RATIO_64),
+ RandomSupport.mixStafford13(seed + RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link Xoroshiro128PlusPlus} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public Xoroshiro128PlusPlus() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(defaultGen.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link Xoroshiro128PlusPlus} using the specified array of
+ * initial seed bytes. Instances of {@link Xoroshiro128PlusPlus} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public Xoroshiro128PlusPlus(byte[] seed) {
+ // Convert the seed to 2 long values, which are not both zero.
+ long[] data = RandomSupport.convertSeedBytesToLongs(seed, 2, 2);
+ long x0 = data[0], x1 = data[1];
+ this.x0 = x0;
+ this.x1 = x1;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ public Xoroshiro128PlusPlus copy() {
+ return new Xoroshiro128PlusPlus(x0, x1);
+ }
+
+ /*
+ * The following two comments are quoted from http://prng.di.unimi.it/xoroshiro128plusplus.c
+ */
+
+ /*
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty.
+ *
+ * See http://creativecommons.org/publicdomain/zero/1.0/.
+ */
+
+ /*
+ * This is xoroshiro128++ 1.0, one of our all-purpose, rock-solid,
+ * small-state generators. It is extremely (sub-ns) fast and it passes all
+ * tests we are aware of, but its state space is large enough only for
+ * mild parallelism.
+ *
+ * For generating just floating-point numbers, xoroshiro128+ is even
+ * faster (but it has a very mild bias, see notes in the comments).
+ *
+ * The state must be seeded so that it is not everywhere zero. If you have
+ * a 64-bit seed, we suggest to seed a splitmix64 generator and use its
+ * output to fill s.
+ */
+
+ @Override
+ public long nextLong() {
+ final long s0 = x0;
+ long s1 = x1;
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = Long.rotateLeft(s0 + s1, 17) + s0; // "plusplus" scrambler
+
+ s1 ^= s0;
+ x0 = Long.rotateLeft(s0, 49) ^ s1 ^ (s1 << 21); // a, b
+ x1 = Long.rotateLeft(s1, 28); // c
+
+ return result;
+ }
+
+ @Override
+ public double jumpDistance() {
+ return 0x1.0p64;
+ }
+
+ @Override
+ public double leapDistance() {
+ return 0x1.0p96;
+ }
+
+ private static final long[] JUMP_TABLE = { 0x2bd7a6a6e99c2ddcL, 0x0992ccaf6a6fca05L };
+
+ private static final long[] LEAP_TABLE = { 0x360fd5f2cf8d5d99L, 0x9c6e6877736c46e3L };
+
+ @Override
+ public void jump() {
+ jumpAlgorithm(JUMP_TABLE);
+ }
+
+ @Override
+ public void leap() {
+ jumpAlgorithm(LEAP_TABLE);
+ }
+
+ private void jumpAlgorithm(long[] table) {
+ long s0 = 0, s1 = 0;
+ for (int i = 0; i < table.length; i++) {
+ for (int b = 0; b < 64; b++) {
+ if ((table[i] & (1L << b)) != 0) {
+ s0 ^= x0;
+ s1 ^= x1;
+ }
+ nextLong();
+ }
+ }
+ x0 = s0;
+ x1 = s1;
+ }
+}
diff --git a/src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java b/src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java
new file mode 100644
index 000000000000..8f5bc540d2aa
--- /dev/null
+++ b/src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java
@@ -0,0 +1,315 @@
+/*
+ * 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 jdk.random;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGenerator.LeapableGenerator;
+import jdk.internal.util.random.RandomSupport;
+import jdk.internal.util.random.RandomSupport.RandomGeneratorProperties;
+
+/**
+ * A "jumpable and leapable" pseudorandom number generator (PRNG) whose period
+ * is roughly 2256. Class {@link Xoshiro256PlusPlus} implements
+ * interfaces {@link RandomGenerator} and {@link LeapableGenerator},
+ * and therefore supports methods for producing pseudorandomly chosen
+ * values of type {@code int}, {@code long}, {@code float}, {@code double},
+ * and {@code boolean} (and for producing streams of pseudorandomly chosen
+ * numbers of type {@code int}, {@code long}, and {@code double}),
+ * as well as methods for creating new {@link Xoshiro256PlusPlus} objects
+ * by moving forward either a large distance (2128) or a very large
+ * distance (2192) around the state cycle.
+ *
+ * Series of generated values pass the TestU01 BigCrush and PractRand test suites
+ * that measure independence and uniformity properties of random number generators.
+ * (Most recently validated with
+ * version 1.2.3 of TestU01
+ * and version 0.90 of PractRand.
+ * Note that TestU01 BigCrush was used to test not only values produced by the {@code nextLong()}
+ * method but also the result of bit-reversing each value produced by {@code nextLong()}.)
+ * These tests validate only the methods for certain
+ * types and ranges, but similar properties are expected to hold, at
+ * least approximately, for others as well.
+ *
+ * The class {@link Xoshiro256PlusPlus} uses the {@code xoshiro256} algorithm,
+ * version 1.0 (parameters 17, 45), with the "++" scrambler that computes
+ * {@code Long.rotateLeft(s0 + s3, 23) + s0}.
+ * Its state consists of four {@code long} fields {@code x0}, {@code x1}, {@code x2},
+ * and {@code x3}, which can take on any values provided that they are not all zero.
+ * The period of this generator is 2256-1.
+ *
+ * The 64-bit values produced by the {@code nextLong()} method are equidistributed.
+ * To be precise, over the course of the cycle of length 2256-1,
+ * each nonzero {@code long} value is generated 2192 times,
+ * but the value 0 is generated only 2192-1 times.
+ * The values produced by the {@code nextInt()}, {@code nextFloat()}, and {@code nextDouble()}
+ * methods are likewise equidistributed.
+ * Moreover, the 64-bit values produced by the {@code nextLong()} method are 3-equidistributed.
+ *
+ * Instances {@link Xoshiro256PlusPlus} are not thread-safe.
+ * They are designed to be used so that each thread as its own instance.
+ * The methods {@link #jump} and {@link #leap} and {@link #jumps} and {@link #leaps}
+ * can be used to construct new instances of {@link Xoshiro256PlusPlus} that traverse
+ * other parts of the state cycle.
+ *
+ * Instances of {@link Xoshiro256PlusPlus} are not cryptographically
+ * secure. Consider instead using {@link java.security.SecureRandom}
+ * in security-sensitive applications. Additionally,
+ * default-constructed instances do not use a cryptographically random
+ * seed unless the {@linkplain System#getProperty system property}
+ * {@code java.util.secureRandomSeed} is set to {@code true}.
+ *
+ * @since 17
+ *
+ */
+@RandomGeneratorProperties(
+ name = "Xoshiro256PlusPlus",
+ group = "Xoshiro",
+ i = 256, j = 1, k = 0,
+ equidistribution = 4
+)
+public final class Xoshiro256PlusPlus implements LeapableGenerator {
+
+ /*
+ * Implementation Overview.
+ *
+ * This is an implementation of the xoroshiro128++ algorithm version 1.0,
+ * written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org).
+ * See http://xoshiro.di.unimi.it and these two papers:
+ *
+ * Sebastiano Vigna. 2016. An Experimental Exploration of Marsaglia's
+ * xorshift Generators, Scrambled. ACM Transactions on Mathematical
+ * Software 42, 4, Article 30 (June 2016), 23 pages.
+ * https://doi.org/10.1145/2845077
+ *
+ * David Blackman and Sebastiano Vigna. 2018. Scrambled Linear
+ * Pseudorandom Number Generators. Computing Research Repository (CoRR).
+ * http://arxiv.org/abs/1805.01407
+ *
+ * The jump operation moves the current generator forward by 2*128
+ * steps; this has the same effect as calling nextLong() 2**128
+ * times, but is much faster. Similarly, the leap operation moves
+ * the current generator forward by 2*192 steps; this has the same
+ * effect as calling nextLong() 2**192 times, but is much faster.
+ * The copy method may be used to make a copy of the current
+ * generator. Thus one may repeatedly and cumulatively copy and
+ * jump to produce a sequence of generators whose states are well
+ * spaced apart along the overall state cycle (indeed, the jumps()
+ * and leaps() methods each produce a stream of such generators).
+ * The generators can then be parceled out to other threads.
+ *
+ * File organization: First static fields, then instance
+ * fields, then constructors, then instance methods.
+ */
+
+ /* ---------------- static fields ---------------- */
+
+ /**
+ * The seed generator for default constructors.
+ */
+ private static final AtomicLong DEFAULT_GEN = new AtomicLong(RandomSupport.initialSeed());
+
+ /* ---------------- instance fields ---------------- */
+
+ /**
+ * The per-instance state.
+ * At least one of the four fields x0, x1, x2, and x3 must be nonzero.
+ */
+ private long x0, x1, x2, x3;
+
+ /* ---------------- constructors ---------------- */
+
+ /**
+ * Basic constructor that initializes all fields from parameters.
+ * It then adjusts the field values if necessary to ensure that
+ * all constraints on the values of fields are met.
+ *
+ * @param x0 first word of the initial state
+ * @param x1 second word of the initial state
+ * @param x2 third word of the initial state
+ * @param x3 fourth word of the initial state
+ */
+ public Xoshiro256PlusPlus(long x0, long x1, long x2, long x3) {
+ this.x0 = x0;
+ this.x1 = x1;
+ this.x2 = x2;
+ this.x3 = x3;
+ // 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 = 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);
+ }
+ }
+
+ /**
+ * Creates a new instance of {@link Xoshiro256PlusPlus} using the
+ * specified {@code long} value as the initial seed. Instances of
+ * {@link Xoshiro256PlusPlus} created with the same seed in the same
+ * program generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public Xoshiro256PlusPlus(long seed) {
+ // Using a value with irregularly spaced 1-bits to xor the seed
+ // argument tends to improve "pedestrian" seeds such as 0 or
+ // other small integers. We may as well use SILVER_RATIO_64.
+ //
+ // 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(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));
+ }
+
+ /**
+ * Creates a new instance of {@link Xoshiro256PlusPlus} that is likely to
+ * generate sequences of values that are statistically independent
+ * of those of any other instances in the current program execution,
+ * but may, and typically does, vary across program invocations.
+ */
+ public Xoshiro256PlusPlus() {
+ // Using GOLDEN_RATIO_64 here gives us a good Weyl sequence of values.
+ this(DEFAULT_GEN.getAndAdd(RandomSupport.GOLDEN_RATIO_64));
+ }
+
+ /**
+ * Creates a new instance of {@link Xoshiro256PlusPlus} using the specified array of
+ * initial seed bytes. Instances of {@link Xoshiro256PlusPlus} created with the same
+ * seed array in the same program execution generate identical sequences of values.
+ *
+ * @param seed the initial seed
+ */
+ public Xoshiro256PlusPlus(byte[] seed) {
+ // Convert the seed to 4 long values, which are not all zero.
+ 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;
+ this.x2 = x2;
+ this.x3 = x3;
+ }
+
+ /* ---------------- public methods ---------------- */
+
+ public Xoshiro256PlusPlus copy() {
+ return new Xoshiro256PlusPlus(x0, x1, x2, x3);
+ }
+
+ /*
+ * The following two comments are quoted from http://prng.di.unimi.it/xoshiro256plusplus.c
+ */
+
+ /*
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty.
+ *
+ * See http://creativecommons.org/publicdomain/zero/1.0/.
+ */
+
+ /*
+ * This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
+ * It has excellent (sub-ns) speed, a state (256 bits) that is large
+ * enough for any parallel application, and it passes all tests we are
+ * aware of.
+ *
+ * For generating just floating-point numbers, xoshiro256+ is even faster.
+ *
+ * The state must be seeded so that it is not everywhere zero. If you have
+ * a 64-bit seed, we suggest to seed a splitmix64 generator and use its
+ * output to fill s.
+ */
+
+ @Override
+ public long nextLong() {
+ // Compute the result based on current state information
+ // (this allows the computation to be overlapped with state update).
+ final long result = Long.rotateLeft(x0 + x3, 23) + x0; // "plusplus" scrambler
+
+ long q0 = x0, q1 = x1, q2 = x2, q3 = x3;
+ { // xoshiro256 1.0
+ long t = q1 << 17;
+ q2 ^= q0;
+ q3 ^= q1;
+ q1 ^= q2;
+ q0 ^= q3;
+ q2 ^= t;
+ q3 = Long.rotateLeft(q3, 45);
+ }
+ x0 = q0; x1 = q1; x2 = q2; x3 = q3;
+ return result;
+ }
+
+ @Override
+ public double jumpDistance() {
+ return 0x1.0p128;
+ }
+
+ @Override
+ public double leapDistance() {
+ return 0x1.0p192;
+ }
+
+ private static final long[] JUMP_TABLE = {
+ 0x180ec6d33cfd0abaL, 0xd5a61266f0c9392cL, 0xa9582618e03fc9aaL, 0x39abdc4529b1661cL };
+
+ private static final long[] LEAP_TABLE = {
+ 0x76e15d3efefdcbbfL, 0xc5004e441c522fb3L, 0x77710069854ee241L, 0x39109bb02acbe635L };
+
+ @Override
+ public void jump() {
+ jumpAlgorithm(JUMP_TABLE);
+ }
+
+ @Override
+ public void leap() {
+ jumpAlgorithm(LEAP_TABLE);
+ }
+
+ private void jumpAlgorithm(long[] table) {
+ long s0 = 0, s1 = 0, s2 = 0, s3 = 0;
+ for (int i = 0; i < table.length; i++) {
+ for (int b = 0; b < 64; b++) {
+ if ((table[i] & (1L << b)) != 0) {
+ s0 ^= x0;
+ s1 ^= x1;
+ s2 ^= x2;
+ s3 ^= x3;
+ }
+ nextLong();
+ }
+ }
+ x0 = s0;
+ x1 = s1;
+ x2 = s2;
+ x3 = s3;
+ }
+
+}
diff --git a/src/jdk.random/share/classes/module-info.java b/src/jdk.random/share/classes/module-info.java
new file mode 100644
index 000000000000..1b2193ef5577
--- /dev/null
+++ b/src/jdk.random/share/classes/module-info.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, 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.
+ */
+
+import jdk.internal.util.random.RandomSupport;
+
+/**
+ * Defines implementations of the
+ * {@linkplain java.util.random.RandomGenerator RandomGenerator Interface}.
+ *
+ * @provides jdk.random.L128X1024MixRandom
+ * @provides jdk.random.L128X128MixRandom
+ * @provides jdk.random.L128X256MixRandom
+ * @provides jdk.random.L32X64MixRandom
+ * @provides jdk.random.L64X1024MixRandom
+ * @provides jdk.random.L64X128MixRandom
+ * @provides jdk.random.L64X128StarStarRandom
+ * @provides jdk.random.L64X256MixRandom
+ * @provides jdk.random.Xoroshiro128PlusPlus
+ * @provides jdk.random.Xoshiro256PlusPlus
+ *
+ * @use java.util.random.RandomGenerator
+ * @use jdk.internal.util.random.RandomSupport
+ *
+ * @moduleGraph
+ * @since 16
+ */
+module jdk.random {
+ exports jdk.random to
+ java.base;
+
+ provides java.util.random.RandomGenerator with
+ jdk.random.L32X64MixRandom,
+ jdk.random.L64X128MixRandom,
+ jdk.random.L64X128StarStarRandom,
+ jdk.random.L64X256MixRandom,
+ jdk.random.L64X1024MixRandom,
+ jdk.random.L128X128MixRandom,
+ jdk.random.L128X256MixRandom,
+ jdk.random.L128X1024MixRandom,
+ jdk.random.Xoroshiro128PlusPlus,
+ jdk.random.Xoshiro256PlusPlus;
+}
diff --git a/test/jdk/java/util/Random/RandomCanaryPi.java b/test/jdk/java/util/Random/RandomCanaryPi.java
new file mode 100644
index 000000000000..050adf381add
--- /dev/null
+++ b/test/jdk/java/util/Random/RandomCanaryPi.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020 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.
+ *
+ * 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.
+ */
+
+import java.util.Comparator;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGenerator.*;
+import java.util.random.RandomGeneratorFactory;
+
+/**
+ * @test
+ * @summary test bit sequences produced by clases that implement interface RandomGenerator
+ * @bug 8248862
+ * @run main RandomCanaryPi
+ * @key randomness
+ */
+
+public class RandomCanaryPi {
+ static double pi(RandomGenerator rng) {
+ int N = 10000000;
+ int k = 0;
+
+ for (int i = 0; i < N; i++) {
+ double x = rng.nextDouble();
+ double y = rng.nextDouble();
+
+ if (x * x + y * y <= 1.0) {
+ k++;
+ }
+ }
+
+ return 4.0 * (double)k / (double)N;
+ }
+
+ static int failed = 0;
+
+ public static void main(String[] args) {
+ RandomGeneratorFactory.all()
+ .sorted(Comparator.comparing(RandomGeneratorFactory::name))
+ .forEach(factory -> {
+ RandomGenerator rng = factory.create();
+ double pi = pi(rng);
+ double delta = Math.abs(Math.PI - pi);
+ boolean pass = delta < 1E-2;
+
+ if (!pass) {
+ System.err.println("Algorithm = " + factory.name() + " failed");
+ System.err.println("Actual = " + Math.PI);
+ System.err.println("Monte Carlo = " + pi);
+ System.err.println("Delta = " + delta);
+ System.err.println();
+
+ failed++;
+ }
+ });
+ if (failed != 0) {
+ throw new RuntimeException(failed + " tests failed");
+ }
+ }
+}
diff --git a/test/jdk/java/util/Random/RandomTestBsi1999.java b/test/jdk/java/util/Random/RandomTestBsi1999.java
new file mode 100644
index 000000000000..45943ba617ef
--- /dev/null
+++ b/test/jdk/java/util/Random/RandomTestBsi1999.java
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2012, 2020 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.
+ *
+ * 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.
+ */
+import java.util.ArrayList;
+import java.util.List;
+import java.util.PrimitiveIterator;
+
+import java.util.random.*;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+import java.util.function.BooleanSupplier;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+
+/**
+ * @test
+ * @summary test bit sequences produced by clases that implement interface RandomGenerator
+ * @bug 8248862
+ * @run main RandomTestBsi1999
+ * @key randomness
+ */
+
+public class RandomTestBsi1999 {
+
+ /* A set of tests for pseudorandom number generators inspired by this report:
+ *
+ * Werner Schindler. Functionality Classes and Evaluation Methodology for
+ * Deterministic Random Number Generators, Version 2.0.
+ * Bundesamt fur Sicherheit in der Informationstechnik (BSI). December 2, 1999.
+ * https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Zertifizierung/Interpretationen/AIS_20_Functionality_Classes_Evaluation_Methodology_DRNG_e.pdf
+ *
+ * Section F of this report (pp. 19-20) recommends the use of five tests to evaluate a
+ * sequence of bits:
+ *
+ * Monobit test
+ * Poker test
+ * Run test
+ * Long run test
+ * Autocorrelation test
+ *
+ * The first four of these tests are in turn taken from this report:
+ *
+ * National Institute of Standards and Technology (NIST),
+ * U.S. Department of Commerce. Security Requirements for
+ * Cryptographic Modules. Federal Information Processing
+ * Standard (FIPS) 140-1, January 11, 1994.
+ * https://csrc.nist.gov/csrc/media/publications/fips/140/1/archive/1994-01-11/documents/fips1401.pdf
+ *
+ * The BSI report appears to contain a few typos in transcribing the FIPS 140-1
+ * requirements (pp. 44-45); specifically, the last three intervals for the runs test
+ * (for lengths 4, 5, and 6+) are given as "223 - 402, 90 - 223, 90 - 223" in the FIPS
+ * standard but as "233-402, 90-223, 90-233" in the BSI publication. A quick
+ * mathematical check indicates that the FIPS 140-1 values are correct; therefore we
+ * use those values here. In addition, the BSI report specifies a test interval of
+ * 2326-2674 for the autocorrelation test, which provides an appropriately small
+ * rejection rate if the test were done for only a single value of tau; but because we
+ * wish to perform 5000 distinct tests, one for each value of tau in the range 1-5000,
+ * that test interval produces too many false positives. Some calculation shows that
+ * the interval 2267-2733 used by the FIPS 140-1 run test for runs of length 1 is
+ * appropriate, so we use that interval here for each of the 5000 individual
+ * autocorrelation tests.
+ *
+ * Each of the four FIPS 140-1 tests examines a sequence of 20000 bits. The
+ * autocorrelation test examines a sequence of 10000 bits. It is convenient to
+ * generate a sequence of 20000 bits (which we represent as an array of 20000 bytes)
+ * and then apply all five tests, knowing that the autocorrelation test will examine
+ * only the first half of the byte array.
+ *
+ * The descriptions of the tests are quoted from the FIPS 140-1 and BSI reports
+ * (with some adjustments of punctuation and mathematical symbols, as well as
+ * for our specific choices of test intervals).
+ */
+
+ static String currentRNG = "";
+ static int failCount = 0;
+
+ static void exceptionOnFail() {
+ if (failCount != 0) {
+ throw new RuntimeException(failCount + " fails detected");
+ }
+ }
+
+ static void setRNG(String rng) {
+ currentRNG = rng;
+ }
+
+ static void fail(String format, Object... args) {
+ if (currentRNG.length() != 0) {
+ System.err.println(currentRNG);
+ currentRNG = "";
+ }
+
+ System.err.format(" " + format, args);
+ failCount++;
+ }
+
+ private static final int SEQUENCE_SIZE = 20000;
+
+ /* The Monobit Test
+ *
+ * 1. Count the number of ones in the 20,000 bit stream. Denote this quantity by X.
+ *
+ * 2. The test is passed if 9,654 < X < 10,346.
+ */
+ static int monobitTest(String id, byte[] s) {
+ // System.out.println("monobit test");
+ int count = 0;
+ for (int j = 0; j < s.length; j++) {
+ count += s[j];
+ }
+ int monobitFailure = ((9654 < count) && (count < 10346)) ? 0 : 1;
+ if (monobitFailure != 0) fail("monobit test failure for %s: count=%d (should be in [9654,10346])\n", id, count);
+ return monobitFailure;
+ }
+
+ /* The Poker Test
+ *
+ * 1. Divide the 20,000 bit stream into 5,000 contiguous 4-bit segments. Count and
+ * store the number of occurrences of each of the 16 possible 4-bit values. Denote
+ * f(i) as the number of each 4-bit value i where 0 <= i <= 15.
+ *
+ * 2. Evaluate the following: X = (16/5000)(sum[i=0,15] (f(i))**2) - 5000
+ *
+ * 3. The test is passed if 1.03 < X < 57.4.
+ */
+
+ static int pokerTest(String id, byte[] s) {
+ // System.out.println("poker test");
+ // Divide the bit sequence into 4-bit chunks, and count the number of times each 4-bit value appears.
+ int[] stats = new int[16];
+ int v = 0;
+ for (int j = 0; j < s.length; j++) {
+ v = (v << 1) | s[j];
+ if ((j & 3) == 3) {
+ ++stats[v];
+ v = 0;
+ }
+ }
+ int z = 0;
+ for (int k = 0; k < stats.length; k++) {
+ z += stats[k]*stats[k];
+ }
+ double x = (16.0 / (s.length / 4)) * z - (s.length / 4);
+ int pokerFailure = ((1.03 < x) && (x < 57.4)) ? 0 : 1;
+ if (pokerFailure != 0) fail("poker test failure for %s: x=%g (should be in [1.03,57.4])\n", id, x);
+ return pokerFailure;
+ }
+
+ /* The Runs Test
+ *
+ * 1. A run is defined as a maximal sequence of consecutive bits of either all ones
+ * or all zeros, which is part of the 20,000 bit sample stream. The incidences of
+ * runs (for both consecutive zeros and consecutive ones) of all lengths (>= 1) in
+ * the sample stream should be counted and stored.
+ *
+ * 2. The test is passed if the number of runs that occur (of lengths 1 through 6)
+ * is each within the corresponding interval specified below. This must hold for
+ * both the zeros and ones; that is, all 12 counts must lie in the specified
+ * interval. For the purpose of this test, runs of greater than 6 are considered to
+ * be of length 6.
+ *
+ * Length of run Required Interval
+ * 1 2,267 - 2,733
+ * 2 1,079 - 1,421
+ * 3 502 - 748
+ * 4 223 - 402
+ * 5 90 - 223
+ * 6+ 90 - 223
+ *
+ * The Long Run Test
+ *
+ * 1 . A long run is defined to be a run of length 34 or more (of either zeros or ones).
+ *
+ * 2. On the sample of 20,000 bits, the test is passed if there are NO long runs.
+ */
+ static int runTestAndLongRunTest(String id, byte[] s) {
+ // System.out.println("run test");
+ int[][] stats = new int[2][8];
+ int count = 0;
+ for (int j = 0; j < s.length; j++) {
+ ++count;
+ if ((j == (s.length - 1)) || (s[j+1] != s[j])) {
+ ++stats[s[j]][(count < 6) ? count : (count < 34) ? 6 : 7];
+ count = 0;
+ }
+ }
+ stats[0][6] += stats[0][7];
+ stats[1][6] += stats[1][7];
+ int runFailure = checkRunStats(stats[0]) | checkRunStats(stats[1]);
+ if (runFailure != 0) fail("run test failure for %s\n", id);
+ int longRunFailure = ((stats[0][7] == 0) && (stats[1][7] == 0)) ? 0 : 1;
+ if (longRunFailure != 0) fail("long run test failure for %s\n", id);
+ return (runFailure + longRunFailure);
+ }
+
+ static int checkRunStats(int[] stats) {
+ int runFailure = 0;
+ runFailure |= ((2267 <= stats[1]) && (stats[1] <= 2733)) ? 0 : 1;
+ runFailure |= ((1079 <= stats[2]) && (stats[2] <= 1421)) ? 0 : 1;
+ runFailure |= (( 502 <= stats[3]) && (stats[3] <= 748)) ? 0 : 1;
+ runFailure |= (( 223 <= stats[4]) && (stats[4] <= 402)) ? 0 : 1;
+ runFailure |= (( 90 <= stats[5]) && (stats[5] <= 223)) ? 0 : 1;
+ runFailure |= (( 90 <= stats[6]) && (stats[6] <= 223)) ? 0 : 1;
+ return runFailure;
+ }
+
+ /* Autocorrelation Test
+ *
+ * For tau in {1, ..., 5000}, Z[tau] := sum[j=1,5000] (b[j] ^ b[j+tau]).
+ *
+ * The sequence passes the autocorrelation test if every Z[tau] lies within the
+ * interval 2267-2733.
+ */
+ static int autocorrelationTest(String id, byte[] s) {
+ // System.out.println("autocorrelation test");
+ int autocorrelationFailure = 0;
+ int N = s.length / 4;
+ for (int tau = 1; tau <= N; tau++) {
+ int count = 0;
+ for (int j = 0; j < N; j++) {
+ count += (s[j] ^ s[j+tau]);
+ }
+ // We intentionally use bounds [2267, 2733], which are wider than
+ // the bounds [2326, 2674] specified by BSI for this test.
+ // The latter bounds produce way too many false positives.
+ int singleAutocorrelationFailure = ((2267 < count) && (count < 2733)) ? 0 : 1;
+ if (singleAutocorrelationFailure != 0) {
+ if (autocorrelationFailure < 8) {
+ fail("autocorrelation failure for %s: count=%d (should be in [2267,2733]), tau=%d\n", id, count, tau);
+ if (count < 100 || count > 4900) {
+ System.out.print(" ");
+ for (int q = 0; q < 50; q++) System.out.print(s[q]);
+ System.out.println();
+ }
+ }
+ }
+ autocorrelationFailure += singleAutocorrelationFailure;
+ }
+ return (autocorrelationFailure == 0) ? 0 : 1;
+ }
+
+ static int entireBsi1999Test(String id, byte[] s) {
+ return (monobitTest(id, s) +
+ pokerTest(id, s) +
+ runTestAndLongRunTest(id, s) +
+ autocorrelationTest(id, s)
+ );
+ }
+
+ /* To test a sequence of boolean values from a BooleanSupplier,
+ * sequentially extract 20000 boolean values, convert to an array
+ * of bytes, and feed them to method {@code entireBsi1999Test}.
+ */
+
+ static int testRngBsi1999BooleanOnce(String id, BooleanSupplier theSupplier) {
+ int failureCount = 0;
+ byte[] s = new byte[SEQUENCE_SIZE];
+ // Take the next SEQUENCE_SIZE booleans and test them
+ for (int j = 0; j < s.length; j++) {
+ s[j] = (theSupplier.getAsBoolean() ? (byte)1 : (byte)0);
+ }
+ failureCount += entireBsi1999Test(id + " consecutive", s);
+ return failureCount;
+ }
+
+ /* To test a sequence of long values from a LongSupplier,
+ * two kinds of tests are performed.
+ *
+ * The first kind of test extracts 313=ceiling(20000/64) long
+ * values and concatenates all their bits; the first 20000 bits
+ * are converted to a byte array of bits to be tested. This test is
+ * repeated 64 times.
+ *
+ * The second kind of test focuses on one bit position m (0 <= m < 64);
+ * it extracts 20000 long values and uses just bit m from each value
+ * to produce an array of bytes to be tested. This test is performed
+ * once for each possible value of m (64 times in all).
+ */
+ static int testRngBsi1999LongOnce(String id, LongSupplier theSupplier) {
+ int failureCount = 0;
+ byte[] s = new byte[SEQUENCE_SIZE];
+ // Part 1: 64 times, take the next SEQUENCE_SIZE bits and test them
+ for (int m = 0; m < 64; m++) {
+ long bits = 0;
+ int bitCount = 0;
+ for (int j = 0; j < s.length; j++) {
+ if ((j & 0x3f) == 0) {
+ bits = theSupplier.getAsLong();
+ // System.out.printf("0x%016x\n", bits);
+ bitCount += Long.bitCount((j == (20000 - 32)) ? ((bits << 32) >>> 32) : bits);
+ }
+ s[j] = (byte)(bits & 1);
+ bits >>>= 1;
+ }
+ // System.out.println(m + ": " + bitCount + " 1-bits");
+ failureCount += entireBsi1999Test(id + " consecutive (" + bitCount + " 1-bits)", s);
+ }
+ // Part 2: for 0 <= m < 64, use bit m from each of the next SEQUENCE_SIZE longs
+ for (int m = 0; m < 64; m++) {
+ for (int j = 0; j < s.length; j++) {
+ s[j] = (byte)((theSupplier.getAsLong() >>> m) & 1);
+ }
+ failureCount += entireBsi1999Test(id + " bit " + m, s);
+ }
+ return failureCount;
+ }
+
+ /* To test a sequence of ing values from an IntSupplier,
+ * two kinds of tests are performed.
+ *
+ * The first kind of test extracts 625=20000/32 int values and
+ * concatenates all their bits; these 20000 bits are converted to
+ * a byte array of bits to be tested. This test is repeated 64
+ * times.
+ *
+ * The second kind of test focuses on one bit position m (0 <= m < 32);
+ * it extracts 20000 int values and uses just bit m from each value
+ * to produce an array of bytes to be tested. This test is performed
+ * once for each possible value of m (32 times in all).
+ */
+ static int testRngBsi1999IntOnce(String id, IntSupplier theSupplier) {
+ int failureCount = 0;
+ byte[] s = new byte[SEQUENCE_SIZE];
+ // Part 1: 64 times, take the next SEQUENCE_SIZE bits and test them
+ for (int m = 0; m < 64; m++) {
+ int bits = 0;
+ int bitCount = 0;
+ for (int j = 0; j < s.length; j++) {
+ if ((j & 0x1f) == 0) {
+ bits = theSupplier.getAsInt();
+ bitCount += Integer.bitCount(bits);
+ }
+ s[j] = (byte)(bits & 1);
+ bits >>>= 1;
+ }
+ // System.out.println(m + ": " + bitCount + " 1-bits");
+ failureCount += entireBsi1999Test(id + " consecutive (" + bitCount + " 1-bits)", s);
+ }
+ // Part 2: for 0 <= m < 32, use bit m from each of the next SEQUENCE_SIZE ints
+ for (int m = 0; m < 32; m++) {
+ for (int j = 0; j < s.length; j++) {
+ s[j] = (byte)((theSupplier.getAsInt() >>> m) & 1);
+ }
+ failureCount += entireBsi1999Test(id + " bit " + m, s);
+ }
+ return failureCount;
+ }
+
+ /* A call to {@code entireBsi1999Test} may report failure even if the source of random
+ * bits is quite good, because the test is statistical in nature. To make the testing
+ * procedure more robust, if the first call to {@code entireBsi1999Test} fails, then
+ * the failure is ignored if two more calls to {@code entireBsi1999Test} both succeed.
+ */
+
+ static boolean testRngBsi1999Boolean(String id, BooleanSupplier theSupplier, int failureTolerance) {
+ if (testRngBsi1999BooleanOnce(id, theSupplier) <= failureTolerance) return true;
+ fail("testRngBsi1999Boolean glitch");
+ return ((testRngBsi1999BooleanOnce(id, theSupplier) <= failureTolerance) &&
+ (testRngBsi1999BooleanOnce(id, theSupplier) <= failureTolerance));
+ }
+
+ static boolean testRngBsi1999Long(String id, LongSupplier theSupplier, int failureTolerance) {
+ if (testRngBsi1999LongOnce(id, theSupplier) <= failureTolerance) return true;
+ fail("testRngBsi1999Long glitch");
+ return ((testRngBsi1999LongOnce(id, theSupplier) <= failureTolerance) &&
+ (testRngBsi1999LongOnce(id, theSupplier) <= failureTolerance));
+ }
+
+ static boolean testRngBsi1999Int(String id, IntSupplier theSupplier, int failureTolerance) {
+ if (testRngBsi1999IntOnce(id, theSupplier) <= failureTolerance) return true;
+ fail("testRngBsi1999Int glitch");
+ return ((testRngBsi1999IntOnce(id, theSupplier) <= failureTolerance) &&
+ (testRngBsi1999IntOnce(id, theSupplier) <= failureTolerance));
+ }
+
+ static void tryIt(RandomGenerator rng, String id, BooleanSupplier theSupplier) {
+ System.out.printf("Testing %s %s\n", rng.getClass().getName(), id);
+ boolean success = theSupplier.getAsBoolean();
+ if (!success) {
+ fail("*** Failure of %s %s\n", rng.getClass().getName(), id);
+ }
+ }
+
+ static void testOneRng(RandomGenerator rng, int failureTolerance) {
+ String name = rng.getClass().getName();
+ tryIt(rng, "nextInt", () -> testRngBsi1999Int(name + " nextInt", rng::nextInt, failureTolerance));
+ tryIt(rng, "nextLong", () -> testRngBsi1999Long(name + " nextLong", rng::nextLong, failureTolerance));
+ tryIt(rng, "nextBoolean", () -> testRngBsi1999Boolean(name + " nextBoolean", rng::nextBoolean, failureTolerance));
+ tryIt(rng, "ints", () -> testRngBsi1999Int(name + " ints", rng.ints().iterator()::next, failureTolerance));
+ tryIt(rng, "longs", () -> testRngBsi1999Long(name + " longs", rng.longs().iterator()::next, failureTolerance));
+ {
+ PrimitiveIterator.OfDouble iter = rng.doubles().iterator();
+ tryIt(rng, "doubles",
+ () -> testRngBsi1999Int(name + " doubles",
+ () -> (int)(long)Math.floor(iter.next() * 0x1.0p32),
+ failureTolerance));
+ }
+ tryIt(rng, "nextDouble",
+ () -> testRngBsi1999Int(name + " nextDouble",
+ () -> (int)(long)Math.floor(rng.nextDouble() * 0x1.0p32),
+ failureTolerance));
+ tryIt(rng, "nextFloat",
+ () -> testRngBsi1999Int(name + " nextFloat",
+ () -> (((int)(long)Math.floor(rng.nextFloat() * 0x1.0p16f) << 16)
+ | (int)(long)Math.floor(rng.nextFloat() * 0x1.0p16f)),
+ failureTolerance));
+ }
+
+ public static void main(String[] args) {
+ RandomGeneratorFactory.all().forEach(factory -> {
+ setRNG(factory.name());
+
+ if (factory.name().equals("Random")) {
+ // testOneRng(factory.create(59), 1);
+ // autocorrelation failure for java.util.Random longs bit 0: count=2207 (should be in [2267,2733]), tau=2819
+
+ } else {
+ testOneRng(factory.create(59), 0);
+ }
+ });
+
+ exceptionOnFail();
+ }
+}
+
diff --git a/test/jdk/java/util/Random/RandomTestChiSquared.java b/test/jdk/java/util/Random/RandomTestChiSquared.java
new file mode 100644
index 000000000000..5d4cfa313d31
--- /dev/null
+++ b/test/jdk/java/util/Random/RandomTestChiSquared.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2012, 2013, 2019, 2020, 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.
+ *
+ * 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.
+ */
+import java.util.ArrayList;
+import java.util.List;
+import java.util.PrimitiveIterator;
+
+import java.util.random.*;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+import java.util.function.BooleanSupplier;
+import java.util.function.Supplier;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+
+/**
+ * @test
+ * @summary test bit sequences produced by clases that implement interface RandomGenerator
+ * @bug 8248862
+ * @run main RandomTestChiSquared
+ * @key randomness
+ */
+
+public class RandomTestChiSquared {
+
+ static String currentRNG = "";
+ static int failCount = 0;
+
+ static void exceptionOnFail() {
+ if (failCount != 0) {
+ throw new RuntimeException(failCount + " fails detected");
+ }
+ }
+
+ static void setRNG(String rng) {
+ currentRNG = rng;
+ }
+
+ static void fail(String format, Object... args) {
+ if (currentRNG.length() != 0) {
+ System.err.println(currentRNG);
+ currentRNG = "";
+ }
+
+ System.err.format(" " + format, args);
+ failCount++;
+ }
+
+ // Some simple chi-squared tests similar to that used for the FIPS 140 poker test,
+ // but intended primarily to test production of random values from ranges.
+
+ private static final int SEQUENCE_SIZE = 20000;
+
+ // Entry k of this table was computed in Microsoft Excel using the formulae
+ // =CHISQ.INV(0.0000000777517,k) and =CHISQ.INV.RT(0.00000142611,k)
+ // (except that entry 0 is a dummy and should never be used).
+ static final double[][] chiSquaredBounds = {
+ { 0.0, 0.0 },
+ { 9.49598E-15, 23.24513154 },
+ { 1.55503E-07, 26.92112020 },
+ { 4.40485E-05, 29.93222467 },
+ { 0.000788782, 32.62391510 },
+ { 0.004636947, 35.11665045 },
+ { 0.015541535, 37.46947634 },
+ { 0.037678318, 39.71667636 },
+ { 0.074471919, 41.88031518 },
+ { 0.128297057, 43.97561646 },
+ { 0.200566433, 46.01362542 },
+ { 0.291944952, 48.00266676 },
+ { 0.402564694, 49.94920504 },
+ { 0.532199236, 51.85838271 },
+ { 0.680392565, 53.73437242 },
+ { 0.846549931, 55.58061674 },
+ { 1.030000010, 57.39999630 },
+ { 1.230036580, 59.19495111 },
+ { 1.445945898, 60.96756998 },
+ { 1.677024296, 62.71965780 },
+ { 1.922589129, 64.45278706 },
+ { 2.181985238, 66.16833789 },
+ { 2.454588423, 67.86752964 },
+ { 2.739806923, 69.55144602 },
+ { 3.037081611, 71.22105544 },
+ { 3.345885349, 72.87722754 },
+ { 3.665721841, 74.52074682 },
+ { 3.996124178, 76.15232388 },
+ { 4.336653242, 77.77260487 },
+ { 4.686896041, 79.38217943 },
+ { 5.046464051, 80.98158736 },
+ { 5.414991603, 82.57132439 }
+ };
+
+
+
+ // N is the number of categories; every element of s ought to be in [0,N).
+ // N must be in [1,31].
+ static boolean chiSquaredTest(String id, int N, IntSupplier theSupplier) {
+ int[] stats = new int[N];
+ for (int j = 0; j < SEQUENCE_SIZE; j++) {
+ int v = theSupplier.getAsInt();
+ // assert((0 <= v) && (v < N));
+ ++stats[v];
+ }
+ int z = 0;
+ for (int k = 0; k < stats.length; k++) {
+ z += stats[k]*stats[k];
+ }
+ double x = ((double)N / (double)SEQUENCE_SIZE) * (double)z - (double)SEQUENCE_SIZE;
+ double lo = chiSquaredBounds[N][0];
+ double hi = chiSquaredBounds[N][1];
+ boolean chiSquaredSuccess = ((lo < x) && (x < hi));
+ if (!chiSquaredSuccess) fail("chi-squared test failure for %s: x=%g (should be in [%g,%g])\n", id, x, lo, hi);
+ return chiSquaredSuccess;
+ }
+
+ static boolean testRngChiSquared(String id, int N, IntSupplier theSupplier) {
+ if (chiSquaredTest(id, N, theSupplier)) return true;
+ fail("testRngChiSquared glitch");
+ return chiSquaredTest(id, N, theSupplier) && chiSquaredTest(id, N, theSupplier);
+ }
+
+ static void tryIt(RandomGenerator rng, String kind, Function{@code
+ * RandomGeneratorFactory
+ *
+ * RandomGeneratorFactory also provides methods describing the attributes (or properties)
+ * of a generator and can be used to select random number generator
+ * algorithms.
+ * These methods are typically used in
+ * conjunction with {@link RandomGeneratorFactory#all()}. In this example, the code
+ * locates the {@link RandomGeneratorFactory} that produces
+ * {@link RandomGenerator RandomGenerators}
+ * with the highest number of state bits.
+ *
+ * {@code
+ * RandomGeneratorFactory
+ *
+ * @since 17
+ *
+ * @see java.util.random
+ *
+ */
+public final class RandomGeneratorFactoryUsing the Random Number Generator Interfaces
+ *
+ * To get started, an application should first create one instance of a
+ * generator class. Assume that the contents of the package
+ * {@link java.util.random} has been imported:
+ *
+ * {@code import java.util.random.*;}
+ *
+ * Then one can choose a specific implementation by giving the name of a generator
+ * algorithm to the static method {@link RandomGenerator#of}, in which case the
+ * no-arguments constructor for that implementation is used:
+ *
+ * {@code RandomGenerator g = RandomGenerator.of("L64X128MixRandom");}
+ *
+ * For a single-threaded application, this is all that is needed. One can then
+ * invoke methods of {@code g} such as
+ * {@link RandomGenerator#nextLong nextLong()},
+ * {@link RandomGenerator#nextInt nextInt()},
+ * {@link RandomGenerator#nextFloat nextFloat()},
+ * {@link RandomGenerator#nextDouble nextDouble()} and
+ * {@link RandomGenerator#nextBoolean nextBoolean()} to generate individual
+ * randomly chosen values. One can also use the methods
+ * {@link RandomGenerator#ints ints()}, {@link RandomGenerator#longs longs()}
+ * and {@link RandomGenerator#doubles doubles()} to create streams of randomly
+ * chosen values. The methods
+ * {@link RandomGenerator#nextGaussian nextGaussian()} and
+ * {@link RandomGenerator#nextExponential nextExponential()} draw floating-point
+ * values from nonuniform distributions.
+ *
+ * Choosing a Random Number Generator Algorithm
+ *
+ * Random Number Generator Algorithms Available
+ *
+ * These algorithms [in the table below] must be found with the current version
+ * of Java SE. A particular JDK implementation may recognize additional
+ * algorithms; check the JDK's documentation for details. The set of algorithm
+ * required by Java SE may be updated by changes to the Java SE specification.
+ * Over time, new algorithms may be added and old algorithms may be removed.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * Algorithm
+ * Group
+ * Period
+ * StateBits
+ * Equidistribution
+ *
+ *
+ * L128X1024MixRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(N*64).subtract(BigInteger.ONE).shiftLeft(128)
+ * 1152
+ * 1
+ *
+ *
+ * L128X128MixRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(128)
+ * 256
+ * 1
+ *
+ *
+ * L128X256MixRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(128)
+ * 384
+ * 1
+ *
+ *
+ * L32X64MixRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE).shiftLeft(32)
+ * 96
+ * 1
+ *
+ *
+ * L64X1024MixRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(N*64).subtract(BigInteger.ONE).shiftLeft(64)
+ * 1088
+ * 16
+ *
+ *
+ * L64X128MixRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(64)
+ * 192
+ * 1
+ *
+ *
+ * L64X128StarStarRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE).shiftLeft(64)
+ * 192
+ * 1
+ *
+ *
+ * L64X256MixRandom
+ * LXM
+ * BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE).shiftLeft(64)
+ * 320
+ * 4
+ *
+ *
+ * Random
+ * Legacy
+ * BigInteger.ONE.shiftLeft(48)
+ * 48
+ * 0
+ *
+ *
+ * SplittableRandom
+ * Legacy
+ * BigInteger.ONE.shiftLeft(64)
+ * 64
+ * 1
+ *
+ *
+ * ThreadLocalRandom *
+ * Legacy
+ * BigInteger.ONE.shiftLeft(64)
+ * 64
+ * 1
+ *
+ *
+ * Xoroshiro128PlusPlus
+ * Xoroshiro
+ * BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE)
+ * 128
+ * 2
+ *
+ *
+ *
+ * Xoshiro256PlusPlus
+ * Xoshiro
+ * BigInteger.ONE.shiftLeft(256).subtract(BigInteger.ONE)
+ * 256
+ * 4
+ * Categories of Random Number Generator Algorithms
+ *
+ * Historically, most pseudorandom generator algorithms have been based on some
+ * sort of finite-state machine with a single, large cycle of states; when it is
+ * necessary to have multiple threads use the same algorithm simultaneously, the
+ * usual technique is to arrange for each thread to traverse a different region
+ * of the state cycle. These regions may be doled out to threads by starting
+ * with a single initial state and then using a "jump function" that travels a
+ * long distance around the cycle (perhaps 264 steps or more); the
+ * jump function is applied repeatedly and sequentially, to identify widely
+ * spaced states that are then doled out, one to each thread, to serve as the
+ * initial state for the generator to be used by that thread. This strategy is
+ * supported by the interface {@link RandomGenerator.JumpableGenerator}.
+ * Sometimes it is desirable to support two levels of jumping (by long distances
+ * and by really long distances); this strategy is supported by the
+ * interface {@link RandomGenerator.LeapableGenerator}. There is also an interface
+ * {@link RandomGenerator.ArbitrarilyJumpableGenerator} for algorithms that allow
+ * jumping along the state cycle by any user-specified distance. In this package,
+ * implementations of these interfaces include
+ * "Xoroshiro128PlusPlus", and
+ * "Xoshiro256PlusPlus".
+ *
+ * The LXM Family of Random Number Generator Algorithms
+ *
+ * The structure of the central nextLong (or nextInt) method of an LXM
+ * algorithm follows a suggestion in December 2017 by Sebastiano Vigna
+ * that using one LCG subgenerator and one xor-based subgenerator (rather
+ * than two LCG subgenerators) would provide a longer period, superior
+ * equidistribution, scalability, and better quality. Each of the
+ * specific implementations here combines one of the best currently known
+ * xor-based generators (xoroshiro or xoshiro, described by Blackman and
+ * Vigna in "Scrambled Linear Pseudorandom Number Generators", ACM
+ * Trans. Math. Softw., 2021) with an LCG that uses one of the best
+ * currently known multipliers (found by a search for better multipliers
+ * in 2019 by Steele and Vigna), and then applies a mixing function
+ * identified by Doug Lea. Testing has confirmed that the LXM algorithm
+ * is far superior in quality to the SplitMix algorithm (2014) used by
+ * SplittableRandom.
+ *
+ * Each class with a name of the form {@code L}p{@code X}q{@code
+ * SomethingRandom} uses some specific member of the LXM family of random number
+ * algorithms; "LXM" is short for "LCG, Xorshift, Mixing function". Every LXM
+ * generator consists of two subgenerators; one is an LCG (Linear Congruential
+ * Generator) and the other is an Xorshift generator. Each output of an LXM
+ * generator is the result of combining state from the LCG with state from the
+ * Xorshift generator by using a Mixing function (and then the state of the LCG
+ * and the state of the Xorshift generator are advanced).
+ *
+ *
+ *
+ *
+ * For the algorithms listed above whose names begin with {@code L32}, the
+ * 32-bit values produced by the {@link RandomGenerator#nextInt nextInt()}
+ * method are exactly equidistributed, but the 64-bit values produced by the
+ * {@link RandomGenerator#nextLong nextLong()} method are not exactly
+ * equidistributed.
+ *
+ *
+ *
+ *
+ * Implementation
+ * Period
+ * State size
+ * Parameter size
+ * {@link RandomGenerator#nextLong nextLong()} values are
+ * "L32X64MixRandom"
+ * 232(264−1)
+ * 96 bits
+ * 32 bits
+ *
+ * "L64X128StarStarRandom"
+ * 264(2128−1)
+ * 192 bits
+ * 64 bits
+ * 2-equidistributed and exactly equidistributed
+ * "L64X128MixRandom"
+ * 264(2128−1)
+ * 192 bits
+ * 64 bits
+ * 2-equidistributed and exactly equidistributed
+ * "L64X256MixRandom"
+ * 264(2256−1)
+ * 320 bits
+ * 64 bits
+ * 4-equidistributed and exactly equidistributed
+ * "L64X1024MixRandom"
+ * 264(21024−1)
+ * 1088 bits
+ * 64 bits
+ * 16-equidistributed and exactly equidistributed
+ * "L128X128MixRandom"
+ * 2128(2128−1)
+ * 256 bits
+ * 128 bits
+ * exactly equidistributed
+ * "L128X256MixRandom"
+ * 2128(2256−1)
+ * 384 bits
+ * 128 bits
+ * exactly equidistributed
+ *
+ * "L128X1024MixRandom"
+ * 2128(21024−1)
+ * 1152 bits
+ * 128 bits
+ * exactly equidistributed
+ *
+ *
+ * @since 17
+ */
+package java.util.random;
+
diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java
new file mode 100644
index 000000000000..1cf59d753dfc
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java
@@ -0,0 +1,3075 @@
+/*
+ * Copyright (c) 2020, 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 jdk.internal.util.random;
+
+import java.lang.annotation.*;
+import java.math.BigInteger;
+import java.util.Objects;
+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;
+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.
+ *
+ *
+ *
+ *
+ * Implementation
+ * LCG multiplier {@code m}
+ * Xorshift algorithm
+ * Xorshift parameters
+ * Mixing function
+ * "L32X64MixRandom"
+ * {@code 0xadb4a92d}
+ * {@code xoroshiro64}, version 1.0
+ * {@code (26, 9, 13)}
+ * mixLea32{@code (s+x0)}
+ * "L64X128StarStarRandom"
+ * {@code 0xd1342543de82ef95L}
+ * {@code xoroshiro128}, version 1.0
+ * {@code (24, 16, 37)}
+ * {@code Long.rotateLeft((s+x0)* 5, 7) * 9}
+ * "L64X128MixRandom"
+ * {@code 0xd1342543de82ef95L}
+ * {@code xoroshiro128}, version 1.0
+ * {@code (24, 16, 37)}
+ * mixLea32{@code (s+x0)}
+ * "L64X256MixRandom"
+ * {@code 0xd1342543de82ef95L}
+ * {@code xoshiro256}, version 1.0
+ * {@code (17, 45)}
+ * mixLea32{@code (s+x0)}
+ * "L64X1024MixRandom"
+ * {@code 0xd1342543de82ef95L}
+ * {@code xoroshiro1024}, version 1.0
+ * {@code (25, 27, 36)}
+ * mixLea32{@code (s+x0)}
+ * "L128X128MixRandom"
+ * {@code 0x1d605bbb58c8abbfdL}
+ * {@code xoroshiro128}, version 1.0
+ * {@code (24, 16, 37)}
+ * mixLea32{@code (sh+x0)}
+ * "L128X256MixRandom"
+ * {@code 0x1d605bbb58c8abbfdL}
+ * {@code xoshiro256}, version 1.0
+ * {@code (17, 45)}
+ * mixLea32{@code (sh+x0)}
+ *
+ * "L128X1024MixRandom"
+ * {@code 0x1d605bbb58c8abbfdL}
+ * {@code xoroshiro1024}, version 1.0
+ * {@code (25, 27, 36)}
+ * mixLea32{@code (sh+x0)}
+ *
+ *
+ *
+ * @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 {@link RandomGenerator#nextLong() nextLong}() used by
+ * the public method {@link RandomGenerator#nextLong(long) nextLong}(bound).
+ * This is essentially a version of
+ * {@link RandomSupport#boundedNextLong(RandomGenerator, long, long) boundedNextLong}(rng, 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 264
+ * possible {@code long} values (that is, each of the 264
+ * 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).
+ *
+ * The implementation considers two cases:
+ *
+ *
+ *
+ *
+ * @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 {@link RandomGenerator#nextInt() nextInt}() used by
+ * an {@link IntStream} {@link Spliterator} and by the public method
+ * {@link RandomGenerator#nextInt(int, int) nextInt}(origin, bound). If
+ * {@code origin} is greater than {@code bound}, then this method simply
+ * calls the unbounded version of
+ * {@link RandomGenerator#nextInt() nextInt}(), choosing pseudorandomly
+ * from among all 264 possible {@code int} values}, and otherwise
+ * uses one or more calls to {@link RandomGenerator#nextInt() 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 {@link RandomGenerator#nextInt() nextInt}() used by
+ * the public method {@link RandomGenerator#nextInt(int) nextInt}(bound).
+ * This is essentially a version of
+ * {@link RandomSupport#boundedNextInt(RandomGenerator, int, int) boundedNextInt}(rng, 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 {@link RandomGenerator#nextDouble() nextDouble}()
+ * used by a {@link DoubleStream} {@link Spliterator} and by the public
+ * method
+ * {@link RandomGenerator#nextDouble(double, double) nextDouble}(origin, bound).
+ * If {@code origin} is greater than {@code bound}, then this method simply
+ * calls the unbounded version of
+ * {@link RandomGenerator#nextDouble() nextDouble}(), and otherwise scales
+ * and translates the result of a call to
+ * {@link RandomGenerator#nextDouble() nextDouble}() so that it lies between
+ * {@code origin} (inclusive) and {@code bound} (exclusive).
+ *
+ * @implNote The implementation considers two cases:
+ *
+ *
+ *
+ *
+ * @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 {@link RandomGenerator#nextDouble() nextDouble}()
+ * used by the public method
+ * {@link RandomGenerator#nextDouble(double) nextDouble}(bound). This is
+ * essentially a version of
+ * {@link RandomSupport#boundedNextDouble(RandomGenerator, double, double) boundedNextDouble}(rng, 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 {@link RandomGenerator#nextFloat() nextFloat}() used
+ * by a {@link Stream