Thanks, Joe. This looks like progress. Feel free to ignore quibbles. Quibble: "guaranteed" may be true in practice, but longBitsToDouble is technically permitted to reset the sign bit back to 1 if the hardware is hostile. Because of this, I would simply remove the word "guaranteed".
Should the non-intrinsified java bodies of abs be updated to match the updated spec? It would promote consistency between spec and interpreter and jit, so I would say yes, but this change is complete without any code updates. Quibble: I would use (the equivalent) ~(1 << 31) & for the float case and ~(1L << 63) & for the double case On Sat, Aug 20, 2016 at 11:55 AM, joe darcy <joe.da...@oracle.com> wrote: > Hello, > > Please review the doc-only patch below to address > > JDK-8164524: Correct inconsistencies in floating-point abs spec > > In brief, Martin noted in JDK-8164199 that a close reading of the > specification of the Math and StrictMath floating-point abs methods reveals > some inconsistencies in the text of the specification versus the > operational semantics of the sample code in term of NaN handling. > > To resolve this, the sample code is slightly modified and demoted to > informative rather than normative text. > > The core of the edit is changing > > Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a)) > > to > > Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a)) > > that is the "raw" floating-point => integral conversion rather than the > "cooked" one which has tighter behavioral requirements around different NaN > values, analogous changes for the double cases. > > (I don't think the request to mandate particular NaN behavior in > JDK-8164199 is warranted; see the comments in that bug for a longer > discussion.) > > Thanks, > > -Joe > > Since the float and double abs methods appears both in java.lang.Math and > java.lang.StrictMath, the same edits are made multiple times. > > diff -r 9287101b5f49 src/java.base/share/classes/java/lang/Math.java > --- a/src/java.base/share/classes/java/lang/Math.java Tue Aug 09 > 07:50:26 2016 -0700 > +++ b/src/java.base/share/classes/java/lang/Math.java Sat Aug 20 > 11:47:22 2016 -0700 > @@ -1370,8 +1370,12 @@ > * result is positive zero. > * <li>If the argument is infinite, the result is positive infinity. > * <li>If the argument is NaN, the result is NaN.</ul> > - * In other words, the result is the same as the value of the > expression: > - * <p>{@code Float.intBitsToFloat(0x7fffffff & > Float.floatToIntBits(a))} > + * > + * @apiNote As implied by the above, one valid implementation of > + * this method is given by the expression below which computes a > + * {@code float} with the same exponent and significand as the > + * argument but with a guaranteed positive sign bit: <br> > + * {@code Float.intBitsToFloat(0x7fffffff & > Float.floatToRawIntBits(a))} > * > * @param a the argument whose absolute value is to be determined > * @return the absolute value of the argument. > @@ -1389,8 +1393,12 @@ > * is positive zero. > * <li>If the argument is infinite, the result is positive infinity. > * <li>If the argument is NaN, the result is NaN.</ul> > - * In other words, the result is the same as the value of the > expression: > - * <p>{@code Double.longBitsToDouble((Doubl > e.doubleToLongBits(a)<<1)>>>1)} > + * > + * @apiNote As implied by the above, one valid implementation of > + * this method is given by the expression below which computes a > + * {@code double} with the same exponent and significand as the > + * argument but with a guaranteed positive sign bit: <br> > + * {@code Double.longBitsToDouble((Doubl > e.doubleToRawLongBits(a)<<1)>>>1)} > * > * @param a the argument whose absolute value is to be determined > * @return the absolute value of the argument. > diff -r 9287101b5f49 src/java.base/share/classes/java/lang/StrictMath.java > --- a/src/java.base/share/classes/java/lang/StrictMath.java Tue Aug 09 > 07:50:26 2016 -0700 > +++ b/src/java.base/share/classes/java/lang/StrictMath.java Sat Aug 20 > 11:47:22 2016 -0700 > @@ -1070,8 +1070,12 @@ > * result is positive zero. > * <li>If the argument is infinite, the result is positive infinity. > * <li>If the argument is NaN, the result is NaN.</ul> > - * In other words, the result is the same as the value of the > expression: > - * <p>{@code Float.intBitsToFloat(0x7fffffff & > Float.floatToIntBits(a))} > + * > + * @apiNote As implied by the above, one valid implementation of > + * this method is given by the expression below which computes a > + * {@code float} with the same exponent and significand as the > + * argument but with a guaranteed positive sign bit: <br> > + * {@code Float.intBitsToFloat(0x7fffffff & > Float.floatToRawIntBits(a))} > * > * @param a the argument whose absolute value is to be determined > * @return the absolute value of the argument. > @@ -1089,8 +1093,12 @@ > * is positive zero. > * <li>If the argument is infinite, the result is positive infinity. > * <li>If the argument is NaN, the result is NaN.</ul> > - * In other words, the result is the same as the value of the > expression: > - * <p>{@code Double.longBitsToDouble((Doubl > e.doubleToLongBits(a)<<1)>>>1)} > + * > + * @apiNote As implied by the above, one valid implementation of > + * this method is given by the expression below which computes a > + * {@code double} with the same exponent and significand as the > + * argument but with a guaranteed positive sign bit: <br> > + * {@code Double.longBitsToDouble((Doubl > e.doubleToRawLongBits(a)<<1)>>>1)} > * > * @param a the argument whose absolute value is to be determined > * @return the absolute value of the argument. > >