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 b58bd961ddbb0d2f1ce05fd28516fae2bf0160db
Author: Alex Herbert <aherb...@apache.org>
AuthorDate: Tue Mar 25 12:44:50 2025 +0000

    Sonar fix: encapsulate division logic in Int128
---
 .../commons/statistics/descriptive/Int128.java     | 18 +++++++++++++
 .../commons/statistics/descriptive/IntMath.java    | 20 --------------
 .../commons/statistics/descriptive/IntMean.java    |  2 +-
 .../commons/statistics/descriptive/LongMean.java   |  2 +-
 .../commons/statistics/descriptive/Int128Test.java | 29 ++++++++++++++++++++
 .../statistics/descriptive/IntMathTest.java        | 31 ----------------------
 6 files changed, 49 insertions(+), 53 deletions(-)

diff --git 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Int128.java
 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Int128.java
index bf0b99e..b006ea1 100644
--- 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Int128.java
+++ 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/Int128.java
@@ -38,6 +38,8 @@ import org.apache.commons.numbers.core.DD;
 final class Int128 {
     /** Mask for the lower 32-bits of a long. */
     private static final long MASK32 = 0xffff_ffffL;
+    /** 2^53. */
+    private static final long TWO_POW_53 = 1L << 53;
 
     /** low 64-bits. */
     private long lo;
@@ -249,6 +251,22 @@ final class Int128 {
         return DD.of(lo).add((hi & MASK32) * 0x1.0p64).add((hi >> 
Integer.SIZE) * 0x1.0p96);
     }
 
+    /**
+     * Divide by the count {@code n}, returning the value as a {@code double}.
+     *
+     * @param n Count.
+     * @return the quotient
+     */
+    double divideToDouble(long n) {
+        final DD a = toDD();
+        if (n < TWO_POW_53) {
+            // n is a representable double
+            return a.divide(n).doubleValue();
+        }
+        // Extended precision divide when n > 2^53
+        return a.divide(DD.of(n)).doubleValue();
+    }
+
     /**
      * Convert to an {@code int}; throwing an exception if the value overflows 
an {@code int}.
      *
diff --git 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMath.java
 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMath.java
index fd5c164..2309750 100644
--- 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMath.java
+++ 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMath.java
@@ -18,7 +18,6 @@ package org.apache.commons.statistics.descriptive;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import org.apache.commons.numbers.core.DD;
 
 /**
  * Support class for integer math.
@@ -36,8 +35,6 @@ final class IntMath {
     private static final int EXP_SHIFT = 52;
     /** 0.5. */
     private static final double HALF = 0.5;
-    /** 2^53. */
-    private static final long TWO_POW_53 = 1L << 53;
 
     /** No instances. */
     private IntMath() {}
@@ -391,21 +388,4 @@ final class IntMath {
         }
         return y;
     }
-
-    /**
-     * Divide value {@code x} by the count {@code n}.
-     *
-     * @param x Value.
-     * @param n Count.
-     * @return the quotient
-     */
-    static double divide(Int128 x, long n) {
-        final DD a = x.toDD();
-        if (n < TWO_POW_53) {
-            // n is a representable double
-            return a.divide(n).doubleValue();
-        }
-        // Extended precision divide when n > 2^53
-        return a.divide(DD.of(n)).doubleValue();
-    }
 }
diff --git 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMean.java
 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMean.java
index 5987571..9fcbff6 100644
--- 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMean.java
+++ 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/IntMean.java
@@ -180,7 +180,7 @@ public final class IntMean implements IntStatistic, 
StatisticAccumulator<IntMean
             return (double) sum.lo64() / n;
         }
         // Extended precision
-        return IntMath.divide(sum, n);
+        return sum.divideToDouble(n);
     }
 
     @Override
diff --git 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/LongMean.java
 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/LongMean.java
index 492ed78..305b1ba 100644
--- 
a/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/LongMean.java
+++ 
b/commons-statistics-descriptive/src/main/java/org/apache/commons/statistics/descriptive/LongMean.java
@@ -177,7 +177,7 @@ public final class LongMean implements LongStatistic, 
StatisticAccumulator<LongM
             return (double) sum.lo64() / n;
         }
         // Extended precision
-        return IntMath.divide(sum, n);
+        return sum.divideToDouble(n);
     }
 
     @Override
diff --git 
a/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/Int128Test.java
 
b/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/Int128Test.java
index b445474..8f884ce 100644
--- 
a/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/Int128Test.java
+++ 
b/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/Int128Test.java
@@ -19,11 +19,14 @@ package org.apache.commons.statistics.descriptive;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.math.MathContext;
 import java.util.Arrays;
 import java.util.stream.LongStream;
 import java.util.stream.Stream;
 import org.apache.commons.rng.UniformRandomProvider;
 import org.apache.commons.rng.simple.RandomSource;
+import org.apache.commons.statistics.distribution.DoubleTolerances;
+import org.apache.commons.statistics.distribution.TestUtils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -179,6 +182,32 @@ class Int128Test {
         return builder.build();
     }
 
+    @ParameterizedTest
+    @MethodSource
+    void testDivideToDouble(long a, long b, long n) {
+        final Int128 x = new Int128(a, b);
+        final BigInteger bi = 
BigInteger.valueOf(a).shiftLeft(Long.SIZE).add(BigInteger.valueOf(b));
+        final double expected = new BigDecimal(bi).divide(
+            new BigDecimal(n), MathContext.DECIMAL128).doubleValue();
+        // This may require a 1 ulp tolerance; log the seed to allow repeats
+        TestUtils.assertEquals(expected, x.divideToDouble(n), 
DoubleTolerances.equals(),
+            () -> String.format("(2^64 * %d + %d) / %d; Seed=%s",
+                a, b, n, Arrays.toString(TestHelper.createRNGSeed())));
+    }
+
+    static Stream<Arguments> testDivideToDouble() {
+        final UniformRandomProvider rng = 
TestHelper.createRNG(TestHelper.createRNGSeed());
+        final Stream.Builder<Arguments> builder = Stream.builder();
+        for (int i = 0; i < 100; i++) {
+            final long a = rng.nextLong();
+            final long b = rng.nextLong();
+            final long n = rng.nextLong();
+            builder.accept(Arguments.of(a, b, n >>> 1));
+            builder.accept(Arguments.of(a, b, n >>> 43));
+        }
+        return builder.build();
+    }
+
     @ParameterizedTest
     @ValueSource(ints = {Integer.MAX_VALUE, Integer.MIN_VALUE})
     void testToIntExact(int x) {
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 f6efb10..72a298f 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
@@ -17,18 +17,13 @@
 
 package org.apache.commons.statistics.descriptive;
 
-import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.math.MathContext;
-import java.util.Arrays;
 import java.util.function.Supplier;
 import java.util.stream.DoubleStream;
 import java.util.stream.LongStream;
 import java.util.stream.LongStream.Builder;
 import java.util.stream.Stream;
 import org.apache.commons.rng.UniformRandomProvider;
-import org.apache.commons.statistics.distribution.DoubleTolerances;
-import org.apache.commons.statistics.distribution.TestUtils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -208,30 +203,4 @@ class IntMathTest {
         Assertions.assertEquals(0, Math.toIntExact(Math.round(x)));
         Assertions.assertThrowsExactly(ArithmeticException.class, () -> 
IntMath.toIntExact(x));
     }
-
-    @ParameterizedTest
-    @MethodSource
-    void testInt128Divide(long a, long b, long n) {
-        final Int128 x = new Int128(a, b);
-        final BigInteger bi = 
BigInteger.valueOf(a).shiftLeft(Long.SIZE).add(BigInteger.valueOf(b));
-        final double expected = new BigDecimal(bi).divide(
-            new BigDecimal(n), MathContext.DECIMAL128).doubleValue();
-        // This may require a 1 ulp tolerance; log the seed to allow repeats
-        TestUtils.assertEquals(expected, IntMath.divide(x, n), 
DoubleTolerances.equals(),
-            () -> String.format("(2^64 * %d + %d) / %d; Seed=%s",
-                a, b, n, Arrays.toString(TestHelper.createRNGSeed())));
-    }
-
-    static Stream<Arguments> testInt128Divide() {
-        final UniformRandomProvider rng = 
TestHelper.createRNG(TestHelper.createRNGSeed());
-        final Stream.Builder<Arguments> builder = Stream.builder();
-        for (int i = 0; i < 100; i++) {
-            final long a = rng.nextLong();
-            final long b = rng.nextLong();
-            final long n = rng.nextLong();
-            builder.accept(Arguments.of(a, b, n >>> 1));
-            builder.accept(Arguments.of(a, b, n >>> 43));
-        }
-        return builder.build();
-    }
 }

Reply via email to