//Sets a = b / c, where a and c are digits.
//Lengths: b[2].
//Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be normalized.
void NN_DigitDiv (NN_DIGIT *a, NN_DIGIT b[2], NN_DIGIT c)
{
NN_DIGIT t_h, t_l, u, v, aHigh, aLow;
t_l = b[0];
t_h = b[1];
//Underestimate high half of quotient and subtract.
if ((c >> 16) == 0x0000ffff) aHigh = (t_h >> 16);
else aHigh = ((t_h / ((c >> 16) + 1)) & 0x0000ffff);
u = aHigh * (c & 0x0000ffff);
v = aHigh * (c >> 16);
if ((u << 16) > t_l) t_h--;
t_l -= (u << 16);
t_h -= (u >> 16);
t_h -= v;
//Correct estimate.
while ((t_h > (c >> 16)) || ((t_h == (c >> 16)) && (t_l >= (c << 16)))){
if ((c << 16) > t_l) t_h--;
t_l -= (c << 16);
t_h -= (c >> 16);
aHigh = ((aHigh + 1) & 0x0000ffff);
}
//Underestimate low half of quotient and subtract.
if ((c >> 16) == 0x0000ffff) aLow = (t_h & 0x0000ffff);
else aLow = ((((t_h << 16) + (t_l >> 16)) / ((c >> 16) + 1)) & 0x0000ffff);
u = aLow * (c & 0x0000ffff);
v = aLow * (c >> 16);
if (u > t_l) t_h--;
t_l -= u;
if ((v << 16) > t_l) t_h--;
t_l -= (v << 16);
t_h -= (v >> 16);
//Correct estimate.
while ((t_h > 0) || ((t_h == 0) && t_l >= c)) {if (c > t_l) t_h--;
t_l -= c;
aLow = ((aLow + 1) & 0x0000ffff);
}
*a = ((aHigh << 16) + aLow);
}