@@ -137,7 +137,8 @@ public boolean isPositive() {
137
137
if (other instanceof IntegerValue ) {
138
138
comparison = () -> BigDecimal .valueOf (value ).compareTo (new BigDecimal (((IntegerValue )other ).value ));
139
139
} else if (other instanceof DecimalValue ) {
140
- comparison = () -> BigDecimal .valueOf (value ).compareTo (((DecimalValue )other ).value );
140
+ final BigDecimal promoted = new BigDecimal (Float .toString (value ));
141
+ comparison = () -> promoted .compareTo (((DecimalValue )other ).value );
141
142
} else if (other instanceof DoubleValue ) {
142
143
comparison = () -> BigDecimal .valueOf (value ).compareTo (BigDecimal .valueOf (((DoubleValue )other ).value ));
143
144
} else if (other instanceof FloatValue ) {
@@ -276,35 +277,38 @@ public NumericValue round(IntegerValue precision) throws XPathException {
276
277
return round (precision , DecimalValue .DEFAULT_ROUNDING_MODE );
277
278
}
278
279
279
- /* (non-Javadoc)
280
- * @see org.exist.xquery.value.NumericValue#minus(org.exist.xquery.value.NumericValue)
281
- */
282
- public ComputableValue minus (ComputableValue other ) throws XPathException {
280
+ @ Override
281
+ public ComputableValue minus (final ComputableValue other ) throws XPathException {
283
282
if (Type .subTypeOf (other .getType (), Type .FLOAT )) {
284
283
return new FloatValue (value - ((FloatValue ) other ).value );
284
+ } else if (other .getType () == Type .DOUBLE ) {
285
+ // type promotion - see https://www.w3.org/TR/xpath-31/#promotion
286
+ return ((DoubleValue ) convertTo (Type .DOUBLE )).minus (other );
285
287
} else {
286
288
return minus ((ComputableValue ) other .convertTo (getType ()));
287
289
}
288
290
}
289
291
290
- /* (non-Javadoc)
291
- * @see org.exist.xquery.value.NumericValue#plus(org.exist.xquery.value.NumericValue)
292
- */
293
- public ComputableValue plus (ComputableValue other ) throws XPathException {
292
+ @ Override
293
+ public ComputableValue plus (final ComputableValue other ) throws XPathException {
294
294
if (Type .subTypeOf (other .getType (), Type .FLOAT )) {
295
295
return new FloatValue (value + ((FloatValue ) other ).value );
296
+ } else if (other .getType () == Type .DOUBLE ) {
297
+ // type promotion - see https://www.w3.org/TR/xpath-31/#promotion
298
+ return ((DoubleValue ) convertTo (Type .DOUBLE )).plus (other );
296
299
} else {
297
300
return plus ((ComputableValue ) other .convertTo (getType ()));
298
301
}
299
302
}
300
303
301
- /* (non-Javadoc)
302
- * @see org.exist.xquery.value.NumericValue#mult(org.exist.xquery.value.NumericValue)
303
- */
304
- public ComputableValue mult (ComputableValue other ) throws XPathException {
304
+ @ Override
305
+ public ComputableValue mult (final ComputableValue other ) throws XPathException {
305
306
switch (other .getType ()) {
306
307
case Type .FLOAT :
307
308
return new FloatValue (value * ((FloatValue ) other ).value );
309
+ case Type .DOUBLE :
310
+ // type promotion - see https://www.w3.org/TR/xpath-31/#promotion
311
+ return ((DoubleValue ) convertTo (Type .DOUBLE )).mult (other );
308
312
case Type .DAY_TIME_DURATION :
309
313
case Type .YEAR_MONTH_DURATION :
310
314
return other .mult (this );
@@ -358,26 +362,26 @@ public ComputableValue div(ComputableValue other) throws XPathException {
358
362
}
359
363
}
360
364
361
- public IntegerValue idiv (NumericValue other ) throws XPathException {
362
- final ComputableValue result = div (other );
363
- return new IntegerValue (((IntegerValue ) result .convertTo (Type .INTEGER )).getLong ());
364
- /*
365
- if (Type.subTypeOf(other.getType(), Type.FLOAT)) {
366
- float result = value / ((FloatValue) other).value;
367
- if (result == Float.NaN || result == Float.POSITIVE_INFINITY || result == Float.NEGATIVE_INFINITY)
368
- throw new XPathException("illegal arguments to idiv");
369
- return new IntegerValue(new BigDecimal(result).toBigInteger(), Type.INTEGER);
370
- }
371
- throw new XPathException("idiv called with incompatible argument type: " + getType() + " vs " + other.getType());
372
- */
365
+ @ Override
366
+ public IntegerValue idiv (final NumericValue other ) throws XPathException {
367
+ if (other .getType () == Type .DOUBLE ) {
368
+ // type promotion - see https://www.w3.org/TR/xpath-31/#promotion
369
+ return ((DoubleValue ) convertTo (Type .DOUBLE )).idiv (other );
370
+ } else if (other .getType () == Type .DECIMAL ) {
371
+ return idiv ((FloatValue ) other .convertTo (Type .FLOAT ));
372
+ } else {
373
+ final ComputableValue result = div (other );
374
+ return new IntegerValue (((IntegerValue ) result .convertTo (Type .INTEGER )).getLong ());
375
+ }
373
376
}
374
377
375
- /* (non-Javadoc)
376
- * @see org.exist.xquery.value.NumericValue#mod(org.exist.xquery.value.NumericValue)
377
- */
378
- public NumericValue mod (NumericValue other ) throws XPathException {
378
+ @ Override
379
+ public NumericValue mod (final NumericValue other ) throws XPathException {
379
380
if (Type .subTypeOf (other .getType (), Type .FLOAT )) {
380
381
return new FloatValue (value % ((FloatValue ) other ).value );
382
+ } else if (other .getType () == Type .DOUBLE ) {
383
+ // type promotion - see https://www.w3.org/TR/xpath-31/#promotion
384
+ return ((DoubleValue ) convertTo (Type .DOUBLE )).mod (other );
381
385
} else {
382
386
return mod ((NumericValue ) other .convertTo (getType ()));
383
387
}
0 commit comments