From ba98d8bf983ef3057102503379c1258ef5d1940c Mon Sep 17 00:00:00 2001 From: Amos Shi Date: Mon, 26 Aug 2024 18:49:44 +0000 Subject: [PATCH] 8302800: Augment NaN handling tests of FDLIBM methods Reviewed-by: mbaesken Backport-of: dfce4e1943f2f95b74b5a9cdde9d738dcffd0b43 --- test/jdk/java/lang/Math/CubeRootTests.java | 25 ++- test/jdk/java/lang/Math/Expm1Tests.java | 24 ++- test/jdk/java/lang/Math/HyperbolicTests.java | 52 ++--- test/jdk/java/lang/Math/InverseTrigTests.java | 187 ++++++++++++++++++ test/jdk/java/lang/Math/Log10Tests.java | 36 ++-- test/jdk/java/lang/Math/Log1pTests.java | 21 +- test/jdk/java/lang/Math/Tests.java | 35 +++- 7 files changed, 286 insertions(+), 94 deletions(-) create mode 100644 test/jdk/java/lang/Math/InverseTrigTests.java diff --git a/test/jdk/java/lang/Math/CubeRootTests.java b/test/jdk/java/lang/Math/CubeRootTests.java index a6350702d90..9347160d719 100644 --- a/test/jdk/java/lang/Math/CubeRootTests.java +++ b/test/jdk/java/lang/Math/CubeRootTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @library /test/lib * @build jdk.test.lib.RandomFactory + * @build Tests * @run main CubeRootTests * @bug 4347132 4939441 8078672 * @summary Tests for {Math, StrictMath}.cbrt (use -Dseed=X to set PRNG seed) @@ -32,6 +33,7 @@ */ import jdk.test.lib.RandomFactory; +import static java.lang.Double.longBitsToDouble; public class CubeRootTests { private CubeRootTests(){} @@ -42,7 +44,7 @@ private CubeRootTests(){} // Initialize shared random number generator static java.util.Random rand = RandomFactory.getRandom(); - static int testCubeRootCase(double input, double expected) { + private static int testCubeRootCase(double input, double expected) { int failures=0; failures+=Tests.test("Math.cbrt", input, Math::cbrt, expected); @@ -53,22 +55,17 @@ static int testCubeRootCase(double input, double expected) { return failures; } - static int testCubeRoot() { + private static int testCubeRoot() { int failures = 0; + + for(double nan : Tests.NaNs) { + failures += testCubeRootCase(nan, NaNd); + } + double [][] testCases = { - {NaNd, NaNd}, - {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, - {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, - {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, - {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, - {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, - {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, {Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY}, + {+0.0, +0.0}, {-0.0, -0.0}, {+1.0, +1.0}, diff --git a/test/jdk/java/lang/Math/Expm1Tests.java b/test/jdk/java/lang/Math/Expm1Tests.java index 204fe44ef15..61f02acfe21 100644 --- a/test/jdk/java/lang/Math/Expm1Tests.java +++ b/test/jdk/java/lang/Math/Expm1Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,14 @@ /* * @test * @bug 4851638 4900189 4939441 + * @build Tests + * @build Expm1Tests + * @run main Expm1Tests * @summary Tests for {Math, StrictMath}.expm1 */ +import static java.lang.Double.longBitsToDouble; + /* * The Taylor expansion of expxm1(x) = exp(x) -1 is * @@ -48,21 +53,14 @@ private Expm1Tests(){} static final double infinityD = Double.POSITIVE_INFINITY; static final double NaNd = Double.NaN; - static int testExpm1() { + private static int testExpm1() { int failures = 0; + for(double nan : Tests.NaNs) { + failures += testExpm1Case(nan, NaNd); + } + double [][] testCases = { - {Double.NaN, NaNd}, - {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, - {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, - {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, - {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, - {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, - {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, {infinityD, infinityD}, {-infinityD, -1.0}, {-0.0, -0.0}, diff --git a/test/jdk/java/lang/Math/HyperbolicTests.java b/test/jdk/java/lang/Math/HyperbolicTests.java index 8309606f63d..c0ce8f49ef3 100644 --- a/test/jdk/java/lang/Math/HyperbolicTests.java +++ b/test/jdk/java/lang/Math/HyperbolicTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,14 @@ /* * @test * @bug 4851625 4900189 4939441 + * @build Tests + * @build HyperbolicTests + * @run main HyperbolicTests * @summary Tests for {Math, StrictMath}.{sinh, cosh, tanh} */ +import static java.lang.Double.longBitsToDouble; + public class HyperbolicTests { private HyperbolicTests(){} @@ -248,19 +253,12 @@ static int testSinh() { 3.0); } + for(double nan : Tests.NaNs) { + failures += testSinhCaseWithUlpDiff(nan, NaNd, 0); + } + double [][] specialTestCases = { {0.0, 0.0}, - {NaNd, NaNd}, - {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, - {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, - {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, - {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, - {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, - {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY} }; @@ -590,19 +588,12 @@ static int testCosh() { 3.0); } + for(double nan : Tests.NaNs) { + failures += testCoshCaseWithUlpDiff(nan, NaNd, 0); + } + double [][] specialTestCases = { {0.0, 1.0}, - {NaNd, NaNd}, - {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, - {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, - {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, - {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, - {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, - {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY} }; @@ -938,19 +929,12 @@ static int testTanh() { 3.0); } + for(double nan : Tests.NaNs) { + failures += testTanhCaseWithUlpDiff(nan, NaNd, 0); + } + double [][] specialTestCases = { {0.0, 0.0}, - {NaNd, NaNd}, - {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, - {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, - {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, - {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, - {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, - {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, {Double.POSITIVE_INFINITY, 1.0} }; diff --git a/test/jdk/java/lang/Math/InverseTrigTests.java b/test/jdk/java/lang/Math/InverseTrigTests.java new file mode 100644 index 00000000000..f533b509d3d --- /dev/null +++ b/test/jdk/java/lang/Math/InverseTrigTests.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8302026 + * @build Tests + * @build InverseTrigTests + * @run main InverseTrigTests + * @summary Tests for {Math, StrictMath}.{asin, acos, atan} + */ + +import static java.lang.Double.longBitsToDouble; + +public class InverseTrigTests { + private InverseTrigTests(){} + + public static void main(String... args) { + int failures = 0; + + failures += testAsinSpecialCases(); + failures += testAcosSpecialCases(); + failures += testAtanSpecialCases(); + + if (failures > 0) { + System.err.println("Testing inverse trig mthods incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + + private static final double InfinityD = Double.POSITIVE_INFINITY; + private static final double NaNd = Double.NaN; + + /** + * From the spec for Math.asin: + * + * "Special cases: + * + * If the argument is NaN or its absolute value is greater than 1, + * then the result is NaN. + * + * If the argument is zero, then the result is a zero with the + * same sign as the argument." + */ + private static int testAsinSpecialCases() { + int failures = 0; + + for(double nan : Tests.NaNs) { + failures += testAsinCase(nan, NaNd); + } + + double [][] testCases = { + {Math.nextUp(1.0), NaNd}, + {Math.nextDown(-1.0), NaNd}, + { InfinityD, NaNd}, + {-InfinityD, NaNd}, + + {-0.0, -0.0}, + {+0.0, +0.0}, + }; + + for(int i = 0; i < testCases.length; i++) { + failures += testAsinCase(testCases[i][0], + testCases[i][1]); + } + + return failures; + } + + private static int testAsinCase(double input, double expected) { + int failures=0; + + failures += Tests.test("Math.asin", input, Math::asin, expected); + failures += Tests.test("StrictMath.asin", input, StrictMath::asin, expected); + + return failures; + } + + /** + * From the spec for Math.acos: + * + * "Special case: + * + * If the argument is NaN or its absolute value is greater than 1, + * then the result is NaN. + * + * If the argument is 1.0, the result is positive zero." + */ + private static int testAcosSpecialCases() { + int failures = 0; + + for(double nan : Tests.NaNs) { + failures += testAcosCase(nan, NaNd); + } + + double [][] testCases = { + {Math.nextUp(1.0), NaNd}, + {Math.nextDown(-1.0), NaNd}, + {InfinityD, NaNd}, + {-InfinityD, NaNd}, + + {1.0, +0.0}, + }; + + for(int i = 0; i < testCases.length; i++) { + failures += testAcosCase(testCases[i][0], + testCases[i][1]); + } + + return failures; + } + + private static int testAcosCase(double input, double expected) { + int failures=0; + + failures += Tests.test("Math.acos", input, Math::acos, expected); + failures += Tests.test("StrictMath.acos", input, StrictMath::acos, expected); + + return failures; + } + + /** + * From the spec for Math.atan: + * + * "Special cases: + * + * If the argument is NaN, then the result is NaN. + * + * If the argument is zero, then the result is a zero with the + * same sign as the argument. + * + * If the argument is infinite, then the result is the closest + * value to pi/2 with the same sign as the input." + */ + private static int testAtanSpecialCases() { + int failures = 0; + + for(double nan : Tests.NaNs) { + failures += testAtanCase(nan, NaNd); + } + + double [][] testCases = { + {-0.0, -0.0}, + {+0.0, +0.0}, + + { InfinityD, +Math.PI/2.0}, + {-InfinityD, -Math.PI/2.0}, + }; + + for(int i = 0; i < testCases.length; i++) { + failures += testAtanCase(testCases[i][0], + testCases[i][1]); + } + + return failures; + } + + private static int testAtanCase(double input, double expected) { + int failures=0; + + failures += Tests.test("Math.atan", input, Math::atan, expected); + failures += Tests.test("StrictMath.atan", input, StrictMath::atan, expected); + + return failures; + } +} diff --git a/test/jdk/java/lang/Math/Log10Tests.java b/test/jdk/java/lang/Math/Log10Tests.java index dbdd7c14179..f53004ca0bc 100644 --- a/test/jdk/java/lang/Math/Log10Tests.java +++ b/test/jdk/java/lang/Math/Log10Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,43 +24,41 @@ /* * @test * @bug 4074599 4939441 + * @build Tests + * @build Log10Tests + * @run main Log10Tests * @summary Tests for {Math, StrictMath}.log10 */ +import static java.lang.Double.longBitsToDouble; + public class Log10Tests { private Log10Tests(){} - static final double infinityD = Double.POSITIVE_INFINITY; - static final double NaNd = Double.NaN; - static final double LN_10 = StrictMath.log(10.0); + private static final double infinityD = Double.POSITIVE_INFINITY; + private static final double NaNd = Double.NaN; + private static final double LN_10 = StrictMath.log(10.0); // Initialize shared random number generator static java.util.Random rand = new java.util.Random(0L); - static int testLog10Case(double input, double expected) { + private static int testLog10Case(double input, double expected) { int failures=0; - failures+=Tests.test("Math.log10", input, Math::log10, expected); - failures+=Tests.test("StrictMath.log10", input, StrictMath::log10, expected); + failures += Tests.test("Math.log10", input, Math::log10, expected); + failures += Tests.test("StrictMath.log10", input, StrictMath::log10, expected); return failures; } - static int testLog10() { + private static int testLog10() { int failures = 0; + for(double nan : Tests.NaNs) { + failures += testLog10Case(nan, NaNd); + } + double [][] testCases = { - {Double.NaN, NaNd}, - {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, - {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, - {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, - {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, - {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, - {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, {Double.NEGATIVE_INFINITY, NaNd}, {-8.0, NaNd}, {-1.0, NaNd}, diff --git a/test/jdk/java/lang/Math/Log1pTests.java b/test/jdk/java/lang/Math/Log1pTests.java index 2fa7ddec442..89412fc971e 100644 --- a/test/jdk/java/lang/Math/Log1pTests.java +++ b/test/jdk/java/lang/Math/Log1pTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ * @test * @library /test/lib * @build jdk.test.lib.RandomFactory + * @build Tests + * @build Log1pTests * @run main Log1pTests * @bug 4851638 4939441 8078672 * @summary Tests for {Math, StrictMath}.log1p (use -Dseed=X to set PRNG seed) @@ -59,21 +61,14 @@ static double hp15cLogp(double x) { * Also x/(x+1) < ln(1+x) < x */ - static int testLog1p() { + private static int testLog1p() { int failures = 0; + for(double nan : Tests.NaNs) { + failures += testLog1pCase(nan, NaNd); + } + double [][] testCases = { - {Double.NaN, NaNd}, - {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, - {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, - {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, - {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, - {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, - {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, - {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, - {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, {Double.NEGATIVE_INFINITY, NaNd}, {-8.0, NaNd}, {-1.0, -infinityD}, diff --git a/test/jdk/java/lang/Math/Tests.java b/test/jdk/java/lang/Math/Tests.java index f1de6319a9e..60981e318e2 100644 --- a/test/jdk/java/lang/Math/Tests.java +++ b/test/jdk/java/lang/Math/Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ import java.util.function.DoubleBinaryOperator; import java.util.function.DoubleUnaryOperator; import java.util.function.DoubleToIntFunction; +import static java.lang.Double.longBitsToDouble; /* * Shared static test methods for numerical tests. Sharing these @@ -37,6 +38,38 @@ public class Tests { private Tests(){}; // do not instantiate + // Used to create a NaN value at runtime; mark as volatile to foil + // compile-time constant folding. + static volatile double zero = 0.0; + + private static final double PLATFORM_NAN = zero / zero; + + public static final double[] NaNs = { + Double.NaN, + PLATFORM_NAN, + bitwiseNegate(PLATFORM_NAN), + // Exotic NaN bit patterns. Includes values that would + // *not* be considered a NaN if only the high-order + // 32-bits were examined. + longBitsToDouble(0x7FF0_0000_0000_0001L), + longBitsToDouble(0xFFF0_0000_0000_0001L), + longBitsToDouble(0x7FF8_5555_5555_5555L), + longBitsToDouble(0xFFF8_5555_5555_5555L), + longBitsToDouble(0x7FFF_FFFF_FFFF_FFFFL), + longBitsToDouble(0xFFFF_FFFF_FFFF_FFFFL), + longBitsToDouble(0x7FF0_0000_7FFF_FFFFL), + longBitsToDouble(0xFFF0_0000_7FFF_FFFFL), + longBitsToDouble(0x7FF0_Dead_Beef_0000L), + longBitsToDouble(0xFFF0_Dead_Beef_0000L), + longBitsToDouble(0x7FF0_Cafe_Babe_0000L), + longBitsToDouble(0xFFF0_Cafe_Babe_0000L), + }; + + public static double bitwiseNegate(double d) { + long SIGNBIT = 0x8000_0000_0000_0000L; + return longBitsToDouble(Double.doubleToRawLongBits(d) ^ SIGNBIT ); + } + public static String toHexString(float f) { if (!Float.isNaN(f)) return Float.toHexString(f);