|
CSR :
|
|
|
Relates :
|
|
|
Relates :
|
|
|
Relates :
|
|
|
Relates :
|
Summary
-------
This proposal introduces new common interface, `RandomGenerator`, that would
allow consumers of random numbers to easily migrate between random number
generation services or adapt to new random number generation algorithms as they
are made available. This proposal also introduces a class,
`RandomGeneratorFactory`, that can be used to locate and select random number
generation algorithms as they become available. `RandomGenerator` and
`RandomGeneratorFactory` are implementation outcomes from
[JEP 356 Enhanced Pseudo-Random Number Generators](https://openjdk.java.net/jeps/356).
Problem
-------
- Existing random number generators (
`java.util.Random`,
`java.security.SecureRandom`,
`java.util.concurrent.ThreadLocalRandom`,
`java.util.SplittableRandom`
) require significant effort to adopt if the consumer wishes to change
generators (algorithms).
- The types of services supported by existing random number generators is
inconsistent.
- Adoption of new random number generation algorithms has a high order of
complexity.
Solution
--------
[Note: This proposal avoids the use of pseudo-random with the intent of future
support for stochastic hardware based (noise) random number generation.]
We propose the introduction of a common `RandomGenerator` interface to be
implemented by all random generators used in Java. This common interface will
allow easier transition between various implementations of a random number
generator.
`RandomGenerator` provides a comprehensive set of methods available from
all random number generators; `nextInt`, `nextLong`, `nextFloat`, `nextDouble`,
``nextBoolean` and `nextBytes`. As well as bounded versions of the *next*
methods, `RandomGenerator` provides methods for generating streams of
ints, longs and doubles.
To locate and construct application specific number generators, we propose to
introduce the `RandomGeneratorFactory<T>` class. `RandomGeneratorFactory<T>`
uses the `ServiceLoader.Provider` mechanism to locate all implementations of
`RandomGenerator`.
`RandomGeneratorFactory<T>` methods, such as `all()`, return
`java.util.stream.Stream` of `RandomGeneratorFactory` to provide a query
mechanism for locating relevant generators. For example, if the developer wants
a sorted list of all available RandomGenerators then they can print such a list
as follows;
RandomGenerator.all()
.map(RandomGeneratorFactory::name)
.sorted()
.forEach(System.out::println);
The `RandomGeneratorFactory<T>` class provides several query and predicate
methods for filtering candidate RandomGenerators. For example, if the developer
needs a generator closest to providing 128 state bits (assuming that a large
number of state bits is more expensive) a query might look like;
RandomGeneratorFactory<RandomGenerator> factory =
RandomGenerator.all()
.filter(f -> 128 <= g.stateBits())
.sorted((f, g) -> Integer.compare(g.stateBits(), f.stateBits()))
.findFirst()
.orElseThrow();
Once a `RandomGeneratorFactory<T>` is chosen, a `RandomGenerator` can then be
instantiated and utilized;
RandomGenerator rng = factory.create();
System.out.println(rng.nextDouble());
If the name of the `RandomGenerator` is known, then the
`RandomGenerator.factoryOf` short-cut method can be used;
RandomGeneratorFactory<RandomGenerator> factory = RandomGenerator.factoryOf("Random");
RandomGenerator rng = factory.create();
System.out.println(rng.nextDouble());
As a further shortcut a new instance of RandomGenerator can be constructed
directly using `RandomGenerator.of`;
RandomGenerator rng = RandomGenerator.of("Random");
System.out.println(rng.nextDouble());
It is generally suggested that developers not use `RandomGenerator.of` by *name* due
to future depreciation and the potential for better `RandomGenerators`. It is
better to use selection queries.
It is proposed that the four existing random number generators will be
implementations of `RandomGenerator`; `java.util.Random`,
`java.security.SecureRandom`, `java.util.concurrent.ThreadLocalRandom` and
`java.util.SplittableRandom`.
Note that `java.util.concurrent.ThreadLocalRandom` will not discoverable via
`RandomGeneratorFactory<T>` due to its lack of a no-arg constructor (
`ThreadLocalRandom.current()` is used instead), but in all other respects
`java.util.concurrent.ThreadLocalRandom` implements `RandomGenerator`.
Finally, it is proposed that five specialized sub-interfaces of
`RandomGenerator` be introduced; `JumpableRandomGenerator`,
`LeapableRandomGenerator`, `ArbitrariliyJumpableRandomGenerator`,
`StreamableRandomGenerator` and `SplittableRandomGenerator`. These
sub-interfaces each provide a small set of specialized methods for handling
specific needs. (see enclosed specdiff).
Specification
-------------
(see enclosed specdiff)
|