Skip to content
Permalink
Browse files
Use JDK 8 Double.isFinite and Math.nextUp/Down
  • Loading branch information
aherbert committed Aug 13, 2021
1 parent 1980c1c commit d04082e8e1091fb3da0f892ad28576098ac20332
Show file tree
Hide file tree
Showing 11 changed files with 54 additions and 103 deletions.
@@ -54,8 +54,7 @@ public GaussianSampler(NormalizedGaussianSampler normalized,
throw new IllegalArgumentException(
"standard deviation is not strictly positive and finite: " + standardDeviation);
}
// To be replaced by JDK 1.8 Double.isFinite. This will detect NaN values.
if (!(Math.abs(mean) <= Double.MAX_VALUE)) {
if (!Double.isFinite(mean)) {
throw new IllegalArgumentException("mean is not finite: " + mean);
}
this.normalized = normalized;
@@ -301,7 +301,7 @@ public double getMinMean() {
*/
public double getMaxMean() {
if (isValidRange()) {
return Math.nextAfter(maxN + 1.0, -1);
return Math.nextDown(maxN + 1.0);
}
return 0;
}
@@ -1483,8 +1483,7 @@ private static void validateParameters(double alpha, double beta,
if (!(0 < gamma && gamma <= Double.MAX_VALUE)) {
throw new IllegalArgumentException("gamma is not strictly positive and finite: " + gamma);
}
// To be replaced by !Double.isFinite(double) from JDK 1.8.
if (!(Math.abs(delta) <= Double.MAX_VALUE)) {
if (!Double.isFinite(delta)) {
throw new IllegalArgumentException("delta is not finite: " + delta);
}
}
@@ -45,24 +45,13 @@ private Coordinates() {}
*/
static double[] requireFinite(double[] values, String message) {
for (final double value : values) {
if (!isFinite(value)) {
if (!Double.isFinite(value)) {
throw new IllegalArgumentException(message + " contains non-finite value: " + value);
}
}
return values;
}

/**
* Checks if the value is finite.
* To be replaced by {@code Double.isFinite(double)} when source requires Java 8.
*
* @param value the value
* @return true if finite
*/
private static boolean isFinite(double value) {
return Math.abs(value) <= Double.MAX_VALUE;
}

/**
* Check that the values is the specified length. This method is primarily for
* parameter validation in methods and constructors, for example:
@@ -443,7 +443,7 @@ public long nextLong() {
public void testNextNormSquaredAfterZeroIsValid() {
// The sampler explicitly handles length == 0 using recursion.
// Anything above zero should be valid.
final double normSq = Math.nextAfter(0.0, 1);
final double normSq = Math.nextUp(0.0);
// Map to the scaling factor
final double f = 1 / Math.sqrt(normSq);
// As long as this is finite positive then the sampler is valid
@@ -105,10 +105,10 @@ public void testInvalidOpenIntervalThrows() {
{-Double.MIN_VALUE, Double.MIN_VALUE},
// Same signs. Requires one double inside the range.
// Same exponent
{1.23, Math.nextAfter(1.23, Double.POSITIVE_INFINITY)},
{1.23, Math.nextAfter(1.23, Double.NEGATIVE_INFINITY)},
{1.23, Math.nextUp(1.23)},
{1.23, Math.nextUp(1.23)},
// Different exponent
{2.0, Math.nextAfter(2.0, Double.NEGATIVE_INFINITY)},
{2.0, Math.nextDown(2.0)},
}) {
final double low = interval[0];
final double high = interval[1];
@@ -145,8 +145,8 @@ public void testTinyOpenIntervalSample() {
for (final double expected : new double[] {
1.23, 2, 56787.7893, 3 * x, 2 * x, x
}) {
final double low = Math.nextAfter(expected, Double.POSITIVE_INFINITY);
final double high = Math.nextAfter(expected, Double.NEGATIVE_INFINITY);
final double low = Math.nextUp(expected);
final double high = Math.nextDown(expected);
Assert.assertEquals(expected, ContinuousUniformSampler.of(rng, low, high, true).sample(), 0.0);
Assert.assertEquals(expected, ContinuousUniformSampler.of(rng, high, low, true).sample(), 0.0);
Assert.assertEquals(-expected, ContinuousUniformSampler.of(rng, -low, -high, true).sample(), 0.0);
@@ -48,7 +48,7 @@ public void testProbabilityOfSuccessIsOneGeneratesZeroForSamples() {
public void testProbabilityOfSuccessUnderOneIsValid() {
// The sampler explicitly handles probabilityOfSuccess == 1 as an edge case.
// Anything under it should be valid for sampling from an ExponentialDistribution.
final double probabilityOfSuccess = Math.nextAfter(1, -1);
final double probabilityOfSuccess = Math.nextDown(1);
// Map to the mean
final double exponentialMean = 1.0 / (-Math.log1p(-probabilityOfSuccess));
// As long as this is finite positive then the sampler is valid
@@ -51,7 +51,7 @@ public void testConstructorThrowsWithMeanLargerThanUpperBound() {
public void testConstructorThrowsWithMeanBelow1() {
final RestorableUniformRandomProvider rng =
RandomSource.SPLIT_MIX_64.create(0L);
final double mean = Math.nextAfter(1, -1);
final double mean = Math.nextDown(1);
LargeMeanPoissonSampler.of(rng, mean);
}

@@ -467,7 +467,7 @@ public void testCreateBinomialDistributionWithLargestTrialsAndSmallestProbabilit
// Validate set-up
Assert.assertEquals("Invalid test set-up for p(0)", Double.MIN_VALUE, getBinomialP0(trials, p), 0);

// Search for larger p until Math.nextAfter(p, 1) produces 0
// Search for larger p until Math.nextUp(p) produces 0
double upper = p * 2;
Assert.assertEquals("Invalid test set-up for p(0)", 0, getBinomialP0(trials, upper), 0);

@@ -484,7 +484,7 @@ public void testCreateBinomialDistributionWithLargestTrialsAndSmallestProbabilit

// Re-validate
Assert.assertEquals("Invalid test set-up for p(0)", Double.MIN_VALUE, getBinomialP0(trials, p), 0);
Assert.assertEquals("Invalid test set-up for p(0)", 0, getBinomialP0(trials, Math.nextAfter(p, 1)), 0);
Assert.assertEquals("Invalid test set-up for p(0)", 0, getBinomialP0(trials, Math.nextUp(p)), 0);

final DiscreteSampler sampler = MarsagliaTsangWangDiscreteSampler.Binomial.of(rng, trials, p);
// This will throw if the table does not sum to 2^30
@@ -75,7 +75,7 @@ public void testConstructorWhenMaxEqualsMin() {
final PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
Assert.assertTrue(cache.isValidRange());
Assert.assertEquals(min, cache.getMinMean(), 0);
Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
Assert.assertEquals(Math.nextDown(Math.floor(max) + 1),
cache.getMaxMean(), 0);
}

@@ -91,7 +91,7 @@ public void testConstructorWhenMaxAboveMin() {
final PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
Assert.assertTrue(cache.isValidRange());
Assert.assertEquals(min, cache.getMinMean(), 0);
Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
Assert.assertEquals(Math.nextDown(Math.floor(max) + 1),
cache.getMaxMean(), 0);
}

@@ -101,7 +101,7 @@ public void testConstructorWhenMaxAboveMin() {
@Test(expected = IllegalArgumentException.class)
public void testConstructorThrowsWhenMaxIsLessThanMin() {
final double min = PoissonSampler.PIVOT;
final double max = Math.nextAfter(min, -1);
final double max = Math.nextDown(min);
createPoissonSamplerCache(min, max);
}

@@ -116,7 +116,7 @@ public void testConstructorWhenMinBelow0() {
final PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
Assert.assertTrue(cache.isValidRange());
Assert.assertEquals(PoissonSampler.PIVOT, cache.getMinMean(), 0);
Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
Assert.assertEquals(Math.nextDown(Math.floor(max) + 1),
cache.getMaxMean(), 0);
}

@@ -161,7 +161,7 @@ public void testWithRangeConstructorWhenMaxEqualsMin() {
final PoissonSamplerCache cache = createPoissonSamplerCache().withRange(min, max);
Assert.assertTrue(cache.isValidRange());
Assert.assertEquals(min, cache.getMinMean(), 0);
Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
Assert.assertEquals(Math.nextDown(Math.floor(max) + 1),
cache.getMaxMean(), 0);
}

@@ -177,7 +177,7 @@ public void testWithRangeConstructorWhenMaxAboveMin() {
final PoissonSamplerCache cache = createPoissonSamplerCache().withRange(min, max);
Assert.assertTrue(cache.isValidRange());
Assert.assertEquals(min, cache.getMinMean(), 0);
Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
Assert.assertEquals(Math.nextDown(Math.floor(max) + 1),
cache.getMaxMean(), 0);
}

@@ -187,7 +187,7 @@ public void testWithRangeConstructorWhenMaxAboveMin() {
@Test(expected = IllegalArgumentException.class)
public void testWithRangeConstructorThrowsWhenMaxIsLessThanMin() {
final double min = PoissonSampler.PIVOT;
final double max = Math.nextAfter(min, -1);
final double max = Math.nextDown(min);
createPoissonSamplerCache().withRange(min, max);
}

@@ -202,7 +202,7 @@ public void testWithRangeConstructorWhenMinBelow0() {
final PoissonSamplerCache cache = createPoissonSamplerCache().withRange(min, max);
Assert.assertTrue(cache.isValidRange());
Assert.assertEquals(PoissonSampler.PIVOT, cache.getMinMean(), 0);
Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
Assert.assertEquals(Math.nextDown(Math.floor(max) + 1),
cache.getMaxMean(), 0);
}

@@ -216,7 +216,7 @@ public void testWithRangeConstructorWhenCacheHasNoCapcity() {
final PoissonSamplerCache cache = createPoissonSamplerCache(0, 0).withRange(min, max);
Assert.assertTrue(cache.isValidRange());
Assert.assertEquals(min, cache.getMinMean(), 0);
Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
Assert.assertEquals(Math.nextDown(Math.floor(max) + 1),
cache.getMaxMean(), 0);
}

0 comments on commit d04082e

Please sign in to comment.