Skip to content

Commit 2fd8ed0

Browse files
committedFeb 8, 2021
8240632: Note differences between IEEE 754-2019 math lib special cases and java.lang.Math
Reviewed-by: bpb
1 parent ace8f94 commit 2fd8ed0

File tree

5 files changed

+264
-21
lines changed

5 files changed

+264
-21
lines changed
 

‎src/java.base/share/classes/java/lang/Math.java

+66-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
3737
* square root, and trigonometric functions.
3838
*
3939
* <p>Unlike some of the numeric methods of class
40-
* {@code StrictMath}, all implementations of the equivalent
40+
* {@link java.lang.StrictMath StrictMath}, all implementations of the equivalent
4141
* functions of class {@code Math} are not defined to return the
4242
* bit-for-bit same results. This relaxation permits
4343
* better-performing implementations where strict reproducibility is
@@ -99,6 +99,28 @@
9999
* occurs only with a specific minimum or maximum value and
100100
* should be checked against the minimum or maximum as appropriate.
101101
*
102+
* <h2><a id=Ieee754RecommendedOps>IEEE 754 Recommended
103+
* Operations</a></h2>
104+
*
105+
* The 2019 revision of the IEEE 754 floating-point standard includes
106+
* a section of recommended operations and the semantics of those
107+
* operations if they are included in a programming environment. The
108+
* recommended operations present in this class include {@link sin
109+
* sin}, {@link cos cos}, {@link tan tan}, {@link asin asin}, {@link
110+
* acos acos}, {@link atan atan}, {@link exp exp}, {@link expm1
111+
* expm1}, {@link log log}, {@link log10 log10}, {@link log1p log1p},
112+
* {@link sinh sinh}, {@link cosh cosh}, {@link tanh tanh}, {@link
113+
* hypot hypot}, and {@link pow pow}. (The {@link sqrt sqrt}
114+
* operation is a required part of IEEE 754 from a different section
115+
* of the standard.) The special case behavior of the recommended
116+
* operations generally follows the guidance of the IEEE 754
117+
* standard. However, the {@code pow} method defines different
118+
* behavior for some arguments, as noted in its {@linkplain pow
119+
* specification}. The IEEE 754 standard defines its operations to be
120+
* correctly rounded, which is a more stringent quality of
121+
* implementation condition than required for most of the methods in
122+
* question that are also included in this class.
123+
*
102124
* @author Joseph D. Darcy
103125
* @since 1.0
104126
*/
@@ -156,7 +178,9 @@ public static double sin(double a) {
156178
/**
157179
* Returns the trigonometric cosine of an angle. Special cases:
158180
* <ul><li>If the argument is NaN or an infinity, then the
159-
* result is NaN.</ul>
181+
* result is NaN.
182+
* <li>If the argument is zero, then the result is {@code 1.0}.
183+
*</ul>
160184
*
161185
* <p>The computed result must be within 1 ulp of the exact result.
162186
* Results must be semi-monotonic.
@@ -209,7 +233,9 @@ public static double asin(double a) {
209233
* Returns the arc cosine of a value; the returned angle is in the
210234
* range 0.0 through <i>pi</i>. Special case:
211235
* <ul><li>If the argument is NaN or its absolute value is greater
212-
* than 1, then the result is NaN.</ul>
236+
* than 1, then the result is NaN.
237+
* <li>If the argument is {@code 1.0}, the result is positive zero.
238+
* </ul>
213239
*
214240
* <p>The computed result must be within 1 ulp of the exact result.
215241
* Results must be semi-monotonic.
@@ -226,7 +252,11 @@ public static double acos(double a) {
226252
* range -<i>pi</i>/2 through <i>pi</i>/2. Special cases:
227253
* <ul><li>If the argument is NaN, then the result is NaN.
228254
* <li>If the argument is zero, then the result is a zero with the
229-
* same sign as the argument.</ul>
255+
* same sign as the argument.
256+
* <li>If the argument is {@linkplain Double#isInfinite infinite},
257+
* then the result is the closest value to <i>pi</i>/2 with the
258+
* same sign as the input.
259+
* </ul>
230260
*
231261
* <p>The computed result must be within 1 ulp of the exact result.
232262
* Results must be semi-monotonic.
@@ -275,7 +305,9 @@ public static double toDegrees(double angrad) {
275305
* <li>If the argument is positive infinity, then the result is
276306
* positive infinity.
277307
* <li>If the argument is negative infinity, then the result is
278-
* positive zero.</ul>
308+
* positive zero.
309+
* <li>If the argument is zero, then the result is {@code 1.0}.
310+
* </ul>
279311
*
280312
* <p>The computed result must be within 1 ulp of the exact result.
281313
* Results must be semi-monotonic.
@@ -297,7 +329,10 @@ public static double exp(double a) {
297329
* <li>If the argument is positive infinity, then the result is
298330
* positive infinity.
299331
* <li>If the argument is positive zero or negative zero, then the
300-
* result is negative infinity.</ul>
332+
* result is negative infinity.
333+
* <li>If the argument is {@code 1.0}, then the result is positive
334+
* zero.
335+
* </ul>
301336
*
302337
* <p>The computed result must be within 1 ulp of the exact result.
303338
* Results must be semi-monotonic.
@@ -321,8 +356,10 @@ public static double log(double a) {
321356
* positive infinity.
322357
* <li>If the argument is positive zero or negative zero, then the
323358
* result is negative infinity.
324-
* <li> If the argument is equal to 10<sup><i>n</i></sup> for
325-
* integer <i>n</i>, then the result is <i>n</i>.
359+
* <li>If the argument is equal to 10<sup><i>n</i></sup> for
360+
* integer <i>n</i>, then the result is <i>n</i>. In particular,
361+
* if the argument is {@code 1.0} (10<sup>0</sup>), then the
362+
* result is positive zero.
326363
* </ul>
327364
*
328365
* <p>The computed result must be within 1 ulp of the exact result.
@@ -529,6 +566,15 @@ public static double rint(double a) {
529566
* <p>The computed result must be within 2 ulps of the exact result.
530567
* Results must be semi-monotonic.
531568
*
569+
* @apiNote
570+
* For <i>y</i> with a positive sign and finite nonzero
571+
* <i>x</i>, the exact mathematical value of {@code atan2} is
572+
* equal to:
573+
* <ul>
574+
* <li>If <i>x</i> {@literal >} 0, atan(abs(<i>y</i>/<i>x</i>))
575+
* <li>If <i>x</i> {@literal <} 0, &pi; - atan(abs(<i>y</i>/<i>x</i>))
576+
* </ul>
577+
*
532578
* @param y the ordinate coordinate
533579
* @param x the abscissa coordinate
534580
* @return the <i>theta</i> component of the point
@@ -660,6 +706,16 @@ public static double atan2(double y, double x) {
660706
* <p>The computed result must be within 1 ulp of the exact result.
661707
* Results must be semi-monotonic.
662708
*
709+
* @apiNote
710+
* The special cases definitions of this method differ from the
711+
* special case definitions of the IEEE 754 recommended {@code
712+
* pow} operation for &plusmn;{@code 1.0} raised to an infinite
713+
* power. This method treats such cases as indeterminate and
714+
* specifies a NaN is returned. The IEEE 754 specification treats
715+
* the infinite power as a large integer (large-magnitude
716+
* floating-point numbers are numerically integers, specifically
717+
* even integers) and therefore specifies {@code 1.0} be returned.
718+
*
663719
* @param a the base.
664720
* @param b the exponent.
665721
* @return the value {@code a}<sup>{@code b}</sup>.
@@ -2113,6 +2169,7 @@ public static double tanh(double x) {
21132169
* <li> If either argument is NaN and neither argument is infinite,
21142170
* then the result is NaN.
21152171
*
2172+
* <li> If both arguments are zero, the result is positive zero.
21162173
* </ul>
21172174
*
21182175
* <p>The computed result must be within 1 ulp of the exact

‎src/java.base/share/classes/java/lang/StrictMath.java

+52-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -74,6 +74,15 @@
7474
* occurs only with a specific minimum or maximum value and
7575
* should be checked against the minimum or maximum as appropriate.
7676
*
77+
* <h2><a id=Ieee754RecommendedOps>IEEE 754 Recommended
78+
* Operations</a></h2>
79+
*
80+
* The {@link java.lang.Math Math} class discusses how the shared
81+
* quality of implementation criteria for selected {@code Math} and
82+
* {@code StrictMath} methods <a
83+
* href="Math.html#Ieee754RecommendedOps">relate to the IEEE 754
84+
* recommended operations</a>.
85+
*
7786
* @author Joseph D. Darcy
7887
* @since 1.3
7988
*/
@@ -126,7 +135,9 @@ private StrictMath() {}
126135
/**
127136
* Returns the trigonometric cosine of an angle. Special cases:
128137
* <ul><li>If the argument is NaN or an infinity, then the
129-
* result is NaN.</ul>
138+
* result is NaN.
139+
* <li>If the argument is zero, then the result is {@code 1.0}.
140+
* </ul>
130141
*
131142
* @param a an angle, in radians.
132143
* @return the cosine of the argument.
@@ -162,7 +173,9 @@ private StrictMath() {}
162173
* Returns the arc cosine of a value; the returned angle is in the
163174
* range 0.0 through <i>pi</i>. Special case:
164175
* <ul><li>If the argument is NaN or its absolute value is greater
165-
* than 1, then the result is NaN.</ul>
176+
* than 1, then the result is NaN.
177+
* <li>If the argument is {@code 1.0}, the result is positive zero.
178+
* </ul>
166179
*
167180
* @param a the value whose arc cosine is to be returned.
168181
* @return the arc cosine of the argument.
@@ -174,7 +187,11 @@ private StrictMath() {}
174187
* range -<i>pi</i>/2 through <i>pi</i>/2. Special cases:
175188
* <ul><li>If the argument is NaN, then the result is NaN.
176189
* <li>If the argument is zero, then the result is a zero with the
177-
* same sign as the argument.</ul>
190+
* same sign as the argument.
191+
* <li>If the argument is {@linkplain Double#isInfinite infinite},
192+
* then the result is the closest value to <i>pi</i>/2 with the
193+
* same sign as the input.
194+
* </ul>
178195
*
179196
* @param a the value whose arc tangent is to be returned.
180197
* @return the arc tangent of the argument.
@@ -220,7 +237,9 @@ public static strictfp double toDegrees(double angrad) {
220237
* <li>If the argument is positive infinity, then the result is
221238
* positive infinity.
222239
* <li>If the argument is negative infinity, then the result is
223-
* positive zero.</ul>
240+
* positive zero.
241+
* <li>If the argument is zero, then the result is {@code 1.0}.
242+
* </ul>
224243
*
225244
* @param a the exponent to raise <i>e</i> to.
226245
* @return the value <i>e</i><sup>{@code a}</sup>,
@@ -238,7 +257,10 @@ public static double exp(double a) {
238257
* <li>If the argument is positive infinity, then the result is
239258
* positive infinity.
240259
* <li>If the argument is positive zero or negative zero, then the
241-
* result is negative infinity.</ul>
260+
* result is negative infinity.
261+
* <li>If the argument is {@code 1.0}, then the result is positive
262+
* zero.
263+
* </ul>
242264
*
243265
* @param a a value
244266
* @return the value ln&nbsp;{@code a}, the natural logarithm of
@@ -256,8 +278,10 @@ public static double exp(double a) {
256278
* positive infinity.
257279
* <li>If the argument is positive zero or negative zero, then the
258280
* result is negative infinity.
259-
* <li> If the argument is equal to 10<sup><i>n</i></sup> for
260-
* integer <i>n</i>, then the result is <i>n</i>.
281+
* <li>If the argument is equal to 10<sup><i>n</i></sup> for
282+
* integer <i>n</i>, then the result is <i>n</i>. In particular,
283+
* if the argument is {@code 1.0} (10<sup>0</sup>), then the
284+
* result is positive zero.
261285
* </ul>
262286
*
263287
* @param a a value
@@ -517,6 +541,15 @@ public static double rint(double a) {
517541
* <li>If both arguments are negative infinity, then the result is the
518542
* {@code double} value closest to -3*<i>pi</i>/4.</ul>
519543
*
544+
* @apiNote
545+
* For <i>y</i> with a positive sign and finite nonzero
546+
* <i>x</i>, the exact mathematical value of {@code atan2} is
547+
* equal to:
548+
* <ul>
549+
* <li>If <i>x</i> {@literal >} 0, atan(abs(<i>y</i>/<i>x</i>))
550+
* <li>If <i>x</i> {@literal <} 0, &pi; - atan(abs(<i>y</i>/<i>x</i>))
551+
* </ul>
552+
*
520553
* @param y the ordinate coordinate
521554
* @param x the abscissa coordinate
522555
* @return the <i>theta</i> component of the point
@@ -642,6 +675,16 @@ public static double rint(double a) {
642675
* method if and only if the result of applying the method to the
643676
* value is equal to the value.)
644677
*
678+
* @apiNote
679+
* The special cases definitions of this method differ from the
680+
* special case definitions of the IEEE 754 recommended {@code
681+
* pow} operation for &plusmn;{@code 1.0} raised to an infinite
682+
* power. This method treats such cases as indeterminate and
683+
* specifies a NaN is returned. The IEEE 754 specification treats
684+
* the infinite power as a large integer (large-magnitude
685+
* floating-point numbers are numerically integers, specifically
686+
* even integers) and therefore specifies {@code 1.0} be returned.
687+
*
645688
* @param a base.
646689
* @param b the exponent.
647690
* @return the value {@code a}<sup>{@code b}</sup>.
@@ -1681,6 +1724,7 @@ public static float signum(float f) {
16811724
* <li> If either argument is NaN and neither argument is infinite,
16821725
* then the result is NaN.
16831726
*
1727+
* <li> If both arguments are zero, the result is positive zero.
16841728
* </ul>
16851729
*
16861730
* @param x a value

‎test/jdk/java/lang/Math/ExpCornerCaseTests.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011,2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8255368
26+
* @bug 8255368 8240632
2727
* @summary Tests corner cases of Math.exp
2828
*/
2929

@@ -46,6 +46,10 @@ private static int testExpCornerCases() {
4646
double [][] testCases = {
4747
{+0x4.0p8, Double.POSITIVE_INFINITY},
4848
{+0x2.71p12, Double.POSITIVE_INFINITY},
49+
50+
// Identified special cases in IEEE 754 exp operation
51+
{+0.0, 1.0},
52+
{-0.0, 1.0},
4953
};
5054

5155
for (double[] testCase : testCases) {

‎test/jdk/java/lang/Math/HypotTests.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
2626
* @library /test/lib
2727
* @build jdk.test.lib.RandomFactory
2828
* @run main HypotTests
29-
* @bug 4851638 4939441 8078672
29+
* @bug 4851638 4939441 8078672 8240632
3030
* @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed)
3131
* @author Joseph D. Darcy
3232
* @key randomness
@@ -198,6 +198,13 @@ static int testHypot() {
198198
return failures;
199199
}
200200

201+
/**
202+
* Verify +0.0 is returned if both arguments are zero.
203+
*/
204+
private static int testHypotZeros() {
205+
return testHypotCase(0.0, 0.0, +0.0, 0.0);
206+
}
207+
201208
static int testHypotCase(double input1, double input2, double expected) {
202209
return testHypotCase(input1,input2, expected, 1);
203210
}
@@ -237,6 +244,7 @@ public static void main(String argv[]) {
237244
int failures = 0;
238245

239246
failures += testHypot();
247+
failures += testHypotZeros();
240248

241249
if (failures > 0) {
242250
System.err.println("Testing the hypot incurred "

0 commit comments

Comments
 (0)
Failed to load comments.