You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2023/12/24 08:45:34 UTC

(commons-statistics) 02/02: Add additional test for conversion to a double

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 06853a9ba70ee25724f8e42ab122abfd819603f5
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sun Dec 24 08:44:50 2023 +0000

    Add additional test for conversion to a double
---
 .../statistics/descriptive/IntMathTest.java        |  8 ++---
 .../statistics/descriptive/UInt192Test.java        | 37 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 4 deletions(-)

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 c8ea420..ccc4416 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
@@ -99,14 +99,14 @@ class IntMathTest {
     }
 
     /**
-     * Create a big integer treating the value as unsigned.
+     * Create a BigInteger treating the value as unsigned.
      *
      * @param v Value
-     * @return the big integer
+     * @return the BigInteger
      */
-    private static BigInteger toUnsignedBigInteger(long v) {
+    static BigInteger toUnsignedBigInteger(long v) {
         return v < 0 ?
-            TWO_POW_63.add(BigInteger.valueOf(v & Long.MAX_VALUE)) :
+            TWO_POW_63.or(BigInteger.valueOf(v & Long.MAX_VALUE)) :
             BigInteger.valueOf(v);
     }
 
diff --git a/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/UInt192Test.java b/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/UInt192Test.java
index f91067a..0edf578 100644
--- a/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/UInt192Test.java
+++ b/commons-statistics-descriptive/src/test/java/org/apache/commons/statistics/descriptive/UInt192Test.java
@@ -255,4 +255,41 @@ class UInt192Test {
         Assertions.assertThrows(ArithmeticException.class, () -> v5.toLongExact());
         Assertions.assertEquals(0x1.0p128, v5.toDouble());
     }
+
+    /**
+     * Additional cases for conversion to a double.
+     * Conversion of uint128 is done in {@link IntMathTest#testUint128ToDouble()}.
+     * This test ensures any bits in the extra 64-bits of the 192-bit value are used.
+     */
+    @ParameterizedTest
+    @MethodSource
+    void testToDouble(long a, long b, long c) {
+        final UInt192 x = new UInt192(a, b, c);
+        final double expected = IntMathTest.toUnsignedBigInteger(a).shiftLeft(128)
+            .add(IntMathTest.toUnsignedBigInteger(b).shiftLeft(64))
+            .add(IntMathTest.toUnsignedBigInteger(c)).doubleValue();
+        Assertions.assertEquals(expected, x.toDouble());
+    }
+
+    static Stream<Arguments> testToDouble() {
+        final Stream.Builder<Arguments> builder = Stream.builder();
+        final UniformRandomProvider rng = TestHelper.createRNG();
+        for (int i = 0; i < 50; i++) {
+            long a = rng.nextLong();
+            final long b = rng.nextLong();
+            final long c = rng.nextLong();
+            builder.accept(Arguments.of(a, b, c));
+            // Edge cases where trailing bits are required for rounding.
+            // Create a 55-bit number. Ensure the highest bit is set.
+            a = (a << 9) | Long.MIN_VALUE;
+            // Shift right and carry bits down.
+            final int shift = rng.nextInt(1, 64);
+            final long x = a >>> shift;
+            final long y = a << -shift;
+            builder.accept(Arguments.of(x, y, 0));
+            builder.accept(Arguments.of(x, y | 1, 0));
+            builder.accept(Arguments.of(x, y, 1));
+        }
+        return builder.build();
+    }
 }