提交 9aad5808 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Do not use BigInteger in ValueLong.multiply()

上级 b80fcd53
...@@ -43,7 +43,6 @@ public class ValueLong extends Value { ...@@ -43,7 +43,6 @@ public class ValueLong extends Value {
*/ */
public static final int DISPLAY_SIZE = 20; public static final int DISPLAY_SIZE = 20;
private static final BigInteger MIN_BI = BigInteger.valueOf(Long.MIN_VALUE);
private static final int STATIC_SIZE = 100; private static final int STATIC_SIZE = 100;
private static final ValueLong[] STATIC_CACHE; private static final ValueLong[] STATIC_CACHE;
...@@ -110,32 +109,20 @@ public class ValueLong extends Value { ...@@ -110,32 +109,20 @@ public class ValueLong extends Value {
return add(other.negate()); return add(other.negate());
} }
private static boolean isInteger(long a) {
return a >= Integer.MIN_VALUE && a <= Integer.MAX_VALUE;
}
@Override @Override
public Value multiply(Value v) { public Value multiply(Value v) {
ValueLong other = (ValueLong) v; long x = value;
long result = value * other.value; long y = ((ValueLong) v).value;
if (value == 0 || value == 1 || other.value == 0 || other.value == 1) { long result = x * y;
return ValueLong.get(result); // Check whether numbers are large enough to overflow and second value != 0
} if ((Math.abs(x) | Math.abs(y)) >>> 31 != 0 && y != 0
if (isInteger(value) && isInteger(other.value)) { // Check with division
return ValueLong.get(result); && (result / y != x
} // Also check the special condition that is not handled above
// just checking one case is not enough: Long.MIN_VALUE * -1 || x == Long.MIN_VALUE && y == -1)) {
// probably this is correct but I'm not sure
// if (result / value == other.value && result / other.value == value) {
// return ValueLong.get(result);
//}
BigInteger bv = BigInteger.valueOf(value);
BigInteger bo = BigInteger.valueOf(other.value);
BigInteger br = bv.multiply(bo);
if (br.compareTo(MIN_BI) < 0 || br.compareTo(MAX_BI) > 0) {
throw getOverflow(); throw getOverflow();
} }
return ValueLong.get(br.longValue()); return ValueLong.get(result);
} }
@Override @Override
......
...@@ -2,3 +2,41 @@ ...@@ -2,3 +2,41 @@
-- and the EPL 1.0 (http://h2database.com/html/license.html). -- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group -- Initial Developer: H2 Group
-- --
-- Multiplication
SELECT CAST(-4294967296 AS BIGINT) * CAST (2147483648 AS BIGINT);
>> -9223372036854775808
SELECT CAST(4294967296 AS BIGINT) * CAST (-2147483648 AS BIGINT);
>> -9223372036854775808
SELECT CAST(-2147483648 AS BIGINT) * CAST (4294967296 AS BIGINT);
>> -9223372036854775808
SELECT CAST(2147483648 AS BIGINT) * CAST (-4294967296 AS BIGINT);
>> -9223372036854775808
SELECT CAST(4294967296 AS BIGINT) * CAST (2147483648 AS BIGINT);
> exception NUMERIC_VALUE_OUT_OF_RANGE_1
SELECT CAST(-4294967296 AS BIGINT) * CAST (-2147483648 AS BIGINT);
> exception NUMERIC_VALUE_OUT_OF_RANGE_1
SELECT CAST(2147483648 AS BIGINT) * CAST (4294967296 AS BIGINT);
> exception NUMERIC_VALUE_OUT_OF_RANGE_1
SELECT CAST(-2147483648 AS BIGINT) * CAST (-4294967296 AS BIGINT);
> exception NUMERIC_VALUE_OUT_OF_RANGE_1
SELECT CAST(-9223372036854775808 AS BIGINT) * CAST(1 AS BIGINT);
>> -9223372036854775808
SELECT CAST(-9223372036854775808 AS BIGINT) * CAST(-1 AS BIGINT);
> exception NUMERIC_VALUE_OUT_OF_RANGE_1
SELECT CAST(1 AS BIGINT) * CAST(-9223372036854775808 AS BIGINT);
>> -9223372036854775808
SELECT CAST(-1 AS BIGINT) * CAST(-9223372036854775808 AS BIGINT);
> exception NUMERIC_VALUE_OUT_OF_RANGE_1
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论