From 27e328ec6139d243ac9146a6edf3a7b06ede4409 Mon Sep 17 00:00:00 2001 From: bpb Date: Thu, 5 Dec 2013 07:45:27 -0800 Subject: [PATCH] 8029501: BigInteger division algorithm selection heuristic is incorrect Summary: Change Burnikel-Ziegler division heuristic to require that the dividend int-length exceed that of the divisor by a minimum amount. Reviewed-by: darcy --- src/share/classes/java/math/BigInteger.java | 26 ++++++++++++------- .../classes/java/math/MutableBigInteger.java | 4 +-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/share/classes/java/math/BigInteger.java b/src/share/classes/java/math/BigInteger.java index f5bf079e4..79291ee34 100644 --- a/src/share/classes/java/math/BigInteger.java +++ b/src/share/classes/java/math/BigInteger.java @@ -244,12 +244,20 @@ public class BigInteger extends Number implements Comparable { /** * The threshold value for using Burnikel-Ziegler division. If the number - * of ints in the number are larger than this value, - * Burnikel-Ziegler division will be used. This value is found - * experimentally to work well. + * of ints in the divisor are larger than this value, Burnikel-Ziegler + * division may be used. This value is found experimentally to work well. */ static final int BURNIKEL_ZIEGLER_THRESHOLD = 80; + /** + * The offset value for using Burnikel-Ziegler division. If the number + * of ints in the divisor exceeds the Burnikel-Ziegler threshold, and the + * number of ints in the dividend is greater than the number of ints in the + * divisor plus this value, Burnikel-Ziegler division will be used. This + * value is found experimentally to work well. + */ + static final int BURNIKEL_ZIEGLER_OFFSET = 40; + /** * The threshold value for using Schoenhage recursive base conversion. If * the number of ints in the number are larger than this value, @@ -2017,8 +2025,8 @@ public class BigInteger extends Number implements Comparable { * @throws ArithmeticException if {@code val} is zero. */ public BigInteger divide(BigInteger val) { - if (mag.length < BURNIKEL_ZIEGLER_THRESHOLD || - val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD) { + if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD || + mag.length - val.mag.length < BURNIKEL_ZIEGLER_OFFSET) { return divideKnuth(val); } else { return divideBurnikelZiegler(val); @@ -2054,8 +2062,8 @@ public class BigInteger extends Number implements Comparable { * @throws ArithmeticException if {@code val} is zero. */ public BigInteger[] divideAndRemainder(BigInteger val) { - if (mag.length < BURNIKEL_ZIEGLER_THRESHOLD || - val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD) { + if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD || + mag.length - val.mag.length < BURNIKEL_ZIEGLER_OFFSET) { return divideAndRemainderKnuth(val); } else { return divideAndRemainderBurnikelZiegler(val); @@ -2083,8 +2091,8 @@ public class BigInteger extends Number implements Comparable { * @throws ArithmeticException if {@code val} is zero. */ public BigInteger remainder(BigInteger val) { - if (mag.length < BURNIKEL_ZIEGLER_THRESHOLD || - val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD) { + if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD || + mag.length - val.mag.length < BURNIKEL_ZIEGLER_OFFSET) { return remainderKnuth(val); } else { return remainderBurnikelZiegler(val); diff --git a/src/share/classes/java/math/MutableBigInteger.java b/src/share/classes/java/math/MutableBigInteger.java index bc4e48413..5bb5c37d9 100644 --- a/src/share/classes/java/math/MutableBigInteger.java +++ b/src/share/classes/java/math/MutableBigInteger.java @@ -1148,8 +1148,8 @@ class MutableBigInteger { } MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient, boolean needRemainder) { - if (intLen < BigInteger.BURNIKEL_ZIEGLER_THRESHOLD || - b.intLen < BigInteger.BURNIKEL_ZIEGLER_THRESHOLD) { + if (b.intLen < BigInteger.BURNIKEL_ZIEGLER_THRESHOLD || + intLen - b.intLen < BigInteger.BURNIKEL_ZIEGLER_OFFSET) { return divideKnuth(b, quotient, needRemainder); } else { return divideAndRemainderBurnikelZiegler(b, quotient); -- GitLab