# HG changeset patch # User jlaskey # Date 1565202955 10800 # Node ID 6a4be8bf89903d57fa022ca4a56bab83d876c503 # Parent 56cbdc3ea0796f2b73dbaabcff71fbcf8a85f42b imported patch factory diff -r 56cbdc3ea079 -r 6a4be8bf8990 src/java.base/share/classes/java/util/Random.java --- a/src/java.base/share/classes/java/util/Random.java Fri Jul 26 15:37:05 2019 -0300 +++ b/src/java.base/share/classes/java/util/Random.java Wed Aug 07 15:35:55 2019 -0300 @@ -31,18 +31,13 @@ import java.math.BigInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.function.DoubleConsumer; -import java.util.function.Function; import java.util.function.IntConsumer; import java.util.function.LongConsumer; -import java.util.Objects; import java.util.random.RandomGenerator; import java.util.random.RandomSupport; import java.util.random.RandomSupport.AbstractSpliteratorGenerator; import java.util.random.RandomSupport.RandomSpliterator; -import java.util.ServiceLoader; -import java.util.ServiceLoader.Provider; import java.util.Spliterator; -import java.util.stream.Collectors; /** * An instance of this class is used to generate a stream of @@ -501,47 +496,6 @@ } /** - * Creates a new random number generator that uses the random number generator algorithm - * specified by name. The seed of the random number generator to a value very likely to be - * distinct from any other invocation. - * - * @param name name of random number generator algorithm to use. - * - * @return an instance of random number generator. - * - * @throws IllegalArgumentException if {@code name} is an unknown random number generator - * - * @since 14 - */ - public static RandomGenerator byName(String name) throws IllegalArgumentException { - Objects.requireNonNull(name); - Map> rngs = getGeneratorMap(); - Provider provider = rngs.get(name.toUpperCase()); - if (provider == null) { - throw new IllegalArgumentException(name + " is an unknown random number generator"); - } - return provider.get(); - } - - private static Map> rngMap; - - private static Map> getGeneratorMap() { - if (rngMap == null) { - synchronized (Random.class) { - if (rngMap == null) { - rngMap = ServiceLoader - .load(RandomGenerator.class) - .stream() - .filter(p -> !p.type().isInterface()) - .collect(Collectors.toMap(p -> p.type().getSimpleName().toUpperCase(), - Function.identity())); - } - } - } - return rngMap; - } - - /** * Serializable fields for Random. * * @serialField seed long diff -r 56cbdc3ea079 -r 6a4be8bf8990 src/java.base/share/classes/java/util/random/RandomGenerator.java --- a/src/java.base/share/classes/java/util/random/RandomGenerator.java Fri Jul 26 15:37:05 2019 -0300 +++ b/src/java.base/share/classes/java/util/random/RandomGenerator.java Wed Aug 07 15:35:55 2019 -0300 @@ -26,11 +26,11 @@ package java.util.random; import java.math.BigInteger; +import java.util.Objects; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; -import java.util.stream.StreamSupport; /** * The {@link RandomGenerator} interface is designed to provide a common protocol for objects @@ -90,6 +90,122 @@ public interface RandomGenerator { /** + * Supported randpm number Algorithms. + */ + public enum Algorithm { + /** + * L32X64MixRandom algorithm + */ + L32X64MixRandom("L32X64MixRandom"), + /** + * L64X1024MixRandom algorithm + */ + L64X1024MixRandom("L64X1024MixRandom"), + /** + * L64X1024Random algorithm + */ + L64X1024Random("L64X1024Random"), + /** + * L64X128MixRandom algorithm + */ + L64X128MixRandom("L64X128MixRandom"), + /** + * L64X128Random algorithm + */ + L64X128Random("L64X128Random"), + /** + * L64X256MixRandom algorithm + */ + L64X256MixRandom("L64X256MixRandom"), + /** + * L64X256Random algorithm + */ + L64X256Random("L64X256Random"), + /** + * L128X256MixRandom algorithm + */ + L128X256MixRandom("L128X256MixRandom"), + /** + * MRG32k3a algorithm + */ + MRG32k3a("MRG32k3a"), + /** + * Xoroshiro128Plus algorithm + */ + Xoroshiro128Plus("Xoroshiro128Plus"), + /** + * Xoroshiro128StarStar algorithm + */ + Xoroshiro128StarStar("Xoroshiro128StarStar"), + /** + * Xoshiro256StarStar algorithm + */ + Xoshiro256StarStar("Xoshiro256StarStar"); + + private String name; + + Algorithm(String name) { + this.name = name; + } + + public String toString() { + return name; + } + } + + /** + * 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} + */ + public static RandomGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, RandomGenerator.class); + } + + /** + * Returns an instance of {@link RandomGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link RandomGenerator} + */ + public static RandomGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), RandomGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link RandomGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return Factory of {@link RandomGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, RandomGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link RandomGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return Factory of {@link RandomGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), RandomGenerator.class); + } + + /** * Returns an effectively unlimited stream of pseudorandomly chosen * {@code double} values. * @@ -672,6 +788,59 @@ * @since 14 */ public 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} + */ + public static StreamableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, StreamableGenerator.class); + } + + /** + * Returns an instance of {@link StreamableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link StreamableGenerator} + */ + public static StreamableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), StreamableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link StreamableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return Factory of {@link StreamableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, StreamableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link StreamableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return Factory of {@link StreamableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), StreamableGenerator.class); + } + /** * Returns an effectively unlimited stream of objects, each of * which implements the {@link RandomGenerator} interface. Ideally the @@ -748,6 +917,58 @@ public interface SplittableGenerator extends StreamableGenerator { /** + * Returns an instance of {@link SplittableGenerator} that utilizes the + * {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return An instance of {@link SplittableGenerator} + */ + public static SplittableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, SplittableGenerator.class); + } + + /** + * Returns an instance of {@link SplittableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link SplittableGenerator} + */ + public static SplittableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), SplittableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link SplittableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return Factory of {@link SplittableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, SplittableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link SplittableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return Factory of {@link SplittableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), SplittableGenerator.class); + } + + /** * Returns a new pseudorandom number generator, split off from * this one, that implements the {@link RandomGenerator} and {@link SplittableGenerator} * interfaces. @@ -910,6 +1131,59 @@ * @since 14 */ public 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} + */ + public static JumpableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, JumpableGenerator.class); + } + + /** + * Returns an instance of {@link JumpableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link JumpableGenerator} + */ + public static JumpableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), JumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link JumpableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return Factory of {@link JumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, JumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link JumpableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return Factory of {@link JumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), 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). @@ -1046,6 +1320,59 @@ * @since 14 */ public 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} + */ + public static LeapableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, LeapableGenerator.class); + } + + /** + * Returns an instance of {@link LeapableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link LeapableGenerator} + */ + public static LeapableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), LeapableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link LeapableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return Factory of {@link LeapableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, LeapableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link LeapableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return Factory of {@link LeapableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), 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). @@ -1155,6 +1482,59 @@ * @since 14 */ public 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} + */ + public static ArbitrarilyJumpableGenerator of(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.of(name, ArbitrarilyJumpableGenerator.class); + } + + /** + * Returns an instance of {@link ArbitrarilyJumpableGenerator} that utilizes the + * specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return An instance of {@link ArbitrarilyJumpableGenerator} + */ + public static ArbitrarilyJumpableGenerator of(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.of(algorithm.toString(), ArbitrarilyJumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link ArbitrarilyJumpableGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number generator algorithm + * + * @return Factory of {@link ArbitrarilyJumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(String name) { + Objects.requireNonNull(name); + return RandomGeneratorFactory.factoryOf(name, ArbitrarilyJumpableGenerator.class); + } + + /** + * Returns a {@link RandomGeneratorFactory} that can produce instances + * of {@link ArbitrarilyJumpableGenerator} that utilizes the specified {@code algorithm}. + * + * @param algorithm Random number generator algorithm + * + * @return Factory of {@link ArbitrarilyJumpableGenerator} + */ + public static RandomGeneratorFactory factoryOf(Algorithm algorithm) { + Objects.requireNonNull(algorithm); + return RandomGeneratorFactory.factoryOf(algorithm.toString(), 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). diff -r 56cbdc3ea079 -r 6a4be8bf8990 src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java Wed Aug 07 15:35:55 2019 -0300 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.random; + +import java.util.function.Function; +import java.util.Map; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.ServiceLoader.Provider; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * This is a factory class for generating random number generators of a specific + * catagory and algorithm. + */ +public class RandomGeneratorFactory { + /** + * Instance provider class of random number algorithm. + */ + private final Provider provider; + + /** + * Map of provider classes. + */ + private static Map> providerMap; + + /** + * Private constructor. + * + * @param provider Provider class to wrap. + */ + private RandomGeneratorFactory(Provider provider) { + this.provider = provider; + } + + /** + * Returns the provider map, lazily constructing map on first call. + * + * @return Map of provider classes. + */ + private static Map> getProviderMap() { + if (providerMap == null) { + synchronized (RandomGeneratorFactory.class) { + if (providerMap == null) { + providerMap = + ServiceLoader + .load(RandomGenerator.class) + .stream() + .filter(p -> !p.type().isInterface()) + .collect(Collectors.toMap(p -> p.type().getSimpleName().toUpperCase(), + Function.identity())); + } + } + } + return providerMap; + } + + private static Provider findProvider(String name, Class category) + throws IllegalArgumentException { + Map> pm = getProviderMap(); + Provider provider = pm.get(name.toUpperCase()); + if (provider == null || provider.type().isAssignableFrom(category)) { + throw new IllegalArgumentException(name + " is an unknown random number generator"); + } + return provider; + } + + /** + * Returns a {@link RandomGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number algorithm to use + * @param category Sub-interface of {@link RandomGenerator} to type check + * @param Sub-interface of {@link RandomGenerator} to produce + * @return An instance of {@link RandomGenerator} + * @throws IllegalArgumentException when either the name or category is null + */ + static T of(String name, Class category) + throws IllegalArgumentException { + @SuppressWarnings("unchecked") + T uncheckedRandomGenerator = (T)findProvider(name, category).get(); + return uncheckedRandomGenerator; + } + + /** + * Returns a {@link RandomGeneratorFactory} that will produce instances + * of {@link RandomGenerator} that utilizes the {@code name} algorithm. + * + * @param name Name of random number algorithm to use + * @param category Sub-interface of {@link RandomGenerator} to type check + * @param Sub-interface of {@link RandomGenerator} to produce + * @return Factory of {@link RandomGenerator} + * @throws IllegalArgumentException when either the name or category is null + */ + static RandomGeneratorFactory factoryOf(String name, Class category) + throws IllegalArgumentException { + @SuppressWarnings("unchecked") + Provider uncheckedProvider = (Provider)findProvider(name, category); + return new RandomGeneratorFactory(uncheckedProvider); + } + + /** + * Create an instance of {@link RandomGenerator}. + * + * @return Instance of {@link RandomGenerator}. + */ + public T create() { + return provider.get(); + } +} + +