Skip to content

Commit

Permalink
Merge pull request #4436 from evolvedbinary/5.x.x/hotfix/numeric-oper…
Browse files Browse the repository at this point in the history
…ations
  • Loading branch information
dizzzz committed Jun 10, 2022
2 parents cbc04e9 + 8fbb99a commit 6046702
Show file tree
Hide file tree
Showing 16 changed files with 924 additions and 39 deletions.
Expand Up @@ -76,7 +76,7 @@ protected Sequence genericCompare(Sequence contextSequence, Item contextItem) th
final AtomicValue rv = rs.itemAt(0).atomize();
final Collator collator = getCollator(contextSequence);
return BooleanValue.valueOf(compareAtomic(collator, lv, rv, StringTruncationOperator.NONE, relation));
}
}
throw new XPathException(this, ErrorCodes.XPTY0004, "Type error: sequence with more than one item is not allowed here");
}

Expand Down
Expand Up @@ -283,7 +283,8 @@ public boolean isPositive() {
} else if (other instanceof DoubleValue) {
comparison = () -> value.compareTo(BigDecimal.valueOf(((DoubleValue)other).value));
} else if (other instanceof FloatValue) {
comparison = () -> value.compareTo(BigDecimal.valueOf(((FloatValue)other).value));
final BigDecimal otherPromoted = new BigDecimal(Float.toString(((FloatValue)other).value));
comparison = () -> value.compareTo(otherPromoted);
} else {
return null;
}
Expand Down Expand Up @@ -352,10 +353,8 @@ public NumericValue round(IntegerValue precision) throws XPathException {
}
}

/* (non-Javadoc)
* @see org.exist.xquery.value.NumericValue#minus(org.exist.xquery.value.NumericValue)
*/
public ComputableValue minus(ComputableValue other) throws XPathException {
@Override
public ComputableValue minus(final ComputableValue other) throws XPathException {
switch (other.getType()) {
case Type.DECIMAL:
return new DecimalValue(value.subtract(((DecimalValue) other).value));
Expand All @@ -366,10 +365,8 @@ public ComputableValue minus(ComputableValue other) throws XPathException {
}
}

/* (non-Javadoc)
* @see org.exist.xquery.value.NumericValue#plus(org.exist.xquery.value.NumericValue)
*/
public ComputableValue plus(ComputableValue other) throws XPathException {
@Override
public ComputableValue plus(final ComputableValue other) throws XPathException {
switch (other.getType()) {
case Type.DECIMAL:
return new DecimalValue(value.add(((DecimalValue) other).value));
Expand Down
62 changes: 33 additions & 29 deletions exist-core/src/main/java/org/exist/xquery/value/FloatValue.java
Expand Up @@ -136,7 +136,8 @@ public boolean isPositive() {
if (other instanceof IntegerValue) {
comparison = () -> BigDecimal.valueOf(value).compareTo(new BigDecimal(((IntegerValue)other).value));
} else if (other instanceof DecimalValue) {
comparison = () -> BigDecimal.valueOf(value).compareTo(((DecimalValue)other).value);
final BigDecimal promoted = new BigDecimal(Float.toString(value));
comparison = () -> promoted.compareTo(((DecimalValue)other).value);
} else if (other instanceof DoubleValue) {
comparison = () -> BigDecimal.valueOf(value).compareTo(BigDecimal.valueOf(((DoubleValue)other).value));
} else if (other instanceof FloatValue) {
Expand Down Expand Up @@ -268,35 +269,38 @@ public NumericValue round(IntegerValue precision) throws XPathException {
return (FloatValue) ((DecimalValue) convertTo(Type.DECIMAL)).round(precision).convertTo(Type.FLOAT);
}

/* (non-Javadoc)
* @see org.exist.xquery.value.NumericValue#minus(org.exist.xquery.value.NumericValue)
*/
public ComputableValue minus(ComputableValue other) throws XPathException {
@Override
public ComputableValue minus(final ComputableValue other) throws XPathException {
if (Type.subTypeOf(other.getType(), Type.FLOAT)) {
return new FloatValue(value - ((FloatValue) other).value);
} else if (other.getType() == Type.DOUBLE) {
// type promotion - see https://www.w3.org/TR/xpath-31/#promotion
return ((DoubleValue) convertTo(Type.DOUBLE)).minus(other);
} else {
return minus((ComputableValue) other.convertTo(getType()));
}
}

/* (non-Javadoc)
* @see org.exist.xquery.value.NumericValue#plus(org.exist.xquery.value.NumericValue)
*/
public ComputableValue plus(ComputableValue other) throws XPathException {
@Override
public ComputableValue plus(final ComputableValue other) throws XPathException {
if (Type.subTypeOf(other.getType(), Type.FLOAT)) {
return new FloatValue(value + ((FloatValue) other).value);
} else if (other.getType() == Type.DOUBLE) {
// type promotion - see https://www.w3.org/TR/xpath-31/#promotion
return ((DoubleValue) convertTo(Type.DOUBLE)).plus(other);
} else {
return plus((ComputableValue) other.convertTo(getType()));
}
}

/* (non-Javadoc)
* @see org.exist.xquery.value.NumericValue#mult(org.exist.xquery.value.NumericValue)
*/
public ComputableValue mult(ComputableValue other) throws XPathException {
@Override
public ComputableValue mult(final ComputableValue other) throws XPathException {
switch (other.getType()) {
case Type.FLOAT:
return new FloatValue(value * ((FloatValue) other).value);
case Type.DOUBLE:
// type promotion - see https://www.w3.org/TR/xpath-31/#promotion
return ((DoubleValue) convertTo(Type.DOUBLE)).mult(other);
case Type.DAY_TIME_DURATION:
case Type.YEAR_MONTH_DURATION:
return other.mult(this);
Expand Down Expand Up @@ -350,26 +354,26 @@ public ComputableValue div(ComputableValue other) throws XPathException {
}
}

public IntegerValue idiv(NumericValue other) throws XPathException {
final ComputableValue result = div(other);
return new IntegerValue(((IntegerValue) result.convertTo(Type.INTEGER)).getLong());
/*
if (Type.subTypeOf(other.getType(), Type.FLOAT)) {
float result = value / ((FloatValue) other).value;
if (result == Float.NaN || result == Float.POSITIVE_INFINITY || result == Float.NEGATIVE_INFINITY)
throw new XPathException("illegal arguments to idiv");
return new IntegerValue(new BigDecimal(result).toBigInteger(), Type.INTEGER);
}
throw new XPathException("idiv called with incompatible argument type: " + getType() + " vs " + other.getType());
*/
@Override
public IntegerValue idiv(final NumericValue other) throws XPathException {
if (other.getType() == Type.DOUBLE) {
// type promotion - see https://www.w3.org/TR/xpath-31/#promotion
return ((DoubleValue) convertTo(Type.DOUBLE)).idiv(other);
} else if (other.getType() == Type.DECIMAL) {
return idiv((FloatValue) other.convertTo(Type.FLOAT));
} else {
final ComputableValue result = div(other);
return new IntegerValue(((IntegerValue) result.convertTo(Type.INTEGER)).getLong());
}
}

/* (non-Javadoc)
* @see org.exist.xquery.value.NumericValue#mod(org.exist.xquery.value.NumericValue)
*/
public NumericValue mod(NumericValue other) throws XPathException {
@Override
public NumericValue mod(final NumericValue other) throws XPathException {
if (Type.subTypeOf(other.getType(), Type.FLOAT)) {
return new FloatValue(value % ((FloatValue) other).value);
} else if (other.getType() == Type.DOUBLE) {
// type promotion - see https://www.w3.org/TR/xpath-31/#promotion
return ((DoubleValue) convertTo(Type.DOUBLE)).mod(other);
} else {
return mod((NumericValue) other.convertTo(getType()));
}
Expand Down
32 changes: 32 additions & 0 deletions exist-core/src/test/java/xquery/numericOp/NumericOpTests.java
@@ -0,0 +1,32 @@
/*
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
* info@exist-db.org
* http://www.exist-db.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package xquery.numericOp;

import org.exist.test.runner.XSuite;
import org.junit.runner.RunWith;

@RunWith(XSuite.class)
@XSuite.XSuiteFiles({
"src/test/xquery/numericOp"
})
public class NumericOpTests {
}
71 changes: 71 additions & 0 deletions exist-core/src/test/xquery/numericOp/numeric-add.xqm
@@ -0,0 +1,71 @@
(:
: eXist-db Open Source Native XML Database
: Copyright (C) 2001 The eXist-db Authors
:
: info@exist-db.org
: http://www.exist-db.org
:
: This library is free software; you can redistribute it and/or
: modify it under the terms of the GNU Lesser General Public
: License as published by the Free Software Foundation; either
: version 2.1 of the License, or (at your option) any later version.
:
: This library is distributed in the hope that it will be useful,
: but WITHOUT ANY WARRANTY; without even the implied warranty of
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
: Lesser General Public License for more details.
:
: You should have received a copy of the GNU Lesser General Public
: License along with this library; if not, write to the Free Software
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
:)
xquery version "3.1";

(:~
: Tests for the op:numeric-add operator.
:)
module namespace ona = "http://exist-db.org/test/op-numeric-add";

declare namespace test = "http://exist-db.org/xquery/xqsuite";

declare
%test:args("1.13", "1.13")
%test:assertEquals("2.2599999952316283")
function ona:numeric-add-float-double($f as xs:float, $d as xs:double) {
$f + $d
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("2.2599999952316283")
function ona:numeric-add-double-float($d as xs:double, $f as xs:float) {
$d + $f
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("2.26")
function ona:numeric-add-double-decimal($d as xs:double, $dec as xs:decimal) {
$d + $dec
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("2.26")
function ona:numeric-add-decimal-double($dec as xs:decimal, $d as xs:double) {
$dec + $d
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("2.26")
function ona:numeric-add-decimal-float($dec as xs:decimal, $f as xs:float) {
$dec + $f
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("2.26")
function ona:numeric-add-float-decimal($f as xs:float, $dec as xs:decimal) {
$f + $dec
};
71 changes: 71 additions & 0 deletions exist-core/src/test/xquery/numericOp/numeric-divide.xqm
@@ -0,0 +1,71 @@
(:
: eXist-db Open Source Native XML Database
: Copyright (C) 2001 The eXist-db Authors
:
: info@exist-db.org
: http://www.exist-db.org
:
: This library is free software; you can redistribute it and/or
: modify it under the terms of the GNU Lesser General Public
: License as published by the Free Software Foundation; either
: version 2.1 of the License, or (at your option) any later version.
:
: This library is distributed in the hope that it will be useful,
: but WITHOUT ANY WARRANTY; without even the implied warranty of
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
: Lesser General Public License for more details.
:
: You should have received a copy of the GNU Lesser General Public
: License along with this library; if not, write to the Free Software
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
:)
xquery version "3.1";

(:~
: Tests for the op:numeric-divide operator.
:)
module namespace ond = "http://exist-db.org/test/op-numeric-divide";

declare namespace test = "http://exist-db.org/xquery/xqsuite";

declare
%test:args("1.13", "1.13")
%test:assertEquals("0.9999999957802023")
function ond:numeric-divide-float-double($f as xs:float, $d as xs:double) {
$f div $d
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("1.0000000042197978")
function ond:numeric-divide-double-float($d as xs:double, $f as xs:float) {
$d div $f
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("1")
function ond:numeric-divide-double-decimal($d as xs:double, $dec as xs:decimal) {
$d div $dec
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("1")
function ond:numeric-divide-decimal-double($dec as xs:decimal, $d as xs:double) {
$dec div $d
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("1")
function ond:numeric-divide-decimal-float($dec as xs:decimal, $f as xs:float) {
$dec div $f
};

declare
%test:args("1.13", "1.13")
%test:assertEquals("1")
function ond:numeric-divide-float-decimal($f as xs:float, $dec as xs:decimal) {
$f div $dec
};
71 changes: 71 additions & 0 deletions exist-core/src/test/xquery/numericOp/numeric-equal.xqm
@@ -0,0 +1,71 @@
(:
: eXist-db Open Source Native XML Database
: Copyright (C) 2001 The eXist-db Authors
:
: info@exist-db.org
: http://www.exist-db.org
:
: This library is free software; you can redistribute it and/or
: modify it under the terms of the GNU Lesser General Public
: License as published by the Free Software Foundation; either
: version 2.1 of the License, or (at your option) any later version.
:
: This library is distributed in the hope that it will be useful,
: but WITHOUT ANY WARRANTY; without even the implied warranty of
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
: Lesser General Public License for more details.
:
: You should have received a copy of the GNU Lesser General Public
: License along with this library; if not, write to the Free Software
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
:)
xquery version "3.1";

(:~
: Tests for the op:numeric-equal operator.
:)
module namespace one = "http://exist-db.org/test/op-numeric-equal";

declare namespace test = "http://exist-db.org/xquery/xqsuite";

declare
%test:args("1.13", "1.13")
%test:assertFalse
function one:numeric-equal-float-double($f as xs:float, $d as xs:double) {
$f eq $d
};

declare
%test:args("1.13", "1.13")
%test:assertFalse
function one:numeric-equal-double-float($d as xs:double, $f as xs:float) {
$d eq $f
};

declare
%test:args("1.13", "1.13")
%test:assertTrue
function one:numeric-equal-double-decimal($d as xs:double, $dec as xs:decimal) {
$d eq $dec
};

declare
%test:args("1.13", "1.13")
%test:assertTrue
function one:numeric-equal-decimal-double($dec as xs:decimal, $d as xs:double) {
$dec eq $d
};

declare
%test:args("1.13", "1.13")
%test:assertTrue
function one:numeric-equal-decimal-float($dec as xs:decimal, $f as xs:float) {
$dec eq $f
};

declare
%test:args("1.13", "1.13")
%test:assertTrue
function one:numeric-equal-float-decimal($f as xs:float, $dec as xs:decimal) {
$f eq $dec
};

0 comments on commit 6046702

Please sign in to comment.