Optimizations of Math.next{After,Up}({float,double})

XMLWordPrintable

Details

• Enhancement
• Resolution: Fixed
• P4
• 9
• b13

Description

For nextAfter(double,double) (same for float version), instead of testing NaN-ity right away,
we can test most common (or at least regular) cases first:

public static double nextAfter(double start, double direction) {
// Balancing out by branching to going-down case first,
// for it is heavier than going-up case (test if start is +-0.0).
if (start > direction) {
// Going down.
if (start == 0.0d) {
// start is +0.0 or -0.0
return -Double.MIN_VALUE;
}
final long transducer = Double.doubleToRawLongBits(start);
assert transducer != 0L;
return Double.longBitsToDouble(transducer + ((transducer > 0L) ? -1L:1L));
} else if (start < direction) {
// Going up.
// Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
// then bitwise convert start to integer.
final long transducer = Double.doubleToRawLongBits(start + 0.0d);
return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L:-1L));
} else if (start == direction) {
return direction;
} else { // start and/or direction is NaN
return start + direction;
}
}

Same for nextUp(double) and float version (also, testing transducer >= 0L
instead of d >= 0.0D seems to help):
public static double nextUp(double d) {
if (d < Double.POSITIVE_INFINITY) {
final long transducer = Double.doubleToRawLongBits(d + 0.0D);
return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L:-1L));
} else { // d is NaN or +Infinity
return d;
}
}

Reference: http://mail.openjdk.java.net/pipermail/core-libs-dev/2011-September/007708.html

People

Brian Burkhalter
Brian Burkhalter