public static BigInteger [] multiByteDivide (BigInteger bi1, BigInteger bi2)
{
if (Kernel.Compare (bi1, bi2) == Sign.Negative)
return new BigInteger [2] { 0, new BigInteger (bi1) };
bi1.Normalize (); bi2.Normalize ();
if (bi2.length == 1)
return DwordDivMod (bi1, bi2.data [0]);
uint remainderLen = bi1.length + 1;
int divisorLen = (int)bi2.length + 1;
uint mask = 0x80000000;
uint val = bi2.data [bi2.length - 1];
int shift = 0;
int resultPos = (int)bi1.length - (int)bi2.length;
while (mask != 0 && (val & mask) == 0) {
shift++; mask >>= 1;
}
BigInteger quot = new BigInteger (Sign.Positive, bi1.length - bi2.length + 1);
BigInteger rem = (bi1 << shift);
uint [] remainder = rem.data;
bi2 = bi2 << shift;
int j = (int)(remainderLen - bi2.length);
int pos = (int)remainderLen - 1;
uint firstDivisorByte = bi2.data [bi2.length-1];
ulong secondDivisorByte = bi2.data [bi2.length-2];
while (j > 0) {
ulong dividend = ((ulong)remainder [pos] << 32) + (ulong)remainder [pos-1];
ulong q_hat = dividend / (ulong)firstDivisorByte;
ulong r_hat = dividend % (ulong)firstDivisorByte;
do {
if (q_hat == 0x100000000 ||
(q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
q_hat--;
r_hat += (ulong)firstDivisorByte;
if (r_hat < 0x100000000)
continue;
}
break;
} while (true);
//
// At this point, q_hat is either exact, or one too large
// (more likely to be exact) so, we attempt to multiply the
// divisor by q_hat, if we get a borrow, we just subtract
// one from q_hat and add the divisor back.
//
uint t;
uint dPos = 0;
int nPos = pos - divisorLen + 1;
ulong mc = 0;
uint uint_q_hat = (uint)q_hat;
do {
mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
t = remainder [nPos];
remainder [nPos] -= (uint)mc;
mc >>= 32;
if (remainder [nPos] > t) mc++;
dPos++; nPos++;
} while (dPos < divisorLen);
nPos = pos - divisorLen + 1;
dPos = 0;
// Overestimate
if (mc != 0) {
uint_q_hat--;
ulong sum = 0;
do {
sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
remainder [nPos] = (uint)sum;
sum >>= 32;
dPos++; nPos++;
} while (dPos < divisorLen);
}
quot.data [resultPos--] = (uint)uint_q_hat;
pos--;
j--;
}
quot.Normalize ();
rem.Normalize ();
BigInteger [] ret = new BigInteger [2] { quot, rem };
if (shift != 0)
ret [1] >>= shift;
return ret;
}