[ https://issues.apache.org/jira/browse/RNG-176?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17530036#comment-17530036 ]
Alex Herbert commented on RNG-176: ---------------------------------- {quote}duplicate non-trivial functionality {quote} Yes. However note that the methods to generate a float in a range are not in the sampling module. This only has samples for int, long and double in a range. The interface methods for ranges would be non-optimised. For a single generation this lack of optimisation will be a benefit over having to create a sampler class to obtain a single number. For the streams then the lack of optimisation would be a negative. In the case of low frequency generation of random numbers in a range then the following is my preferred method: {code:java} double lo = 1.33; double hi = 4.66; // No RNG available double d = ThreadLocalRandom.current().nextDouble(lo, hi); UniformRandomProvider rng; double d = lo + rng.nextDouble() * (hi - lo); {code} The nextDouble(lo, hi) method effectively does exactly as specified but then adds a check that the upper bound is exclusive, which can occur due to rounding: {noformat} jshell> double lo = 3.5 lo ==> 3.5 jshell> double hi = 4.5 hi ==> 4.5 jshell> lo + Math.nextDown(1.0) * (hi - lo) $14 ==> 4.5 {noformat} I am finding that I am increasingly using the JDKs streaming methods for quick generation of random numbers, typically into arrays of test random data. For heavy generation in simulations I would use samplers, typically created once then shared out to threads via an Executor and a Jumpable RNG. I do not really see any harm in adding the methods. It provides a convenience for consumers of the interface and brings in parity with the RandomGenerator interface. This is the type of code I think the convenience methods are used for: {code:java} double[] data = new SplittableRandom().doubles(50, lo, hi).toArray(); // Current UniformRandomProvider rng = ...; double[] data = DoubleStream.generate( ContinuousUniformSampler.of(rng, lo, hi)::sample) .limit(50).toArray(); // New double[] data = rng.doubles(50, lo, hi).toArray(); {code} So here we are saving not many characters of typing but it does not require inclusion of the sampling module, or even knowledge of how to do this with the DoubleStream. > Enhance the UniformRandomProvider interface with extra methods and default > implementations > ------------------------------------------------------------------------------------------ > > Key: RNG-176 > URL: https://issues.apache.org/jira/browse/RNG-176 > Project: Commons RNG > Issue Type: New Feature > Affects Versions: 1.4 > Reporter: Alex Herbert > Assignee: Alex Herbert > Priority: Major > > JDK 17 introduced the {{RandomGenerator}} interface with the following > methods: > {code:java} > DoubleStream doubles(); > DoubleStream doubles(double randomNumberOrigin, double randomNumberBound); > DoubleStream doubles(long streamSize); > DoubleStream doubles(long streamSize, double randomNumberOrigin, > double randomNumberBound); > IntStream ints(); > IntStream ints(int randomNumberOrigin, int randomNumberBound); > IntStream ints(long streamSize); > IntStream ints(long streamSize, int randomNumberOrigin, > int randomNumberBound); > LongStream longs(); > LongStream longs(long randomNumberOrigin, long randomNumberBound); > LongStream longs(long streamSize); > LongStream longs(long streamSize, long randomNumberOrigin, > long randomNumberBound); > boolean nextBoolean(); > void nextBytes(byte[] bytes); > float nextFloat(); > float nextFloat(float bound); > float nextFloat(float origin, float bound); > double nextDouble(); > double nextDouble(double bound); > double nextDouble(double origin, double bound); > int nextInt(); > int nextInt(int bound); > int nextInt(int origin, int bound); > long nextLong(); > long nextLong(long bound); > long nextLong(long origin, long bound); > double nextGaussian(); > double nextGaussian(double mean, double stddev); > double nextExponential(); > {code} > The only method that is *non-default* is {{{}nextLong{}}}. This allows a new > generator to be simply implemented by providing the source of randomness as > 64-bit longs. > The {{UniformRandomProvider}} interface can be expanded to include these > generation methods. Using Java 8 default interface methods will not require > any changes to generators currently implementing the interface. > I propose to: > # Add the new methods for streams and numbers in a range. > # Add default implementations of the current API. These can be extracted > from the o.a.c.rng.core.BaseProvider implementations. > # Remove the implementations in o.a.c.rng.core.BaseProvider. This change > would be binary compatible. > The base classes in commons core for 32-bit and 64-bit sources of randomness, > IntProvider and LongProvider, can be updated suitably to only override the > default interface methods where they can be more efficiently implemented > given the source of randomness. This applies to: > ||Source||Update||Details|| > |int|nextBytes|Use nextInt() for the source of bytes| > | |nextBoolean|Use a cached int for the randomness| > | |nextInt|Directly supply the int rather than using 32-bits from nextLong()| > | |nextDouble|Optimise the bits used from two ints for the 53-bits required > for the double.| > |long|nextInt; nextBoolean|Use a cached long for the randomness| > h3. Note 1 > The UniformRandomProvider also has the method: > {code:java} > void nextBytes(byte[] bytes, > int start, > int len); > {code} > This can also have a default implementation using the output from nextLong(). > h3. Note 2 > The methods to generate an exponential and Gaussian are already implemented > in the {{commons-rng-sampling}} module. > java.util.Random has a nextGaussian() method and so this method appears to be > for backward compatibility with legacy Java code. The method is implemented > using a modified Ziggurat sampler which uses an exponential sampler for the > long tail. The API has thus exposed the exponential sampling method that is > used internally in the nextGaussian implementation. > With no backward compatibility requirements the Commons RNG interface can > avoid the distribution sampling methods. Users should select an appropriate > sampler from the sampling module. > -- This message was sent by Atlassian Jira (v8.20.7#820007)