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-statistics.git
commit a7153c2343a70665ca8b45dbbc45f66be0bac7be Author: Alex Herbert <aherb...@apache.org> AuthorDate: Mon Nov 21 16:57:12 2022 +0000 Convert to parameterized tests --- .../distribution/GammaDistributionTest.java | 264 +++++++++------------ 1 file changed, 116 insertions(+), 148 deletions(-) diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java index 7c5ae4b..3d9c73c 100644 --- a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java +++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/GammaDistributionTest.java @@ -25,9 +25,9 @@ import java.util.stream.Stream; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import org.apache.commons.numbers.gamma.LanczosApproximation; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; /** @@ -80,114 +80,111 @@ class GammaDistributionTest extends BaseContinuousDistributionTest { ); } - @Test - void testAdditionalCumulativeProbability() { - checkCumulativeProbability(-1.000, 4.0, 2.0, 0.0); - checkCumulativeProbability(15.501, 4.0, 2.0, 0.94989465156755404); - checkCumulativeProbability(0.504, 4.0, 1.0, 0.0018026739713985257); - checkCumulativeProbability(10.011, 1.0, 2.0, 0.99329900998454213); - checkCumulativeProbability(5.000, 2.0, 2.0, 0.71270250481635422); - } - - private void checkCumulativeProbability(double x, double a, double b, double expected) { - final GammaDistribution distribution = GammaDistribution.of(a, b); - final double actual = distribution.cumulativeProbability(x); + @ParameterizedTest + @CsvSource({ + "4.0, 2.0, -1.0, 0.0", + "4.0, 2.0, 15.501, 0.94989465156755404", + "4.0, 1.0, 0.504, 0.0018026739713985257", + "1.0, 2.0, 10.011, 0.99329900998454213", + "2.0, 2.0, 5.000, 0.71270250481635422", + }) + void testAdditionalCumulativeProbability(double a, double b, double x, double expected) { + final GammaDistribution dist = GammaDistribution.of(a, b); + final double actual = dist.cumulativeProbability(x); Assertions.assertEquals(expected, actual, expected * 1e-15, () -> "probability for " + x); } - @Test - void testAdditionalInverseCumulativeProbability() { - checkInverseCumulativeProbability(15.501, 4.0, 2.0, 0.94989465156755404); - checkInverseCumulativeProbability(0.504, 4.0, 1.0, 0.0018026739713985257); - checkInverseCumulativeProbability(10.011, 1.0, 2.0, 0.99329900998454213); - checkInverseCumulativeProbability(5.000, 2.0, 2.0, 0.71270250481635422); - } - - private void checkInverseCumulativeProbability(double expected, double a, double b, double p) { - final GammaDistribution distribution = GammaDistribution.of(a, b); - final double actual = distribution.inverseCumulativeProbability(p); - Assertions.assertEquals(expected, actual, expected * 1e-10, () -> "critical value for " + p); + @ParameterizedTest + @CsvSource({ + "4.0, 2.0, 0.94989465156755404, 15.501", + "4.0, 1.0, 0.0018026739713985257, 0.504", + "1.0, 2.0, 0.99329900998454213, 10.011", + "2.0, 2.0, 0.71270250481635422, 5.0", + }) + void testAdditionalInverseCumulativeProbability(double a, double b, double p, double expected) { + final GammaDistribution dist = GammaDistribution.of(a, b); + final double actual = dist.inverseCumulativeProbability(p); + Assertions.assertEquals(expected, actual, expected * 5e-15, () -> "critical value for " + p); } - @Test - void testAdditionalDensity() { - final double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5}; - // R2.5: print(dgamma(x, shape=1, rate=1), digits=10) - checkDensity(1, 1, x, new double[]{0.000000000000, 0.999999000001, 0.606530659713, 0.367879441171, 0.135335283237, 0.006737946999}); - // R2.5: print(dgamma(x, shape=2, rate=1), digits=10) - checkDensity(2, 1, x, new double[]{0.000000000000, 0.000000999999, 0.303265329856, 0.367879441171, 0.270670566473, 0.033689734995}); - // R2.5: print(dgamma(x, shape=4, rate=1), digits=10) - checkDensity(4, 1, x, new double[]{0.000000000e+00, 1.666665000e-19, 1.263605541e-02, 6.131324020e-02, 1.804470443e-01, 1.403738958e-01}); - // R2.5: print(dgamma(x, shape=4, rate=10), digits=10) - checkDensity(4, 10, x, new double[]{0.000000000e+00, 1.666650000e-15, 1.403738958e+00, 7.566654960e-02, 2.748204830e-05, 4.018228850e-17}); - // R2.5: print(dgamma(x, shape=.1, rate=10), digits=10) - checkDensity(0.1, 10, x, new double[]{0.000000000e+00, 3.323953832e+04, 1.663849010e-03, 6.007786726e-06, 1.461647647e-10, 5.996008322e-24}); - // R2.5: print(dgamma(x, shape=.1, rate=20), digits=10) - checkDensity(0.1, 20, x, new double[]{0.000000000e+00, 3.562489883e+04, 1.201557345e-05, 2.923295295e-10, 3.228910843e-19, 1.239484589e-45}); - // R2.5: print(dgamma(x, shape=.1, rate=4), digits=10) - checkDensity(0.1, 4, x, new double[]{0.000000000e+00, 3.032938388e+04, 3.049322494e-02, 2.211502311e-03, 2.170613371e-05, 5.846590589e-11}); - // R2.5: print(dgamma(x, shape=.1, rate=1), digits=10) - checkDensity(0.1, 1, x, new double[]{0.000000000e+00, 2.640334143e+04, 1.189704437e-01, 3.866916944e-02, 7.623306235e-03, 1.663849010e-04}); - // To force overflow condition - // R2.5: print(dgamma(x, shape=1000, rate=100), digits=10) - checkDensity(1000, 100, x, new double[]{0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 3.304830256e-84}); + @ParameterizedTest + @MethodSource + void testAdditionalDensity(double alpha, double rate, double[] x, double[] expected) { + final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate); + testDensity(dist, x, expected, DoubleTolerances.relative(1e-9)); } - /** - * Test a shape far below 1. Support for very small shape parameters - * was fixed in STATISTICS-39. - */ - @Test - void testShapeBelow1() { - // R2.5: print(dgamma(x, shape=0.05, rate=1), digits=20) - final double[] x = new double[]{1e-100, 1e-10, 1e-5, 0.1}; - checkDensity(0.05, 1, x, new double[] { - 5.1360843263583843333e+93, 1.6241724724359893799e+08, - 2.8882035841935007738e+03, 4.1419294512123655538e-01 - }); + static Stream<Arguments> testAdditionalDensity() { + final double[] x = {-0.1, 1e-6, 0.5, 1, 2, 5}; + final double[] x1 = new double[]{1e-100, 1e-10, 1e-5, 0.1}; + return Stream.of( + // R2.5: print(dgamma((x, shape=1, rate=1), digits=10) + Arguments.of(1, 1, x, new double[]{0.000000000000, 0.999999000001, 0.606530659713, 0.367879441171, 0.135335283237, 0.006737946999}), + // R2.5: print(dgamma((x, shape=2, rate=1), digits=10) + Arguments.of(2, 1, x, new double[]{0.000000000000, 0.000000999999, 0.303265329856, 0.367879441171, 0.270670566473, 0.033689734995}), + // R2.5: print(dgamma((x, shape=4, rate=1), digits=10) + Arguments.of(4, 1, x, new double[]{0.000000000e+00, 1.666665000e-19, 1.263605541e-02, 6.131324020e-02, 1.804470443e-01, 1.403738958e-01}), + // R2.5: print(dgamma((x, shape=4, rate=10), digits=10) + Arguments.of(4, 10, x, new double[]{0.000000000e+00, 1.666650000e-15, 1.403738958e+00, 7.566654960e-02, 2.748204830e-05, 4.018228850e-17}), + // R2.5: print(dgamma((x, shape=.1, rate=10), digits=10) + Arguments.of(0.1, 10, x, new double[]{0.000000000e+00, 3.323953832e+04, 1.663849010e-03, 6.007786726e-06, 1.461647647e-10, 5.996008322e-24}), + // R2.5: print(dgamma((x, shape=.1, rate=20), digits=10) + Arguments.of(0.1, 20, x, new double[]{0.000000000e+00, 3.562489883e+04, 1.201557345e-05, 2.923295295e-10, 3.228910843e-19, 1.239484589e-45}), + // R2.5: print(dgamma((x, shape=.1, rate=4), digits=10) + Arguments.of(0.1, 4, x, new double[]{0.000000000e+00, 3.032938388e+04, 3.049322494e-02, 2.211502311e-03, 2.170613371e-05, 5.846590589e-11}), + // R2.5: print(dgamma((x, shape=.1, rate=1), digits=10) + Arguments.of(0.1, 1, x, new double[]{0.000000000e+00, 2.640334143e+04, 1.189704437e-01, 3.866916944e-02, 7.623306235e-03, 1.663849010e-04}), + // To force overflow condition + // R2.5: print(dgamma((x, shape=1000, rate=100), digits=10) + Arguments.of(1000, 100, x, new double[]{0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 0.000000000e+00, 3.304830256e-84}), + + // Test a shape far below 1. + // Support for very small shape parameters was fixed in STATISTICS-39. + // R2.5: print(dgamma((x1, shape=0.05, rate=1), digits=20) + Arguments.of(0.05, 1, x1, + new double[] { + 5.1360843263583843333e+93, 1.6241724724359893799e+08, + 2.8882035841935007738e+03, 4.1419294512123655538e-01 + }) + ); } - private void checkDensity(double alpha, double rate, double[] x, double[] expected) { + @ParameterizedTest + @MethodSource + void testAdditionalLogDensity(double alpha, double rate, double[] x, double[] expected) { final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate); - for (int i = 0; i < x.length; i++) { - Assertions.assertEquals(expected[i], dist.density(x[i]), Math.abs(expected[i]) * 1e-9); - } + testLogDensity(dist, x, expected, DoubleTolerances.relative(1e-9)); } - @Test - void testAdditionalLogDensity() { - final double[] x = new double[]{-0.1, 1e-6, 0.5, 1, 2, 5}; - final double inf = Double.POSITIVE_INFINITY; - // R2.5: print(dgamma(x, shape=1, rate=1, log=TRUE), digits=10) - checkLogDensity(1, 1, x, new double[]{-inf, -1e-06, -5e-01, -1e+00, -2e+00, -5e+00}); - // R2.5: print(dgamma(x, shape=2, rate=1, log=TRUE), digits=10) - checkLogDensity(2, 1, x, new double[]{-inf, -13.815511558, -1.193147181, -1.000000000, -1.306852819, -3.390562088}); - // R2.5: print(dgamma(x, shape=4, rate=1, log=TRUE), digits=10) - checkLogDensity(4, 1, x, new double[]{-inf, -43.238292143, -4.371201011, -2.791759469, -1.712317928, -1.963445732}); - // R2.5: print(dgamma(x, shape=4, rate=10, log=TRUE), digits=10) - checkLogDensity(4, 10, x, new double[]{-inf, -34.0279607711, 0.3391393611, -2.5814190973, -10.5019775556, -37.7531053599}); - // R2.5: print(dgamma(x, shape=.1, rate=10, log=TRUE), digits=10) - checkLogDensity(0.1, 10, x, new double[]{-inf, 10.41149536, -6.39862168, -12.02245414, -22.64628660, -53.47094826}); - // R2.5: print(dgamma(x, shape=.1, rate=20, log=TRUE), digits=10) - checkLogDensity(0.1, 20, x, new double[]{-inf, 10.48080008, -11.32930696, -21.95313942, -42.57697189, -103.40163355}); - // R2.5: print(dgamma(x, shape=.1, rate=4, log=TRUE), digits=10) - checkLogDensity(0.1, 4, x, new double[]{-inf, 10.319872287, -3.490250753, -6.114083216, -10.737915678, -23.562577337}); - // R2.5: print(dgamma(x, shape=.1, rate=1, log=TRUE), digits=10) - checkLogDensity(0.1, 1, x, new double[]{-inf, 10.181245850, -2.128880189, -3.252712652, -4.876545114, -8.701206773}); - // To force overflow condition to pdf=zero - // R2.5: print(dgamma(x, shape=1000, rate=100, log=TRUE), digits=10) - checkLogDensity(1000, 100, x, new double[]{-inf, -15101.7453846, -2042.5042706, -1400.0502372, -807.5962038, -192.2217627}); - // To force overflow condition to pdf=infinity + static Stream<Arguments> testAdditionalLogDensity() { + final double[] x = {-0.1, 1e-6, 0.5, 1, 2, 5}; final double[] x1 = {1e-315, 1e-320, 1e-323}; - // scipy.stats gamma(1e-2).logpdf(x1) - checkLogDensity(0.01, 1, x1, new double[]{713.46168137365419, 724.85948860402209, 731.70997561537104}); - } - - private void checkLogDensity(double alpha, double rate, double[] x, double[] expected) { - final GammaDistribution dist = GammaDistribution.of(alpha, 1 / rate); - for (int i = 0; i < x.length; i++) { - Assertions.assertEquals(expected[i], dist.logDensity(x[i]), Math.abs(expected[i]) * 1e-9); - } + final double inf = Double.POSITIVE_INFINITY; + return Stream.of( + // R2.5: print(dgamma((x, shape=1, rate=1, log=TRUE), digits=10) + Arguments.of(1, 1, x, new double[]{-inf, -1e-06, -5e-01, -1e+00, -2e+00, -5e+00}), + // R2.5: print(dgamma((x, shape=2, rate=1, log=TRUE), digits=10) + Arguments.of(2, 1, x, new double[]{-inf, -13.815511558, -1.193147181, -1.000000000, -1.306852819, -3.390562088}), + // R2.5: print(dgamma((x, shape=4, rate=1, log=TRUE), digits=10) + Arguments.of(4, 1, x, new double[]{-inf, -43.238292143, -4.371201011, -2.791759469, -1.712317928, -1.963445732}), + // R2.5: print(dgamma((x, shape=4, rate=10, log=TRUE), digits=10) + Arguments.of(4, 10, x, new double[]{-inf, -34.0279607711, 0.3391393611, -2.5814190973, -10.5019775556, -37.7531053599}), + // R2.5: print(dgamma((x, shape=.1, rate=10, log=TRUE), digits=10) + Arguments.of(0.1, 10, x, new double[]{-inf, 10.41149536, -6.39862168, -12.02245414, -22.64628660, -53.47094826}), + // R2.5: print(dgamma((x, shape=.1, rate=20, log=TRUE), digits=10) + Arguments.of(0.1, 20, x, new double[]{-inf, 10.48080008, -11.32930696, -21.95313942, -42.57697189, -103.40163355}), + // R2.5: print(dgamma((x, shape=.1, rate=4, log=TRUE), digits=10) + Arguments.of(0.1, 4, x, new double[]{-inf, 10.319872287, -3.490250753, -6.114083216, -10.737915678, -23.562577337}), + // R2.5: print(dgamma((x, shape=.1, rate=1, log=TRUE), digits=10) + Arguments.of(0.1, 1, x, new double[]{-inf, 10.181245850, -2.128880189, -3.252712652, -4.876545114, -8.701206773}), + // To force overflow condition to pdf=zero + // R2.5: print(dgamma((x, shape=1000, rate=100, log=TRUE), digits=10) + Arguments.of(1000, 100, x, new double[]{-inf, -15101.7453846, -2042.5042706, -1400.0502372, -807.5962038, -192.2217627}), + // To force overflow condition to pdf=infinity + // scipy.stats gamma(1e-2).logpdf(x1) + Arguments.of(0.01, 1, x1, + new double[]{713.46168137365419, 724.85948860402209, 731.70997561537104}) + ); } private static double logGamma(double x) { @@ -205,9 +202,9 @@ class GammaDistributionTest extends BaseContinuousDistributionTest { HALF_LOG_2_PI + Math.log(sum / x); } - private static double density(final double x, - final double shape, - final double scale) { + private static double density(double x, + double shape, + double scale) { /* * This is a copy of * double GammaDistribution.density(double) @@ -234,11 +231,13 @@ class GammaDistributionTest extends BaseContinuousDistributionTest { * @param resourceName Resource name containing a pair of comma separated values for the * random variable x and the expected value of the gamma distribution: x, gamma(x; shape, scale=1) */ - private void doTestMath753(final double shape, - final double meanNoOF, final double sdNoOF, - final double meanOF, final double sdOF, - final String resourceName) { - final GammaDistribution distribution = GammaDistribution.of(shape, 1.0); + @ParameterizedTest + @MethodSource + void testMath753(double shape, + double meanNoOF, double sdNoOF, + double meanOF, double sdOF, + String resourceName) { + final GammaDistribution dist = GammaDistribution.of(shape, 1.0); final SummaryStatistics statOld = new SummaryStatistics(); // statNewNoOF = No overflow of old function // statNewOF = Overflow of old function @@ -261,7 +260,7 @@ class GammaDistributionTest extends BaseContinuousDistributionTest { final double expected = Double.parseDouble(tokens[1]); final double ulp = Math.ulp(expected); final double actualOld = density(x, shape, 1.0); - final double actualNew = distribution.density(x); + final double actualNew = dist.density(x); final double errOld = Math.abs((actualOld - expected) / ulp); final double errNew = Math.abs((actualNew - expected) / ulp); @@ -333,48 +332,17 @@ class GammaDistributionTest extends BaseContinuousDistributionTest { } } - @Test - void testMath753Shape025() { - doTestMath753(0.25, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.25.csv"); - } - - @Test - void testMath753Shape05() { - doTestMath753(0.5, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.5.csv"); - } - - @Test - void testMath753Shape075() { - doTestMath753(0.75, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.75.csv"); - } - - @Test - void testMath753Shape1() { - doTestMath753(1.0, 1.0, 0.5, 0.0, 0.0, "gamma-distribution-shape-1.csv"); - } - - @Test - void testMath753Shape8() { - doTestMath753(8.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-8.csv"); - } - - @Test - void testMath753Shape10() { - doTestMath753(10.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-10.csv"); - } - - @Test - void testMath753Shape100() { - doTestMath753(100.0, 2.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-100.csv"); - } - - @Test - void testMath753Shape142() { - doTestMath753(142.0, 1.5, 1.0, 40.0, 40.0, "gamma-distribution-shape-142.csv"); - } - - @Test - void testMath753Shape1000() { - doTestMath753(1000.0, 1.0, 1.0, 160.0, 200.0, "gamma-distribution-shape-1000.csv"); + static Stream<Arguments> testMath753() { + return Stream.of( + Arguments.of(0.25, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.25.csv"), + Arguments.of(0.5, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.5.csv"), + Arguments.of(0.75, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-0.75.csv"), + Arguments.of(1.0, 1.0, 0.5, 0.0, 0.0, "gamma-distribution-shape-1.csv"), + Arguments.of(8.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-8.csv"), + Arguments.of(10.0, 1.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-10.csv"), + Arguments.of(100.0, 2.0, 1.0, 0.0, 0.0, "gamma-distribution-shape-100.csv"), + Arguments.of(142.0, 1.5, 1.0, 40.0, 40.0, "gamma-distribution-shape-142.csv"), + Arguments.of(1000.0, 1.0, 1.0, 160.0, 200.0, "gamma-distribution-shape-1000.csv") + ); } }