public uint DivRem(BigInteger bi) {
AssertValid();
bi.AssertValid();
Debug.Assert((object)this != (object)bi);
int idx, cu;
uint uQuo, wCarry;
int wT;
uint uT, uHi, uLo;
cu = bi.length;
Debug.Assert(length <= cu);
if (length < cu) {
return 0;
}
// Get a lower bound on the quotient.
uQuo = (uint)(digits[cu - 1] / (bi.digits[cu - 1] + 1));
Debug.Assert(uQuo >= 0 && uQuo <= 9);
// Handle 0 and 1 as special cases.
switch (uQuo) {
case 0:
break;
case 1:
Subtract(bi);
break;
default:
uHi = 0;
wCarry = 1;
for (idx = 0; idx < cu; idx++) {
Debug.Assert(0 == wCarry || 1 == wCarry);
// Compute the product.
uLo = MulU(uQuo, bi.digits[idx], out uT);
uHi = uT + AddU(ref uLo, uHi);
// Subtract the product. See note in BigInteger.Subtract.
if (0 != uLo || 0 == wCarry) {
wCarry = AddU(ref digits[idx], ~uLo + wCarry);
}
}
Debug.Assert(1 == wCarry);
Debug.Assert(idx == cu);
// Trim off zeros.
while (--idx >= 0 && 0 == digits[idx]) {
}
length = idx + 1;
break;
}
if (uQuo < 9 && (wT = CompareTo(bi)) >= 0) {
// Quotient was off too small (by one).
uQuo++;
if (0 == wT) {
length = 0;
} else {
Subtract(bi);
}
}
Debug.Assert(CompareTo(bi) < 0);
return uQuo;
}