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
commit d4950ef16cc79c86c0ad48129009f6f0bacbeadf Author: aherbert <aherb...@apache.org> AuthorDate: Tue Mar 5 11:22:12 2019 +0000 RNG-79: NumberFactoryTest floating-point precision uses commons-math3 --- commons-rng-core/pom.xml | 7 +++ .../commons/rng/core/util/NumberFactoryTest.java | 60 +++++++++++++++++----- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/commons-rng-core/pom.xml b/commons-rng-core/pom.xml index ceeaf48..e027ec6 100644 --- a/commons-rng-core/pom.xml +++ b/commons-rng-core/pom.xml @@ -53,6 +53,13 @@ <artifactId>commons-rng-client-api</artifactId> <version>1.3-SNAPSHOT</version> </dependency> + <dependency> + <!-- For testing floating point precision --> + <groupId>org.apache.commons</groupId> + <artifactId>commons-math3</artifactId> + <version>3.6.1</version> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/commons-rng-core/src/test/java/org/apache/commons/rng/core/util/NumberFactoryTest.java b/commons-rng-core/src/test/java/org/apache/commons/rng/core/util/NumberFactoryTest.java index 6fb909e..9bbcc4d 100644 --- a/commons-rng-core/src/test/java/org/apache/commons/rng/core/util/NumberFactoryTest.java +++ b/commons-rng-core/src/test/java/org/apache/commons/rng/core/util/NumberFactoryTest.java @@ -16,6 +16,7 @@ */ package org.apache.commons.rng.core.util; +import org.apache.commons.math3.util.Precision; import org.junit.Assert; import org.junit.Test; @@ -141,16 +142,18 @@ public class NumberFactoryTest { } } + /** + * Test different methods for generation of a {@code float} from a {@code int}. The output + * value should be in the range between 0 and 1. + */ @Test - public void testFloatGeneration() { + public void testFloatGenerationMethods() { final int allBits = 0xffffffff; // Not capable of generating 1. Set the delta with 1 or 2 ULP of 1. - final float deltaUlp2 = 1f - Math.nextAfter(Math.nextAfter(1f, -1), -1); - final float deltaUlp1 = 1f - Math.nextAfter(1f, -1); - Assert.assertEquals(1, (allBits >>> 9) * 0x1.0p-23f, deltaUlp2); - Assert.assertEquals(1, (allBits >>> 8) * 0x1.0p-24f, deltaUlp1); - Assert.assertEquals(1, Float.intBitsToFloat(0x7f << 23 | allBits >>> 9) - 1.0f, deltaUlp2); + assertCloseToNotAbove1((allBits >>> 9) * 0x1.0p-23f, 2); + assertCloseToNotAbove1((allBits >>> 8) * 0x1.0p-24f, 1); + assertCloseToNotAbove1(Float.intBitsToFloat(0x7f << 23 | allBits >>> 9) - 1.0f, 2); final int noBits = 0; Assert.assertEquals(0, (noBits >>> 9) * 0x1.0p-23f, 0); @@ -158,20 +161,53 @@ public class NumberFactoryTest { Assert.assertEquals(0, Float.intBitsToFloat(0x7f << 23 | noBits >>> 9) - 1.0f, 0); } + /** + * Test different methods for generation of a {@code double} from a {@code long}. The output + * value should be in the range between 0 and 1. + */ @Test - public void testDoubleGeneration() { + public void testDoubleGenerationMethods() { final long allBits = 0xffffffffffffffffL; // Not capable of generating 1. Set the delta with 1 or 2 ULP of 1. - final double deltaUlp2 = 1 - Math.nextAfter(Math.nextAfter(1, -1), -1); - final double deltaUlp1 = 1 - Math.nextAfter(1, -1); - Assert.assertEquals(1, (allBits >>> 12) * 0x1.0p-52d, deltaUlp2); - Assert.assertEquals(1, (allBits >>> 11) * 0x1.0p-53d, deltaUlp1); - Assert.assertEquals(1, Double.longBitsToDouble(0x3ffL << 52 | allBits >>> 12) - 1.0, deltaUlp2); + assertCloseToNotAbove1((allBits >>> 12) * 0x1.0p-52d, 2); + assertCloseToNotAbove1((allBits >>> 11) * 0x1.0p-53d, 1); + assertCloseToNotAbove1(Double.longBitsToDouble(0x3ffL << 52 | allBits >>> 12) - 1.0, 2); final long noBits = 0; Assert.assertEquals(0, (noBits >>> 12) * 0x1.0p-52d, 0); Assert.assertEquals(0, (noBits >>> 11) * 0x1.0p-53d, 0); Assert.assertEquals(0, Double.longBitsToDouble(0x3ffL << 52 | noBits >>> 12) - 1.0, 0); } + + + /** + * Assert that the value is close to but <strong>not above</strong> 1. This is used to test + * the output from methods that produce a {@code float} value that must be in the range + * between 0 and 1. + * + * @param value the value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point values between x and y. + * @see Precision#equals(float, float, int) + */ + private static void assertCloseToNotAbove1(float value, int maxUlps) { + Assert.assertTrue("Not <= 1.0f", value <= 1.0f); + Assert.assertTrue("Not equal to 1.0f within units of least precision: " + maxUlps, + Precision.equals(1.0f, value, maxUlps)); + } + + /** + * Assert that the value is close to but <strong>not above</strong> 1. This is used to test + * the output from methods that produce a {@code double} value that must be in the range + * between 0 and 1. + * + * @param value the value + * @param maxUlps {@code (maxUlps - 1)} is the number of floating point values between x and y. + * @see Precision#equals(double, double, int) + */ + private static void assertCloseToNotAbove1(double value, int maxUlps) { + Assert.assertTrue("Not <= 1.0", value <= 1.0); + Assert.assertTrue("Not equal to 1.0 within units of least precision: " + maxUlps, + Precision.equals(1.0, value, maxUlps)); + } }