This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-rng.git
The following commit(s) were added to refs/heads/master by this push: new 2cfea0b RNG-145: Correct ContinuousUniformSampler support of an open bound 2cfea0b is described below commit 2cfea0baac98f65ce2145b91575847a2d106028e Author: Alex Herbert <aherb...@apache.org> AuthorDate: Mon Jun 14 18:49:51 2021 +0100 RNG-145: Correct ContinuousUniformSampler support of an open bound Corrects the test to check the interval is open. Updates the sampler to exclude samples from the bound. --- .../distribution/ContinuousUniformSampler.java | 32 +++++++--------------- .../rng/sampling/distribution/InternalUtils.java | 26 ------------------ .../distribution/ContinuousUniformSamplerTest.java | 2 +- 3 files changed, 11 insertions(+), 49 deletions(-) diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSampler.java index 6a8a9a9..e255062 100644 --- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSampler.java +++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSampler.java @@ -49,8 +49,15 @@ public class ContinuousUniformSampler } @Override - double getU() { - return InternalUtils.nextDouble01(getRng()); + public double sample() { + final double x = super.sample(); + // Due to rounding using a variate u in the open interval (0,1) with the original + // algorithm may generate a value at the bound. Thus the bound is explicitly tested + // and the sample repeated if necessary. + if (x == getHi() || x == getLo()) { + return sample(); + } + return x; } @Override @@ -76,21 +83,11 @@ public class ContinuousUniformSampler /** {@inheritDoc} */ @Override public double sample() { - final double u = getU(); + final double u = rng.nextDouble(); return u * hi + (1 - u) * lo; } /** - * Gets the uniform deviate {@code u} the interval 0 to 1. - * The interval may be open or closed depending on the implementation. - * - * @return u - */ - double getU() { - return rng.nextDouble(); - } - - /** * Gets the lower bound. This is deliberately scoped as package private. * * @return the lower bound @@ -108,15 +105,6 @@ public class ContinuousUniformSampler return hi; } - /** - * Gets the RNG. This is deliberately scoped as package private. - * - * @return the rng - */ - UniformRandomProvider getRng() { - return rng; - } - /** {@inheritDoc} */ @Override public String toString() { diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/InternalUtils.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/InternalUtils.java index 02eed2f..af4c049 100644 --- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/InternalUtils.java +++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/InternalUtils.java @@ -38,13 +38,6 @@ final class InternalUtils { // Class is package-private on purpose; do not make /** The first array index with a non-zero log factorial. */ private static final int BEGIN_LOG_FACTORIALS = 2; - /** - * The multiplier to convert the least significant 53-bits of a {@code long} to a {@code double}. - * See {@link #makeDouble(long)} and {@link #makeDouble(int, int)}. - * - * <p>This is equivalent to 1.0 / (1L << 53). - */ - private static final double DOUBLE_MULTIPLIER = 0x1.0p-53d; /** Utility class. */ private InternalUtils() {} @@ -126,25 +119,6 @@ final class InternalUtils { // Class is package-private on purpose; do not make } /** - * Gets a uniform random variable in the open interval {@code (0, 1)}. - * - * @param rng Generator of uniformly distributed random numbers. - * @return u - */ - static double nextDouble01(UniformRandomProvider rng) { - // See o.a.c.rng.core.util.NumberFactory.createDouble(long) - // Require the least significant 53-bits so shift the higher bits across - final long x = rng.nextLong() >>> 11; - if (x == 0) { - // Recursive call will create a stack overflow if the random generator - // is broken (always returns 0-bits). The alternative would be an infinite loop. - return nextDouble01(rng); - } - // Generate a double in the 2^53-1 dyadic rationals in (0, 1). - return x * DOUBLE_MULTIPLIER; - } - - /** * Class for computing the natural logarithm of the factorial of {@code n}. * It allows to allocate a cache of precomputed values. * In case of cache miss, computation is performed by a call to diff --git a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSamplerTest.java b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSamplerTest.java index 74f86ea..d937a98 100644 --- a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSamplerTest.java +++ b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousUniformSamplerTest.java @@ -84,7 +84,7 @@ public class ContinuousUniformSamplerTest { // Test the sampler excludes the end points for (int i = 0; i < 10; i++) { final double value = sampler.sample(); - Assert.assertTrue("Value not in range", value >= low && value <= high); + Assert.assertTrue("Value not in range: " + value, value > low && value < high); } }