diff --git a/lucene/src/java/org/apache/lucene/util/NumericUtils.java b/lucene/src/java/org/apache/lucene/util/NumericUtils.java index 232461d..7426e49 100644 --- a/lucene/src/java/org/apache/lucene/util/NumericUtils.java +++ b/lucene/src/java/org/apache/lucene/util/NumericUtils.java @@ -265,7 +265,17 @@ public final class NumericUtils { */ public static int floatToSortableInt(float val) { int f = Float.floatToRawIntBits(val); - if (f<0) f ^= 0x7fffffff; + + // Canonicalize NaN ranges. I assume this check will be faster here than + // (v == v) == false on the FPU? We don't distinguish between different + // flavors of NaNs here (see http://en.wikipedia.org/wiki/NaN). I guess + // in Java this doesn't matter much anyway. + if ((f & 0x7fffffff) > 0x7f800000) { + // canonical "quiet NaN" + f = 0x7fc00000; + } else { + if (f < 0) f ^= 0x7fffffff; + } return f; } diff --git a/lucene/src/test/org/apache/lucene/util/NumericUtilsTest.java b/lucene/src/test/org/apache/lucene/util/NumericUtilsTest.java new file mode 100644 index 0000000..cf537b1 --- /dev/null +++ b/lucene/src/test/org/apache/lucene/util/NumericUtilsTest.java @@ -0,0 +1,20 @@ +package org.apache.lucene.util; + +public class NumericUtilsTest extends LuceneTestCase { + public void testSortableFloat() { + float [] nans = { + Float.intBitsToFloat(0x7f800001), + Float.intBitsToFloat(0x7fffffff), + Float.intBitsToFloat(0xff800001), + Float.intBitsToFloat(0xffffffff) + }; + + int plusInf = NumericUtils.floatToSortableInt(Float.POSITIVE_INFINITY); + for (float nan : nans) { + assertTrue(Float.isNaN(nan)); + int sortable = NumericUtils.floatToSortableInt(nan); + assertTrue("Float not sorted correctly: " + nan + ", int repr: " + + sortable + ", positive inf.: " + plusInf, sortable > plusInf); + } + } +}