diff --git a/src/main/java/org/apache/commons/jxpath/ri/compiler/CoreOperationCompare.java b/src/main/java/org/apache/commons/jxpath/ri/compiler/CoreOperationCompare.java index ba0b9ea2e..0248c38d4 100644 --- a/src/main/java/org/apache/commons/jxpath/ri/compiler/CoreOperationCompare.java +++ b/src/main/java/org/apache/commons/jxpath/ri/compiler/CoreOperationCompare.java @@ -137,16 +137,9 @@ protected boolean equal(Object l, Object r) { if (l instanceof Boolean || r instanceof Boolean) { result = l == r || InfoSetUtil.booleanValue(l) == InfoSetUtil.booleanValue(r); } else if (l instanceof Number || r instanceof Number) { - // if either side is NaN, no comparison returns true: - final double ld = InfoSetUtil.doubleValue(l); - if (Double.isNaN(ld)) { - return false; - } - final double rd = InfoSetUtil.doubleValue(r); - if (Double.isNaN(rd)) { - return false; - } - result = ld == rd; + // Numbers are compared per IEEE 754 (XPath 1.0 section 3.4): NaN is not + // equal to anything, including itself, so "=" is false and "!=" is true. + result = InfoSetUtil.doubleValue(l) == InfoSetUtil.doubleValue(r); } else { if (l instanceof String || r instanceof String) { l = InfoSetUtil.stringValue(l); diff --git a/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreOperationTest.java b/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreOperationTest.java index 7c47790b3..7e960ca87 100644 --- a/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreOperationTest.java +++ b/src/test/java/org/apache/commons/jxpath/ri/compiler/CoreOperationTest.java @@ -105,21 +105,24 @@ void testNan() { assertXPathValue(context, "$nan <= $nan", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan >= $nan and $nan <= $nan", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan = $nan", Boolean.FALSE, Boolean.class); - assertXPathValue(context, "$nan != $nan", Boolean.FALSE, Boolean.class); + assertXPathValue(context, "$nan != $nan", Boolean.TRUE, Boolean.class); assertXPathValue(context, "$nan > 0", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan < 0", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan >= 0", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan <= 0", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan >= 0 and $nan <= 0", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan = 0", Boolean.FALSE, Boolean.class); - assertXPathValue(context, "$nan != 0", Boolean.FALSE, Boolean.class); + assertXPathValue(context, "$nan != 0", Boolean.TRUE, Boolean.class); assertXPathValue(context, "$nan > 1", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan < 1", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan >= 1", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan <= 1", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan >= 1 and $nan <= 1", Boolean.FALSE, Boolean.class); assertXPathValue(context, "$nan = 1", Boolean.FALSE, Boolean.class); - assertXPathValue(context, "$nan != 1", Boolean.FALSE, Boolean.class); + assertXPathValue(context, "$nan != 1", Boolean.TRUE, Boolean.class); + assertXPathValue(context, "number('foo') = 1", Boolean.FALSE, Boolean.class); + assertXPathValue(context, "number('foo') != 1", Boolean.TRUE, Boolean.class); + assertXPathValue(context, "number('foo') != number('foo')", Boolean.TRUE, Boolean.class); } @Test