diff --git a/basex-core/src/main/java/org/basex/query/value/item/ANum.java b/basex-core/src/main/java/org/basex/query/value/item/ANum.java
index e3a27c0218..b4be8b8821 100644
--- a/basex-core/src/main/java/org/basex/query/value/item/ANum.java
+++ b/basex-core/src/main/java/org/basex/query/value/item/ANum.java
@@ -83,6 +83,38 @@ public final boolean atomicEqual(final Item item) throws QueryException {
*/
protected abstract float flt();
+ /**
+ * Converts an item to decimal, if it is untyped, or to double if decimal conversion cannot
+ * succeed.
+ * @param item item
+ * @param ii input info
+ * @return converted item (unchanged if not untyped, otherwise decimal or double)
+ * @throws QueryException query exception
+ */
+ protected static Item untypedToDec(final Item item, final InputInfo ii) throws QueryException {
+ if(!item.type.isUntyped()) return item;
+ final byte[] token = item.string(ii);
+ for(final byte b : token) if(b == 'e' || b == 'E' || b == 'N') return Dbl.get(item.dbl(ii));
+ return Dec.get(item.dec(ii));
+ }
+
+ /**
+ * Converts an item to float, if it is untyped, or to double if float conversion fails.
+ * @param item item
+ * @param ii input info
+ * @return converted item (unchanged if not untyped, otherwise float or double)
+ * @throws QueryException query exception
+ */
+ protected static Item untypedToFlt(final Item item, final InputInfo ii) throws QueryException {
+ if(!item.type.isUntyped()) return item;
+ try {
+ return Flt.get(item.flt(ii));
+ } catch(QueryException ex) {
+ Util.debug(ex);
+ return Dbl.get(item.dbl(ii));
+ }
+ }
+
/**
* Returns an absolute value.
* @return absolute value
diff --git a/basex-core/src/main/java/org/basex/query/value/item/Dbl.java b/basex-core/src/main/java/org/basex/query/value/item/Dbl.java
index c8b53d5715..dab5d8856b 100644
--- a/basex-core/src/main/java/org/basex/query/value/item/Dbl.java
+++ b/basex-core/src/main/java/org/basex/query/value/item/Dbl.java
@@ -107,14 +107,17 @@ public Dbl round(final int prec, final RoundMode mode) {
@Override
public boolean equal(final Item item, final Collation coll, final InputInfo ii)
throws QueryException {
- return value == item.dbl(ii);
+ return !item.type.instanceOf(AtomType.DECIMAL) ? value == item.dbl(ii) :
+ Double.isFinite(value) ? dec(ii).compareTo(item.dec(ii)) == 0 : false;
}
@Override
public int compare(final Item item, final Collation coll, final boolean transitive,
final InputInfo ii) throws QueryException {
- return transitive && item instanceof Dec ? -item.compare(this, coll, transitive, ii) :
- compare(value, item.dbl(ii), transitive);
+ return !item.type.instanceOf(AtomType.DECIMAL) ? compare(value, item.dbl(ii), transitive) :
+ Double.isFinite(value) ? dec(ii).compareTo(item.dec(ii)) :
+ value == Double.NEGATIVE_INFINITY ? -1 : value == Double.POSITIVE_INFINITY ? 1 :
+ transitive ? -1 : NAN_DUMMY;
}
/**
diff --git a/basex-core/src/main/java/org/basex/query/value/item/Dec.java b/basex-core/src/main/java/org/basex/query/value/item/Dec.java
index 9e523fb622..22152a2559 100644
--- a/basex-core/src/main/java/org/basex/query/value/item/Dec.java
+++ b/basex-core/src/main/java/org/basex/query/value/item/Dec.java
@@ -163,23 +163,24 @@ static BigDecimal round(final BigDecimal value, final int prec, final RoundMode
@Override
public boolean equal(final Item item, final Collation coll, final InputInfo ii)
throws QueryException {
- final Type tp = item.type;
- return tp.isUntyped() ? dbl() == item.dbl(ii) :
- tp == AtomType.DOUBLE || tp == AtomType.FLOAT ? item.equal(this, coll, ii) :
- value.compareTo(item.dec(ii)) == 0;
+ final Item it = untypedToDec(item, ii);
+ return !(it instanceof Dbl || it instanceof Flt) || Double.isFinite(it.dbl(ii)) ?
+ value.compareTo(it.dec(ii)) == 0 :
+ false;
}
@Override
public int compare(final Item item, final Collation coll, final boolean transitive,
final InputInfo ii) throws QueryException {
- if(transitive) {
- final double n = item.dbl(ii);
- if(n == Double.NEGATIVE_INFINITY || Double.isNaN(n)) return 1;
- if(n == Double.POSITIVE_INFINITY) return -1;
- } else if(item instanceof Dbl || item instanceof Flt) {
- return -item.compare(this, coll, transitive, ii);
+ final Item it = untypedToDec(item, ii);
+ if(it instanceof Dbl || it instanceof Flt) {
+ final double n = it.dbl(ii);
+ if(!Double.isFinite(n)) {
+ return n == Double.NEGATIVE_INFINITY ? 1 : n == Double.POSITIVE_INFINITY ? -1 :
+ transitive ? 1 : NAN_DUMMY;
+ }
}
- return value.compareTo(item.dec(ii));
+ return value.compareTo(it.dec(ii));
}
@Override
diff --git a/basex-core/src/main/java/org/basex/query/value/item/Flt.java b/basex-core/src/main/java/org/basex/query/value/item/Flt.java
index 470e3c1c59..be058ee34f 100644
--- a/basex-core/src/main/java/org/basex/query/value/item/Flt.java
+++ b/basex-core/src/main/java/org/basex/query/value/item/Flt.java
@@ -107,14 +107,22 @@ public Flt round(final int prec, final RoundMode mode) {
@Override
public boolean equal(final Item item, final Collation coll, final InputInfo ii)
throws QueryException {
- return item.type == AtomType.DOUBLE ? item.equal(this, coll, ii) : value == item.flt(ii);
+ final Item it = untypedToFlt(item, ii);
+ return it instanceof Flt flt ? value == flt.value :
+ it instanceof Dbl ? it.equal(this, coll, ii) :
+ Float.isFinite(value) ? dec(ii).compareTo(it.dec(ii)) == 0 : false;
}
@Override
public int compare(final Item item, final Collation coll, final boolean transitive,
final InputInfo ii) throws QueryException {
- return item instanceof Dbl || transitive && item instanceof Dec
- ? -item.compare(this, coll, transitive, ii) : compare(value, item.flt(ii), transitive);
+ final Item it = untypedToFlt(item, ii);
+ return it instanceof Flt flt ? compare(value, flt.value, transitive) :
+ it instanceof Dbl ? -it.compare(this, coll, transitive, ii) :
+ Float.isFinite(value) ? dec(ii).compareTo(it.dec(ii)) :
+ value == Float.NEGATIVE_INFINITY ? -1 :
+ value == Float.POSITIVE_INFINITY ? 1 :
+ transitive ? -1 : NAN_DUMMY;
}
/**
diff --git a/basex-core/src/main/java/org/basex/query/value/item/Itr.java b/basex-core/src/main/java/org/basex/query/value/item/Itr.java
index b745f6f56e..d2447de4ce 100644
--- a/basex-core/src/main/java/org/basex/query/value/item/Itr.java
+++ b/basex-core/src/main/java/org/basex/query/value/item/Itr.java
@@ -151,16 +151,14 @@ public int toInt() {
public boolean equal(final Item item, final Collation coll, final InputInfo ii)
throws QueryException {
return item instanceof final Itr itr ? value == itr.value :
- item instanceof Dec ? item.equal(this, coll, ii) :
- value == item.dbl(ii);
+ untypedToDec(item, ii).equal(this, coll, ii);
}
@Override
public int compare(final Item item, final Collation coll, final boolean transitive,
final InputInfo ii) throws QueryException {
return item instanceof final Itr itr ? Long.compare(value, itr.value) :
- item instanceof Dec ? -item.compare(this, coll, transitive, ii) :
- Dbl.compare(dbl(ii), item.dbl(ii), transitive);
+ -untypedToDec(item, ii).compare(this, coll, transitive, ii);
}
@Override
diff --git a/basex-core/src/main/java/org/basex/query/value/item/Uln.java b/basex-core/src/main/java/org/basex/query/value/item/Uln.java
index d4bc54d2fd..5495db78e1 100644
--- a/basex-core/src/main/java/org/basex/query/value/item/Uln.java
+++ b/basex-core/src/main/java/org/basex/query/value/item/Uln.java
@@ -88,19 +88,17 @@ public ANum round(final int prec, final RoundMode mode) {
@Override
public boolean equal(final Item item, final Collation coll, final InputInfo ii)
throws QueryException {
- return item.type == AtomType.UNSIGNED_LONG ? value.equals(((Uln) item).value) :
- item.type == AtomType.DOUBLE || item.type == AtomType.FLOAT || item.type == AtomType.DECIMAL ?
- item.equal(this, coll, ii) :
- value.compareTo(BigInteger.valueOf(item.itr(ii))) == 0;
+ return item instanceof final Uln uln ? value.equals(uln.value) :
+ item instanceof Itr ? value.equals(BigInteger.valueOf(item.itr(ii))) :
+ untypedToDec(item, ii).equal(this, coll, ii);
}
@Override
public int compare(final Item item, final Collation coll, final boolean transitive,
final InputInfo ii) throws QueryException {
- return item.type == AtomType.UNSIGNED_LONG ? value.compareTo(((Uln) item).value) :
- item.type == AtomType.DOUBLE || item.type == AtomType.FLOAT || item.type == AtomType.DECIMAL ?
- -item.compare(this, coll, transitive, ii) :
- value.compareTo(BigInteger.valueOf(item.itr(ii)));
+ return item instanceof final Uln uln ? value.compareTo(uln.value) :
+ item instanceof Itr ? value.compareTo(BigInteger.valueOf(item.itr(ii))) :
+ -untypedToDec(item, ii).compare(this, coll, transitive, ii);
}
@Override
diff --git a/basex-core/src/test/java/org/basex/query/ast/RewritingsTest.java b/basex-core/src/test/java/org/basex/query/ast/RewritingsTest.java
index cbcd058c57..adbbd84c32 100644
--- a/basex-core/src/test/java/org/basex/query/ast/RewritingsTest.java
+++ b/basex-core/src/test/java/org/basex/query/ast/RewritingsTest.java
@@ -171,9 +171,11 @@ public final class RewritingsTest extends SandboxTest {
check("5[text() <= -800000000]", "", exists(cmpr));
check("5[text() > 8000000000000000000]", "", exists(cmpr));
check("5[text() < -8000000000000000000]", "", exists(cmpr));
- check("exists(1234567890.12345678[. = 1234567890.1234567])", true, empty(cmpr));
+ check("exists(1234567890.12345678[. = 1234567890.1234567])", false, empty(cmpr));
+ check("exists(1234567890.12345678e0[. = 1234567890.1234567e0])", true, empty(cmpr));
- check("exists(123456789012345678 [. = 123456789012345679])", true, empty(cmpr));
+ check("exists(123456789012345678 [. = 123456789012345679])", false, empty(cmpr));
+ check("exists(123456789012345678e0 [. = 123456789012345679e0])", true, empty(cmpr));
check("5[xs:integer(.) > 8000000000000000000]", "", empty(cmpr));
check("5[xs:integer(.) < -8000000000000000000]", "", empty(cmpr));
check("(1, 1234567890.12345678)[. = 1234567890.1234567]", "", empty(cmpr));
@@ -885,9 +887,13 @@ public final class RewritingsTest extends SandboxTest {
"2\n3\n4\n5\n6\n7", empty(Cast.class));
check("for $n in (10000000000000000, 1)[. != 0] return number($n) = 10000000000000001",
- "true\nfalse", exists(NUMBER));
+ "false\nfalse", exists(NUMBER));
+ check("for $n in (10000000000000000, 1)[. != 0] return number($n) = "
+ + "xs:double(10000000000000001)", "true\nfalse", exists(NUMBER));
check("for $n in (10000000000000000, 1)[. != 0] return xs:double($n) = 10000000000000001",
- "true\nfalse", exists(Cast.class));
+ "false\nfalse", exists(Cast.class));
+ check("for $n in (10000000000000000, 1)[. != 0] return xs:double($n) = "
+ + "xs:double(10000000000000001)", "true\nfalse", exists(Cast.class));
check("number() + number(<_>2)", 3, count(NUMBER, 1));
check("xs:double() + xs:double(<_>2)", 3, count(Cast.class, 1));
diff --git a/basex-core/src/test/java/org/basex/query/simple/SimpleTest.java b/basex-core/src/test/java/org/basex/query/simple/SimpleTest.java
index ca1628baee..9db7c66618 100644
--- a/basex-core/src/test/java/org/basex/query/simple/SimpleTest.java
+++ b/basex-core/src/test/java/org/basex/query/simple/SimpleTest.java
@@ -53,10 +53,10 @@ public final class SimpleTest extends QueryTest {
{ "Compare 5", booleans(false), "1234567890.12345678 = 1234567890.1234567" },
{ "Compare 6", booleans(false), "123456789012345678 = 123456789012345679" },
// GH-2112, GH-2115
- { "Compare 7", booleans(false), "xs:decimal(1.13) gt xs:double(1.13)" },
- { "Compare 8", booleans(false), "xs:decimal(1.13) gt xs:float(1.13)" },
- { "Compare 9", booleans(true), "xs:decimal(1.13) le xs:double(1.13)" },
- { "Compare 10", booleans(true), "xs:decimal(1.13) le xs:float(1.13)" },
+ { "Compare 7", booleans(true), "xs:decimal(1.13) gt xs:double(1.13)" },
+ { "Compare 8", booleans(true), "xs:decimal(1.13) gt xs:float(1.13)" },
+ { "Compare 9", booleans(false), "xs:decimal(1.13) le xs:double(1.13)" },
+ { "Compare 10", booleans(false), "xs:decimal(1.13) le xs:float(1.13)" },
// GH-2113, GH-2114
{ "Compare 11", booleans(false), "xs:float (1.13) ge xs:double(1.13)" },
{ "Compare 12", booleans(true), "xs:float (1.13) le xs:double(1.13)" },