Attached is a patch that improves the performance of an Float/Double
compare by exploiting information carried in their bit integer/long
versions sign bit. It removes one comparison from the normal path, as
well as making other compares with ints/longs. When sorting an array of
floats this can yield a little under a 8% speed up on a Pentium 4.
There's a thread discussing whether this is a good or bad idea on the
main mailing list, but so far I'm merrily talking to myself :-)
Ian
--- java/lang/Double.java 2006-12-10 20:25:44.000000000 +0000
+++ java/lang/Double.java 2007-06-30 22:21:39.986100000 +0100
@@ -587,16 +587,17 @@
*/
public static int compare(double x, double y)
{
- if (isNaN(x))
- return isNaN(y) ? 0 : 1;
- if (isNaN(y))
- return -1;
- // recall that 0.0 == -0.0, so we convert to infinites and try again
- if (x == 0 && y == 0)
- return (int) (1 / x - 1 / y);
- if (x == y)
- return 0;
-
- return x > y ? 1 : -1;
+ long lx = doubleToLongBits(x);
+ long ly = doubleToLongBits(y);
+ if (lx == ly) return 0;
+ if (isNaN(x)) return 1;
+ if (isNaN(y)) return -1;
+ int lx_sign = (int)(lx>>63);
+ int ly_sign = (int)(ly>>63);
+ if (lx_sign == ly_sign) {
+ return x > y ? 1 : -1;
+ } else {
+ return lx_sign - ly_sign;
+ }
}
}
--- java/lang/Float.java 2006-12-10 20:25:44.000000000 +0000
+++ java/lang/Float.java 2007-06-30 22:10:46.099648000 +0100
@@ -596,16 +596,17 @@
*/
public static int compare(float x, float y)
{
- if (isNaN(x))
- return isNaN(y) ? 0 : 1;
- if (isNaN(y))
- return -1;
- // recall that 0.0 == -0.0, so we convert to infinities and try again
- if (x == 0 && y == 0)
- return (int) (1 / x - 1 / y);
- if (x == y)
- return 0;
-
- return x > y ? 1 : -1;
+ int ix = floatToIntBits(x);
+ int iy = floatToIntBits(y);
+ if (ix == iy) return 0;
+ if (isNaN(x)) return 1;
+ if (isNaN(y)) return -1;
+ int ix_sign = ix>>31;
+ int iy_sign = iy>>31;
+ if (ix_sign == iy_sign) {
+ return x > y ? 1 : -1;
+ } else {
+ return ix_sign - iy_sign;
+ }
}
}