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 8e1ec4cfb3ce498bde9f0908054ce2c3f9b36e07 Author: Alex Herbert <aherb...@apache.org> AuthorDate: Thu Dec 21 20:38:05 2023 +0000 Move default StatisticResult implementations to IntMath --- .../statistics/descriptive/StatisticResult.java | 50 ++++++---------------- .../commons/statistics/descriptive/Statistics.java | 29 ------------- .../statistics/descriptive/IntMathTest.java | 3 +- src/conf/pmd/pmd-ruleset.xml | 2 +- 4 files changed, 17 insertions(+), 67 deletions(-) diff --git a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/StatisticResult.java b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/StatisticResult.java index 56108e7..79af4ca 100644 --- a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/StatisticResult.java +++ b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/StatisticResult.java @@ -16,7 +16,6 @@ */ package org.apache.commons.statistics.descriptive; -import java.math.BigDecimal; import java.math.BigInteger; import java.util.function.DoubleSupplier; import java.util.function.IntSupplier; @@ -35,67 +34,46 @@ public interface StatisticResult extends DoubleSupplier, IntSupplier, LongSuppli * {@inheritDoc} * * <p>The default implementation uses the closest representable {@code int} value of - * the {@link #getAsDouble()} result. In the event of ties the result is towards - * positive infinity. This will raise an {@link ArithmeticException} if the closest - * integer result is not within the range {@code [-2^31, 2^31)}. + * the {@link #getAsDouble()} {@code result}. In the event of ties the result is + * rounded towards positive infinity. This will raise an {@link ArithmeticException} + * if the closest integer result is not within the range {@code [-2^31, 2^31)}. * - * @throws ArithmeticException if the {@code result} overflows an int, or is not + * @throws ArithmeticException if the {@code result} overflows an {@code int} or is not * finite */ @Override default int getAsInt() { - // Note: Do not use (int) getAsLong() to avoid a narrowing primitive conversion. - final double x = getAsDouble(); - final double r = Statistics.roundToInteger(x); - if (r >= -0x1.0p31 && r < 0x1.0p31) { - return (int) r; - } - throw new ArithmeticException("integer overflow: " + x); + return IntMath.toIntExact(getAsDouble()); } /** * {@inheritDoc} * * <p>The default implementation uses the closest representable {@code long} value of - * the {@link #getAsDouble()} result. In the event of ties the result is rounded - * positive infinity. This will raise an {@link ArithmeticException} if the closest - * long integer result is not within the range {@code [-2^63, 2^63)}. + * the {@link #getAsDouble()} {@code result}. In the event of ties the result is + * rounded towards positive infinity. This will raise an {@link ArithmeticException} + * if the closest integer result is not within the range {@code [-2^63, 2^63)}. * - * @throws ArithmeticException if the {@code result} overflows a long, or is not + * @throws ArithmeticException if the {@code result} overflows a {@code long} or is not * finite */ @Override default long getAsLong() { - final double x = getAsDouble(); - final double r = Statistics.roundToInteger(x); - if (r >= -0x1.0p63 && r < 0x1.0p63) { - return (long) r; - } - throw new ArithmeticException("long integer overflow: " + x); + return IntMath.toLongExact(getAsDouble()); } /** * Gets a result as a {@link BigInteger}. * * <p>The default implementation uses the closest representable {@code BigInteger} - * value of the {@link #getAsDouble()} result. In the event of ties the result is - * rounded positive infinity. This will raise an {@link ArithmeticException} if the - * result is not finite. + * value of the {@link #getAsDouble()} {@code result}. In the event of ties the result + * is rounded towards positive infinity. This will raise an + * {@link ArithmeticException} if the {@code result} is not finite. * * @return a result * @throws ArithmeticException if the {@code result} is not finite */ default BigInteger getAsBigInteger() { - final double x = getAsDouble(); - if (!Double.isFinite(x)) { - throw new ArithmeticException("BigInteger overflow: " + x); - } - final double r = Statistics.roundToInteger(x); - if (r >= -0x1.0p63 && r < 0x1.0p63) { - // Representable as a long - return BigInteger.valueOf((long) r); - } - // Large result - return new BigDecimal(r).toBigInteger(); + return IntMath.toBigIntegerExact(getAsDouble()); } } diff --git a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Statistics.java b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Statistics.java index 73c8a40..f43218c 100644 --- a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Statistics.java +++ b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Statistics.java @@ -24,9 +24,6 @@ import java.util.function.LongConsumer; * Utility methods for statistics. */ final class Statistics { - /** 0.5. */ - private static final double HALF = 0.5; - /** No instances. */ private Statistics() {} @@ -95,30 +92,4 @@ final class Statistics { // (1e-15 ~ 4.5 eps where eps = 2^-52). return m2 <= Math.pow(1e-15 * m1, 2); } - - /** - * Get the whole number that is the nearest to x, with ties rounding towards positive infinity. - * - * <p>This method is intended to perform the equivalent of - * {@link Math#round(double)} without converting to a {@code long} primitive type. - * This allows the domain of the result to be checked against the range {@code [-2^63, 2^63)}. - * - * <p>Note: Adapted from {@code o.a.c.math4.AccurateMath.rint} and - * modified to perform rounding towards positive infinity. - * - * @param x Number from which nearest whole number is requested. - * @return a double number r such that r is an integer {@code r - 0.5 <= x < r + 0.5} - */ - static double roundToInteger(double x) { - final double y = Math.floor(x); - final double d = x - y; - if (d >= HALF) { - // Here we do not preserve the sign of the operand in the case - // of -0.5 < x <= -0.0 since the rounded result is required as an integer. - // if y == -1.0: - // return -0.0 - return y + 1.0; - } - return y; - } } diff --git a/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/IntMathTest.java b/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/IntMathTest.java index c390041..09721ff 100644 --- a/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/IntMathTest.java +++ b/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/IntMathTest.java @@ -26,6 +26,7 @@ import java.util.stream.Stream; import org.apache.commons.rng.UniformRandomProvider; import org.apache.commons.rng.simple.RandomSource; 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.MethodSource; @@ -73,7 +74,7 @@ class IntMathTest { () -> String.format("%s * %s", bi1, bi2)); final double x = expected.doubleValue(); Assertions.assertEquals(x, IntMath.unsignedMultiplyToDouble(a, b), - () -> String.format("double2 %s * %s", bi1, bi2)); + () -> String.format("double %s * %s", bi1, bi2)); } static Stream<Arguments> testUnsignedMultiplyHigh() { diff --git a/src/conf/pmd/pmd-ruleset.xml b/src/conf/pmd/pmd-ruleset.xml index ff41429..72d7b54 100644 --- a/src/conf/pmd/pmd-ruleset.xml +++ b/src/conf/pmd/pmd-ruleset.xml @@ -212,7 +212,7 @@ <properties> <!-- Exact conversion from double to BigInteger is required. --> <property name="violationSuppressXPath" - value="./ancestor-or-self::MethodDeclaration[@Name='getAsBigInteger']"/> + value="./ancestor-or-self::MethodDeclaration[@Name='toBigIntegerExact']"/> </properties> </rule>