8029501: BigInteger division algorithm selection heuristic is incorrect
authorbpb
Thu, 05 Dec 2013 07:45:27 -0800
changeset 21984 4dff16390b67
parent 21983 586d25bfe206
child 21985 5c22272c888a
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
jdk/src/share/classes/java/math/BigInteger.java
jdk/src/share/classes/java/math/MutableBigInteger.java
--- a/jdk/src/share/classes/java/math/BigInteger.java	Thu Dec 05 07:44:59 2013 -0800
+++ b/jdk/src/share/classes/java/math/BigInteger.java	Thu Dec 05 07:45:27 2013 -0800
@@ -244,13 +244,21 @@
 
     /**
      * 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,
      * the Schoenhage algorithm will be used.  In practice, it appears that the
@@ -2017,8 +2025,8 @@
      * @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 @@
      * @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 @@
      * @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);
--- a/jdk/src/share/classes/java/math/MutableBigInteger.java	Thu Dec 05 07:44:59 2013 -0800
+++ b/jdk/src/share/classes/java/math/MutableBigInteger.java	Thu Dec 05 07:45:27 2013 -0800
@@ -1148,8 +1148,8 @@
     }
 
     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);