Details
Description
A DESCRIPTION OF THE REQUEST :
Please add support for static nextValue(), previousValue() methods in java.lang.Float and java.lang.Double classes.
JUSTIFICATION :
Using the static ulp() method to compute previous and next value with a difference binary operation does not return the expected value, due to roundoff errors if the magnitude of the returned value changes:
* if the original value x is negative infinite, adding ulp(x) does not return MAX_VALUE;
* if the original value x is positive infinite, subtracting ulp(x) does not return MAX_VALUE;
* if the magnitude decreases (exponent decremented) by adding or subtracting ulp(x), the returned value as skipped over the expected nearest representable value.
* if the magnitude must increase (exponent incremented) by adding or subtracting ulp(x), this is not guaranteed due to the current rounding mode JIT (in non strictfp mode, if it is not rounding to nearest even) the returned value as skipped over the expected nearest representable value; it may even happen that the infinite value is not returned.
Between each value x and the next or previous representable float (or double) the difference:
* is 1 *ulp(x) for most values, but
* it should be 2*ulp(x) if the magnitude grows (exponent is incremented),
* it should be infinite if the magnitude becomes infinite (exponent is incremented to the infinite value)
* it should be null if this is just a change of sign for zeroes.
The correct code to do that is tricky, and should better be supported and implemented in the java.lang.Float and java.lang.Double classes by new static methods.
These methods are needed to test allowed differences in highprecision computing, where at most 1 bit of difference is allowed in the significand, and not just 2*ulp(x) (because it is wrong within 1 bit of difference from infinite values). The 1*ulp(x) roundoff error is unreachable except with strict IEEE754 rounding mode to nearest even.
An implementation follows. It is simple to test.
 BEGIN SOURCE 
public class Test {
static float previousValue(float f) {
if (Float.isNaN(f)  f == Float.NEGATIVE_INFINITY)
return f;
if (f == 0.0f)
return 0.0f;
return Float.intBitsToFloat(Float.floatToIntBits(f)  (f < 0 ? 1 : 1));
}
static float nextValue(float f) {
if (Float.isNaN(f)  f == Float.POSITIVE_INFINITY)
return f;
if (f == 0.0f)
return 0.0f;
return Float.intBitsToFloat(Float.floatToIntBits(f) + (f < 0 ? 1 : 1));
}
static double previousValue(double d) {
if (Double.isNaN(d)  d == Double.NEGATIVE_INFINITY)
return d;
if (d == 0.0d)
return 0.0d;
return Double.longBitsToDouble(Double.doubleToLongBits(d)  (d < 0 ? 1 : 1));
}
static double nextValue(double d) {
if (Double.isNaN(d)  d == Double.POSITIVE_INFINITY)
return d;
if (d == 0.0d)
return 0.0d;
return Double.longBitsToDouble(Double.doubleToLongBits(d) + (d < 0 ? 1 : 1));
}
}
 END SOURCE 
Please add support for static nextValue(), previousValue() methods in java.lang.Float and java.lang.Double classes.
JUSTIFICATION :
Using the static ulp() method to compute previous and next value with a difference binary operation does not return the expected value, due to roundoff errors if the magnitude of the returned value changes:
* if the original value x is negative infinite, adding ulp(x) does not return MAX_VALUE;
* if the original value x is positive infinite, subtracting ulp(x) does not return MAX_VALUE;
* if the magnitude decreases (exponent decremented) by adding or subtracting ulp(x), the returned value as skipped over the expected nearest representable value.
* if the magnitude must increase (exponent incremented) by adding or subtracting ulp(x), this is not guaranteed due to the current rounding mode JIT (in non strictfp mode, if it is not rounding to nearest even) the returned value as skipped over the expected nearest representable value; it may even happen that the infinite value is not returned.
Between each value x and the next or previous representable float (or double) the difference:
* is 1 *ulp(x) for most values, but
* it should be 2*ulp(x) if the magnitude grows (exponent is incremented),
* it should be infinite if the magnitude becomes infinite (exponent is incremented to the infinite value)
* it should be null if this is just a change of sign for zeroes.
The correct code to do that is tricky, and should better be supported and implemented in the java.lang.Float and java.lang.Double classes by new static methods.
These methods are needed to test allowed differences in highprecision computing, where at most 1 bit of difference is allowed in the significand, and not just 2*ulp(x) (because it is wrong within 1 bit of difference from infinite values). The 1*ulp(x) roundoff error is unreachable except with strict IEEE754 rounding mode to nearest even.
An implementation follows. It is simple to test.
 BEGIN SOURCE 
public class Test {
static float previousValue(float f) {
if (Float.isNaN(f)  f == Float.NEGATIVE_INFINITY)
return f;
if (f == 0.0f)
return 0.0f;
return Float.intBitsToFloat(Float.floatToIntBits(f)  (f < 0 ? 1 : 1));
}
static float nextValue(float f) {
if (Float.isNaN(f)  f == Float.POSITIVE_INFINITY)
return f;
if (f == 0.0f)
return 0.0f;
return Float.intBitsToFloat(Float.floatToIntBits(f) + (f < 0 ? 1 : 1));
}
static double previousValue(double d) {
if (Double.isNaN(d)  d == Double.NEGATIVE_INFINITY)
return d;
if (d == 0.0d)
return 0.0d;
return Double.longBitsToDouble(Double.doubleToLongBits(d)  (d < 0 ? 1 : 1));
}
static double nextValue(double d) {
if (Double.isNaN(d)  d == Double.POSITIVE_INFINITY)
return d;
if (d == 0.0d)
return 0.0d;
return Double.longBitsToDouble(Double.doubleToLongBits(d) + (d < 0 ? 1 : 1));
}
}
 END SOURCE 
Attachments
Issue Links
 relates to

JDK4826652 Add copySign, nextAfter, nextUp, scalb, ilogb, etc. to Math and StrictMath
 Resolved