Hi there,

I came across a case in BigDecimal division where the dividend ends up getting 
mutated, which is rather strange for a seemingly immutable class! (It's a 
subset of the cases where the Burnikel-Ziegler algorithm is used, I haven't 
done the analysis to find out under which exact conditions it's triggered.)

The attached patch - against the JDK8 version - should fix the problem, at the 
cost of an extra array copy.  Could somebody review and/or comment please?

Thanks,
Robert

--- MutableBigInteger.java      2014-09-04 09:42:23.426815000 +0200
+++ MutableBigInteger.java.patched      2014-09-04 09:46:21.344132000 +0200
@@ -1261,19 +1261,20 @@
             int sigma = (int) Math.max(0, n32 - b.bitLength());   // step 3: 
sigma = max{T | (2^T)*B < beta^n}
             MutableBigInteger bShifted = new MutableBigInteger(b);
             bShifted.safeLeftShift(sigma);   // step 4a: shift b so its length 
is a multiple of n
-            safeLeftShift(sigma);     // step 4b: shift this by the same amount
+            MutableBigInteger aShifted = new MutableBigInteger (this);
+            aShifted.safeLeftShift(sigma);     // step 4b: shift a by the same 
amount
-            // step 5: t is the number of blocks needed to accommodate this 
plus one additional bit
-            int t = (int) ((bitLength()+n32) / n32);
+            // step 5: t is the number of blocks needed to accommodate a plus 
one additional bit
+            int t = (int) ((aShifted.bitLength()+n32) / n32);
             if (t < 2) {
                 t = 2;
             }
-            // step 6: conceptually split this into blocks a[t-1], ..., a[0]
-            MutableBigInteger a1 = getBlock(t-1, t, n);   // the most 
significant block of this
+            // step 6: conceptually split a into blocks a[t-1], ..., a[0]
+            MutableBigInteger a1 = aShifted.getBlock(t-1, t, n);   // the most 
significant block of a
             // step 7: z[t-2] = [a[t-1], a[t-2]]
-            MutableBigInteger z = getBlock(t-2, t, n);    // the second to 
most significant block
+            MutableBigInteger z = aShifted.getBlock(t-2, t, n);    // the 
second to most significant block
             z.addDisjoint(a1, n);   // z[t-2]
             // do schoolbook division on blocks, dividing 2-block numbers by 
1-block numbers
@@ -1284,7 +1285,7 @@
                 ri = z.divide2n1n(bShifted, qi);
                 // step 8b: z = [ri, a[i-1]]
-                z = getBlock(i-1, t, n);   // a[i-1]
+                z = aShifted.getBlock(i-1, t, n);   // a[i-1]
                 z.addDisjoint(ri, n);
                 quotient.addShifted(qi, i*n);   // update q (part of step 9)
             }
@@ -1292,7 +1293,7 @@
             ri = z.divide2n1n(bShifted, qi);
             quotient.add(qi);
-           ri.rightShift(sigma);   // step 9: this and b were shifted, so 
shift back
+           ri.rightShift(sigma);   // step 9: a and b were shifted, so shift 
back
             return ri;
         }
     }

Reply via email to