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 <[email protected]> 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(); + } }
