Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions basex-core/src/main/java/org/basex/query/value/item/ANum.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions basex-core/src/main/java/org/basex/query/value/item/Dbl.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
23 changes: 12 additions & 11 deletions basex-core/src/main/java/org/basex/query/value/item/Dec.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 11 additions & 3 deletions basex-core/src/main/java/org/basex/query/value/item/Flt.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
6 changes: 2 additions & 4 deletions basex-core/src/main/java/org/basex/query/value/item/Itr.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 6 additions & 8 deletions basex-core/src/main/java/org/basex/query/value/item/Uln.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 10 additions & 4 deletions basex-core/src/test/java/org/basex/query/ast/RewritingsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,11 @@ public final class RewritingsTest extends SandboxTest {
check("<a>5</a>[text() <= -800000000]", "", exists(cmpr));
check("<a>5</a>[text() > 8000000000000000000]", "", exists(cmpr));
check("<a>5</a>[text() < -8000000000000000000]", "", exists(cmpr));
check("exists(<x>1234567890.12345678</x>[. = 1234567890.1234567])", true, empty(cmpr));
check("exists(<x>1234567890.12345678</x>[. = 1234567890.1234567])", false, empty(cmpr));
check("exists(<x>1234567890.12345678e0</x>[. = 1234567890.1234567e0])", true, empty(cmpr));

check("exists(<x>123456789012345678</x> [. = 123456789012345679])", true, empty(cmpr));
check("exists(<x>123456789012345678</x> [. = 123456789012345679])", false, empty(cmpr));
check("exists(<x>123456789012345678e0</x> [. = 123456789012345679e0])", true, empty(cmpr));
check("<a>5</a>[xs:integer(.) > 8000000000000000000]", "", empty(cmpr));
check("<a>5</a>[xs:integer(.) < -8000000000000000000]", "", empty(cmpr));
check("(1, 1234567890.12345678)[. = 1234567890.1234567]", "", empty(cmpr));
Expand Down Expand Up @@ -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(<?_ 1?>) + number(<_>2</_>)", 3, count(NUMBER, 1));
check("xs:double(<?_ 1?>) + xs:double(<_>2</_>)", 3, count(Cast.class, 1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)" },
Expand Down