提交 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 {
*/
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 ValueLong[] STATIC_CACHE;
......@@ -110,32 +109,20 @@ public class ValueLong extends Value {
return add(other.negate());
}
private static boolean isInteger(long a) {
return a >= Integer.MIN_VALUE && a <= Integer.MAX_VALUE;
}
@Override
public Value multiply(Value v) {
ValueLong other = (ValueLong) v;
long result = value * other.value;
if (value == 0 || value == 1 || other.value == 0 || other.value == 1) {
return ValueLong.get(result);
}
if (isInteger(value) && isInteger(other.value)) {
return ValueLong.get(result);
}
// just checking one case is not enough: Long.MIN_VALUE * -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) {
long x = value;
long y = ((ValueLong) v).value;
long result = x * y;
// Check whether numbers are large enough to overflow and second value != 0
if ((Math.abs(x) | Math.abs(y)) >>> 31 != 0 && y != 0
// Check with division
&& (result / y != x
// Also check the special condition that is not handled above
|| x == Long.MIN_VALUE && y == -1)) {
throw getOverflow();
}
return ValueLong.get(br.longValue());
return ValueLong.get(result);
}
@Override
......
......@@ -2,3 +2,41 @@
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论