private static void multiByteDivide(BigInteger bi1, BigInteger bi2,
BigInteger outQuotient, BigInteger outRemainder)
{
uint[] result = new uint[maxLength];
int remainderLen = bi1.dataLength + 1;
uint[] remainder = new uint[remainderLen];
uint mask = 0x80000000;
uint val = bi2.data[bi2.dataLength - 1];
int shift = 0, resultPos = 0;
while (mask != 0 && (val & mask) == 0) {
shift++; mask >>= 1;
}
//Console.WriteLine("shift = {0}", shift);
//Console.WriteLine("Before bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);
for (int i = 0; i < bi1.dataLength; i++)
remainder[i] = bi1.data[i];
shiftLeft(remainder, shift);
bi2 = bi2 << shift;
/*
Console.WriteLine("bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);
Console.WriteLine("dividend = " + bi1 + "\ndivisor = " + bi2);
for(int q = remainderLen - 1; q >= 0; q--)
Console.Write("{0:x2}", remainder[q]);
Console.WriteLine();
*/
int j = remainderLen - bi2.dataLength;
int pos = remainderLen - 1;
ulong firstDivisorByte = bi2.data[bi2.dataLength - 1];
ulong secondDivisorByte = bi2.data[bi2.dataLength - 2];
int divisorLen = bi2.dataLength + 1;
uint[] dividendPart = new uint[divisorLen];
while (j > 0) {
ulong dividend = ((ulong)remainder[pos] << 32) + (ulong)remainder[pos - 1];
//Console.WriteLine("dividend = {0}", dividend);
ulong q_hat = dividend / firstDivisorByte;
ulong r_hat = dividend % firstDivisorByte;
//Console.WriteLine("q_hat = {0:X}, r_hat = {1:X}", q_hat, r_hat);
bool done = false;
while (!done) {
done = true;
if (q_hat == 0x100000000 ||
(q_hat * secondDivisorByte) > ((r_hat << 32) + remainder[pos - 2])) {
q_hat--;
r_hat += firstDivisorByte;
if (r_hat < 0x100000000)
done = false;
}
}
for (int h = 0; h < divisorLen; h++)
dividendPart[h] = remainder[pos - h];
BigInteger kk = new BigInteger(dividendPart);
BigInteger ss = bi2 * (long)q_hat;
//Console.WriteLine("ss before = " + ss);
while (ss > kk) {
q_hat--;
ss -= bi2;
//Console.WriteLine(ss);
}
BigInteger yy = kk - ss;
//Console.WriteLine("ss = " + ss);
//Console.WriteLine("kk = " + kk);
//Console.WriteLine("yy = " + yy);
for (int h = 0; h < divisorLen; h++)
remainder[pos - h] = yy.data[bi2.dataLength - h];
/*
Console.WriteLine("dividend = ");
for(int q = remainderLen - 1; q >= 0; q--)
Console.Write("{0:x2}", remainder[q]);
Console.WriteLine("\n************ q_hat = {0:X}\n", q_hat);
*/
result[resultPos++] = (uint)q_hat;
pos--;
j--;
}
outQuotient.dataLength = resultPos;
int y = 0;
for (int x = outQuotient.dataLength - 1; x >= 0; x--, y++)
outQuotient.data[y] = result[x];
for (; y < maxLength; y++)
outQuotient.data[y] = 0;
while (outQuotient.dataLength > 1 && outQuotient.data[outQuotient.dataLength - 1] == 0)
outQuotient.dataLength--;
if (outQuotient.dataLength == 0)
outQuotient.dataLength = 1;
outRemainder.dataLength = shiftRight(remainder, shift);
for (y = 0; y < outRemainder.dataLength; y++)
outRemainder.data[y] = remainder[y];
for (; y < maxLength; y++)
outRemainder.data[y] = 0;
}