[
https://issues.apache.org/jira/browse/RNG-190?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18058709#comment-18058709
]
Alex Herbert commented on RNG-190:
----------------------------------
I have performed further testing across JDKs 8, 11, 17, 21 on a few machines.
The most stable in performance is the multiplication method. Use of this method
is very similar to the default implementation of nextDouble() in the
UniformRandomProvider interface. Thus using this method allows the
ContinuousUniformSampler to output values from the rng within 1 dyadic rational
(2^-53) of the standard double output. There are only 2^52 possible values
which is the compromise for the performance gain over the rejection method used
in releases 1.4 - 1.6.
> ContinuousUniformSampler to specialize generation of the open interval (0, 1)
> -----------------------------------------------------------------------------
>
> Key: RNG-190
> URL: https://issues.apache.org/jira/browse/RNG-190
> Project: Commons RNG
> Issue Type: Improvement
> Components: sampling
> Affects Versions: 1.6
> Reporter: Alex Herbert
> Priority: Minor
>
> The ContinuousUniformSampler can generate double values in the open interval
> (lo, hi) using a constructor flag:
> {code:java}
> UniformRandomProvider rng = ...
> double lo = ...
> double hi = ...
> boolean excludeBounds = true;
> double x = ContinuousUniformSampler.of(rng, lo, hi, excludeBounds)
> .sample();
> {code}
> The bounds are excluded using a rejection algorithm. This is used as rounding
> during floating-point operations to map the underlying double value in [0, 1)
> to (lo, hi) can generate values at the bounds.
> In the case where the interval is (0, 1) then it is possible to generate the
> random value with a branchless operation that is more performant. Examples
> are setting the lowest 1-bit using various methods:
> {code:java}
> // Using bits to double
> Double.longBitsToDouble(
> (source.nextLong() >>> 12) | 0x3ff0000000000001L) - 1.0;
> // Using float addition to force a lowest 1-bit
> ((source.nextLong() >>> 12) + 0.5) * 0x1.0p-52d
> // Adding a bit before conversion to float
> ((source.nextLong() >>> 11) | 1) * 0x1.0p-53d
> {code}
> Note that the output would be limited to 2^52 evenly spaced rationals in (0,
> 1). Rejection algorithms would output 2^53 - 1 rationals. In practice this
> difference would not be noticeable.
> Provision of a guarantee of a fast non-zero double would be a benefit to
> certain applications such as an inverse probability distribution defined on
> the open interval.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)