8240632: Note differences between IEEE 754-2019 math lib special cases and java.lang.Math
Reviewed-by: bpb
This commit is contained in:
parent
ace8f94616
commit
2fd8ed024b
src/java.base/share/classes/java/lang
test/jdk/java/lang/Math
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2021, 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
|
||||
@ -37,7 +37,7 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
* square root, and trigonometric functions.
|
||||
*
|
||||
* <p>Unlike some of the numeric methods of class
|
||||
* {@code StrictMath}, all implementations of the equivalent
|
||||
* {@link java.lang.StrictMath StrictMath}, all implementations of the equivalent
|
||||
* functions of class {@code Math} are not defined to return the
|
||||
* bit-for-bit same results. This relaxation permits
|
||||
* better-performing implementations where strict reproducibility is
|
||||
@ -99,6 +99,28 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
* occurs only with a specific minimum or maximum value and
|
||||
* should be checked against the minimum or maximum as appropriate.
|
||||
*
|
||||
* <h2><a id=Ieee754RecommendedOps>IEEE 754 Recommended
|
||||
* Operations</a></h2>
|
||||
*
|
||||
* The 2019 revision of the IEEE 754 floating-point standard includes
|
||||
* a section of recommended operations and the semantics of those
|
||||
* operations if they are included in a programming environment. The
|
||||
* recommended operations present in this class include {@link sin
|
||||
* sin}, {@link cos cos}, {@link tan tan}, {@link asin asin}, {@link
|
||||
* acos acos}, {@link atan atan}, {@link exp exp}, {@link expm1
|
||||
* expm1}, {@link log log}, {@link log10 log10}, {@link log1p log1p},
|
||||
* {@link sinh sinh}, {@link cosh cosh}, {@link tanh tanh}, {@link
|
||||
* hypot hypot}, and {@link pow pow}. (The {@link sqrt sqrt}
|
||||
* operation is a required part of IEEE 754 from a different section
|
||||
* of the standard.) The special case behavior of the recommended
|
||||
* operations generally follows the guidance of the IEEE 754
|
||||
* standard. However, the {@code pow} method defines different
|
||||
* behavior for some arguments, as noted in its {@linkplain pow
|
||||
* specification}. The IEEE 754 standard defines its operations to be
|
||||
* correctly rounded, which is a more stringent quality of
|
||||
* implementation condition than required for most of the methods in
|
||||
* question that are also included in this class.
|
||||
*
|
||||
* @author Joseph D. Darcy
|
||||
* @since 1.0
|
||||
*/
|
||||
@ -156,7 +178,9 @@ public final class Math {
|
||||
/**
|
||||
* Returns the trigonometric cosine of an angle. Special cases:
|
||||
* <ul><li>If the argument is NaN or an infinity, then the
|
||||
* result is NaN.</ul>
|
||||
* result is NaN.
|
||||
* <li>If the argument is zero, then the result is {@code 1.0}.
|
||||
*</ul>
|
||||
*
|
||||
* <p>The computed result must be within 1 ulp of the exact result.
|
||||
* Results must be semi-monotonic.
|
||||
@ -209,7 +233,9 @@ public final class Math {
|
||||
* Returns the arc cosine of a value; the returned angle is in the
|
||||
* range 0.0 through <i>pi</i>. Special case:
|
||||
* <ul><li>If the argument is NaN or its absolute value is greater
|
||||
* than 1, then the result is NaN.</ul>
|
||||
* than 1, then the result is NaN.
|
||||
* <li>If the argument is {@code 1.0}, the result is positive zero.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The computed result must be within 1 ulp of the exact result.
|
||||
* Results must be semi-monotonic.
|
||||
@ -226,7 +252,11 @@ public final class Math {
|
||||
* range -<i>pi</i>/2 through <i>pi</i>/2. Special cases:
|
||||
* <ul><li>If the argument is NaN, then the result is NaN.
|
||||
* <li>If the argument is zero, then the result is a zero with the
|
||||
* same sign as the argument.</ul>
|
||||
* same sign as the argument.
|
||||
* <li>If the argument is {@linkplain Double#isInfinite infinite},
|
||||
* then the result is the closest value to <i>pi</i>/2 with the
|
||||
* same sign as the input.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The computed result must be within 1 ulp of the exact result.
|
||||
* Results must be semi-monotonic.
|
||||
@ -275,7 +305,9 @@ public final class Math {
|
||||
* <li>If the argument is positive infinity, then the result is
|
||||
* positive infinity.
|
||||
* <li>If the argument is negative infinity, then the result is
|
||||
* positive zero.</ul>
|
||||
* positive zero.
|
||||
* <li>If the argument is zero, then the result is {@code 1.0}.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The computed result must be within 1 ulp of the exact result.
|
||||
* Results must be semi-monotonic.
|
||||
@ -297,7 +329,10 @@ public final class Math {
|
||||
* <li>If the argument is positive infinity, then the result is
|
||||
* positive infinity.
|
||||
* <li>If the argument is positive zero or negative zero, then the
|
||||
* result is negative infinity.</ul>
|
||||
* result is negative infinity.
|
||||
* <li>If the argument is {@code 1.0}, then the result is positive
|
||||
* zero.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The computed result must be within 1 ulp of the exact result.
|
||||
* Results must be semi-monotonic.
|
||||
@ -321,8 +356,10 @@ public final class Math {
|
||||
* positive infinity.
|
||||
* <li>If the argument is positive zero or negative zero, then the
|
||||
* result is negative infinity.
|
||||
* <li> If the argument is equal to 10<sup><i>n</i></sup> for
|
||||
* integer <i>n</i>, then the result is <i>n</i>.
|
||||
* <li>If the argument is equal to 10<sup><i>n</i></sup> for
|
||||
* integer <i>n</i>, then the result is <i>n</i>. In particular,
|
||||
* if the argument is {@code 1.0} (10<sup>0</sup>), then the
|
||||
* result is positive zero.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The computed result must be within 1 ulp of the exact result.
|
||||
@ -529,6 +566,15 @@ public final class Math {
|
||||
* <p>The computed result must be within 2 ulps of the exact result.
|
||||
* Results must be semi-monotonic.
|
||||
*
|
||||
* @apiNote
|
||||
* For <i>y</i> with a positive sign and finite nonzero
|
||||
* <i>x</i>, the exact mathematical value of {@code atan2} is
|
||||
* equal to:
|
||||
* <ul>
|
||||
* <li>If <i>x</i> {@literal >} 0, atan(abs(<i>y</i>/<i>x</i>))
|
||||
* <li>If <i>x</i> {@literal <} 0, π - atan(abs(<i>y</i>/<i>x</i>))
|
||||
* </ul>
|
||||
*
|
||||
* @param y the ordinate coordinate
|
||||
* @param x the abscissa coordinate
|
||||
* @return the <i>theta</i> component of the point
|
||||
@ -660,6 +706,16 @@ public final class Math {
|
||||
* <p>The computed result must be within 1 ulp of the exact result.
|
||||
* Results must be semi-monotonic.
|
||||
*
|
||||
* @apiNote
|
||||
* The special cases definitions of this method differ from the
|
||||
* special case definitions of the IEEE 754 recommended {@code
|
||||
* pow} operation for ±{@code 1.0} raised to an infinite
|
||||
* power. This method treats such cases as indeterminate and
|
||||
* specifies a NaN is returned. The IEEE 754 specification treats
|
||||
* the infinite power as a large integer (large-magnitude
|
||||
* floating-point numbers are numerically integers, specifically
|
||||
* even integers) and therefore specifies {@code 1.0} be returned.
|
||||
*
|
||||
* @param a the base.
|
||||
* @param b the exponent.
|
||||
* @return the value {@code a}<sup>{@code b}</sup>.
|
||||
@ -2113,6 +2169,7 @@ public final class Math {
|
||||
* <li> If either argument is NaN and neither argument is infinite,
|
||||
* then the result is NaN.
|
||||
*
|
||||
* <li> If both arguments are zero, the result is positive zero.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The computed result must be within 1 ulp of the exact
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, 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
|
||||
@ -74,6 +74,15 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
* occurs only with a specific minimum or maximum value and
|
||||
* should be checked against the minimum or maximum as appropriate.
|
||||
*
|
||||
* <h2><a id=Ieee754RecommendedOps>IEEE 754 Recommended
|
||||
* Operations</a></h2>
|
||||
*
|
||||
* The {@link java.lang.Math Math} class discusses how the shared
|
||||
* quality of implementation criteria for selected {@code Math} and
|
||||
* {@code StrictMath} methods <a
|
||||
* href="Math.html#Ieee754RecommendedOps">relate to the IEEE 754
|
||||
* recommended operations</a>.
|
||||
*
|
||||
* @author Joseph D. Darcy
|
||||
* @since 1.3
|
||||
*/
|
||||
@ -126,7 +135,9 @@ public final class StrictMath {
|
||||
/**
|
||||
* Returns the trigonometric cosine of an angle. Special cases:
|
||||
* <ul><li>If the argument is NaN or an infinity, then the
|
||||
* result is NaN.</ul>
|
||||
* result is NaN.
|
||||
* <li>If the argument is zero, then the result is {@code 1.0}.
|
||||
* </ul>
|
||||
*
|
||||
* @param a an angle, in radians.
|
||||
* @return the cosine of the argument.
|
||||
@ -162,7 +173,9 @@ public final class StrictMath {
|
||||
* Returns the arc cosine of a value; the returned angle is in the
|
||||
* range 0.0 through <i>pi</i>. Special case:
|
||||
* <ul><li>If the argument is NaN or its absolute value is greater
|
||||
* than 1, then the result is NaN.</ul>
|
||||
* than 1, then the result is NaN.
|
||||
* <li>If the argument is {@code 1.0}, the result is positive zero.
|
||||
* </ul>
|
||||
*
|
||||
* @param a the value whose arc cosine is to be returned.
|
||||
* @return the arc cosine of the argument.
|
||||
@ -174,7 +187,11 @@ public final class StrictMath {
|
||||
* range -<i>pi</i>/2 through <i>pi</i>/2. Special cases:
|
||||
* <ul><li>If the argument is NaN, then the result is NaN.
|
||||
* <li>If the argument is zero, then the result is a zero with the
|
||||
* same sign as the argument.</ul>
|
||||
* same sign as the argument.
|
||||
* <li>If the argument is {@linkplain Double#isInfinite infinite},
|
||||
* then the result is the closest value to <i>pi</i>/2 with the
|
||||
* same sign as the input.
|
||||
* </ul>
|
||||
*
|
||||
* @param a the value whose arc tangent is to be returned.
|
||||
* @return the arc tangent of the argument.
|
||||
@ -220,7 +237,9 @@ public final class StrictMath {
|
||||
* <li>If the argument is positive infinity, then the result is
|
||||
* positive infinity.
|
||||
* <li>If the argument is negative infinity, then the result is
|
||||
* positive zero.</ul>
|
||||
* positive zero.
|
||||
* <li>If the argument is zero, then the result is {@code 1.0}.
|
||||
* </ul>
|
||||
*
|
||||
* @param a the exponent to raise <i>e</i> to.
|
||||
* @return the value <i>e</i><sup>{@code a}</sup>,
|
||||
@ -238,7 +257,10 @@ public final class StrictMath {
|
||||
* <li>If the argument is positive infinity, then the result is
|
||||
* positive infinity.
|
||||
* <li>If the argument is positive zero or negative zero, then the
|
||||
* result is negative infinity.</ul>
|
||||
* result is negative infinity.
|
||||
* <li>If the argument is {@code 1.0}, then the result is positive
|
||||
* zero.
|
||||
* </ul>
|
||||
*
|
||||
* @param a a value
|
||||
* @return the value ln {@code a}, the natural logarithm of
|
||||
@ -256,8 +278,10 @@ public final class StrictMath {
|
||||
* positive infinity.
|
||||
* <li>If the argument is positive zero or negative zero, then the
|
||||
* result is negative infinity.
|
||||
* <li> If the argument is equal to 10<sup><i>n</i></sup> for
|
||||
* integer <i>n</i>, then the result is <i>n</i>.
|
||||
* <li>If the argument is equal to 10<sup><i>n</i></sup> for
|
||||
* integer <i>n</i>, then the result is <i>n</i>. In particular,
|
||||
* if the argument is {@code 1.0} (10<sup>0</sup>), then the
|
||||
* result is positive zero.
|
||||
* </ul>
|
||||
*
|
||||
* @param a a value
|
||||
@ -517,6 +541,15 @@ public final class StrictMath {
|
||||
* <li>If both arguments are negative infinity, then the result is the
|
||||
* {@code double} value closest to -3*<i>pi</i>/4.</ul>
|
||||
*
|
||||
* @apiNote
|
||||
* For <i>y</i> with a positive sign and finite nonzero
|
||||
* <i>x</i>, the exact mathematical value of {@code atan2} is
|
||||
* equal to:
|
||||
* <ul>
|
||||
* <li>If <i>x</i> {@literal >} 0, atan(abs(<i>y</i>/<i>x</i>))
|
||||
* <li>If <i>x</i> {@literal <} 0, π - atan(abs(<i>y</i>/<i>x</i>))
|
||||
* </ul>
|
||||
*
|
||||
* @param y the ordinate coordinate
|
||||
* @param x the abscissa coordinate
|
||||
* @return the <i>theta</i> component of the point
|
||||
@ -642,6 +675,16 @@ public final class StrictMath {
|
||||
* method if and only if the result of applying the method to the
|
||||
* value is equal to the value.)
|
||||
*
|
||||
* @apiNote
|
||||
* The special cases definitions of this method differ from the
|
||||
* special case definitions of the IEEE 754 recommended {@code
|
||||
* pow} operation for ±{@code 1.0} raised to an infinite
|
||||
* power. This method treats such cases as indeterminate and
|
||||
* specifies a NaN is returned. The IEEE 754 specification treats
|
||||
* the infinite power as a large integer (large-magnitude
|
||||
* floating-point numbers are numerically integers, specifically
|
||||
* even integers) and therefore specifies {@code 1.0} be returned.
|
||||
*
|
||||
* @param a base.
|
||||
* @param b the exponent.
|
||||
* @return the value {@code a}<sup>{@code b}</sup>.
|
||||
@ -1681,6 +1724,7 @@ public final class StrictMath {
|
||||
* <li> If either argument is NaN and neither argument is infinite,
|
||||
* then the result is NaN.
|
||||
*
|
||||
* <li> If both arguments are zero, the result is positive zero.
|
||||
* </ul>
|
||||
*
|
||||
* @param x a value
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011,2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8255368
|
||||
* @bug 8255368 8240632
|
||||
* @summary Tests corner cases of Math.exp
|
||||
*/
|
||||
|
||||
@ -46,6 +46,10 @@ public class ExpCornerCaseTests {
|
||||
double [][] testCases = {
|
||||
{+0x4.0p8, Double.POSITIVE_INFINITY},
|
||||
{+0x2.71p12, Double.POSITIVE_INFINITY},
|
||||
|
||||
// Identified special cases in IEEE 754 exp operation
|
||||
{+0.0, 1.0},
|
||||
{-0.0, 1.0},
|
||||
};
|
||||
|
||||
for (double[] testCase : testCases) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, 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
|
||||
@ -26,7 +26,7 @@
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.RandomFactory
|
||||
* @run main HypotTests
|
||||
* @bug 4851638 4939441 8078672
|
||||
* @bug 4851638 4939441 8078672 8240632
|
||||
* @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed)
|
||||
* @author Joseph D. Darcy
|
||||
* @key randomness
|
||||
@ -198,6 +198,13 @@ public class HypotTests {
|
||||
return failures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify +0.0 is returned if both arguments are zero.
|
||||
*/
|
||||
private static int testHypotZeros() {
|
||||
return testHypotCase(0.0, 0.0, +0.0, 0.0);
|
||||
}
|
||||
|
||||
static int testHypotCase(double input1, double input2, double expected) {
|
||||
return testHypotCase(input1,input2, expected, 1);
|
||||
}
|
||||
@ -237,6 +244,7 @@ public class HypotTests {
|
||||
int failures = 0;
|
||||
|
||||
failures += testHypot();
|
||||
failures += testHypotZeros();
|
||||
|
||||
if (failures > 0) {
|
||||
System.err.println("Testing the hypot incurred "
|
||||
|
130
test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java
Normal file
130
test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2021, 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 8240632
|
||||
* @summary Test special cases of IEEE 754 recommended ops not otherwise tested
|
||||
* @build Tests
|
||||
* @build Ieee754SpecialCaseTests
|
||||
* @run main Ieee754SpecialCaseTests
|
||||
*/
|
||||
|
||||
public class Ieee754SpecialCaseTests {
|
||||
private Ieee754SpecialCaseTests() {throw new AssertionError("No instances for you.");}
|
||||
|
||||
public static void main(String... args) {
|
||||
int failures = 0;
|
||||
|
||||
failures += testSpecialCos();
|
||||
failures += testSpecialAcos();
|
||||
failures += testSpecialAtan();
|
||||
failures += testSpecialLog();
|
||||
|
||||
if (failures > 0) {
|
||||
System.err.printf("Testing special cases incurred %d failures.%n", failures);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
private static int testSpecialCos() {
|
||||
int failures = 0;
|
||||
double [][] testCases = {
|
||||
{+0.0, 1.0},
|
||||
{-0.0, 1.0},
|
||||
};
|
||||
|
||||
for(double[] testCase: testCases) {
|
||||
failures += testCosCase(testCase[0], testCase[1]);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testCosCase(double input, double expected) {
|
||||
int failures = 0;
|
||||
failures += Tests.test("Math.cos", input, Math.cos(input), expected);
|
||||
failures += Tests.test("StrictMath.cos", input, StrictMath.cos(input), expected);
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testSpecialAcos() {
|
||||
int failures = 0;
|
||||
double [][] testCases = {
|
||||
{1.0, 0.0},
|
||||
};
|
||||
|
||||
for(double[] testCase: testCases) {
|
||||
failures += testAcosCase(testCase[0], testCase[1]);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testAcosCase(double input, double expected) {
|
||||
int failures = 0;
|
||||
failures += Tests.test("Math.acos", input, Math.acos(input), expected);
|
||||
failures += Tests.test("StrictMath.acos", input, StrictMath.acos(input), expected);
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testSpecialAtan() {
|
||||
int failures = 0;
|
||||
double [][] testCases = {
|
||||
{Double.POSITIVE_INFINITY, +Math.PI/2.0},
|
||||
{Double.NEGATIVE_INFINITY, -Math.PI/2.0},
|
||||
};
|
||||
|
||||
for(double[] testCase: testCases) {
|
||||
failures += testAtanCase(testCase[0], testCase[1]);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testAtanCase(double input, double expected) {
|
||||
int failures = 0;
|
||||
failures += Tests.test("Math.atan", input, Math.atan(input), expected);
|
||||
failures += Tests.test("StrictMath.atan", input, StrictMath.atan(input), expected);
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testSpecialLog() {
|
||||
int failures = 0;
|
||||
double [][] testCases = {
|
||||
{1.0, +0.0},
|
||||
};
|
||||
|
||||
for(double[] testCase: testCases) {
|
||||
failures += testLogCase(testCase[0], testCase[1]);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
private static int testLogCase(double input, double expected) {
|
||||
int failures = 0;
|
||||
failures += Tests.test("Math.log", input, Math.log(input), expected);
|
||||
failures += Tests.test("StrictMath.log", input, StrictMath.log(input), expected);
|
||||
return failures;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user