static void Div( Digits numer , Digit den , Reciprocal recip , Digits q , int n , Digits r ) { Digit carry = 0; int nLeft = n; if (nLeft > 0 && numer[nLeft - 1] < den) { nLeft--; carry = numer[nLeft]; if (q != null) { q[nLeft] = 0; } } if (recip == null && nLeft < 2) { for (int i = nLeft; i-- != 0;) { Digit qest = 0; Digit2.Div((UInt64)carry << Digit.BitN | numer[i] , den , out qest , out carry); if (q != null) { q[i] = qest; } } } else { if (recip == null) { recip = new Reciprocal(); DivPrecondition(new Digits(new Digit[] { den }), 1, recip); } for (int i = nLeft; i-- != 0;) { Digit qest = 0; Digit2.Div((UInt64)carry << Digit.BitN | numer[i] , den , recip , out qest , out carry); if (q != null) { q[i] = qest; } } } r[0] = carry; }
DivPrecondition(Digits denom, int denomN, Reciprocal recip) { if (denom == null) { throw new ArgumentNullException(); } if (denomN == 0 || denom[denomN - 1] == 0) { throw new ArgumentException(); } int recipBitShift = Digit.BitN - Digit.SigBitN(denom[denomN - 1]); Digit dlead2 = denom[denomN - 1] , dlead1 = denomN >= 2 ? denom[denomN - 2] : 0 , dlead0 = denomN >= 3 ? denom[denomN - 3] : 0 , dShiftHi = dlead2 << recipBitShift | dlead1 >> 1 >> Digit.BitN - 1 - recipBitShift , dShiftLo = dlead1 << recipBitShift | dlead0 >> 1 >> Digit.BitN - 1 - recipBitShift; Digit recipMpy, r; Digit2.Div((UInt64)(Digit.MaxValue - dShiftHi) << Digit.BitN | Digit.MaxValue - dShiftLo , dShiftHi , out recipMpy , out r); if (Digit2.Hi((UInt64)recipMpy * dShiftLo) > r) { recipMpy -= 1; } r = (Digit.MaxValue >> recipBitShift) - denom[denomN - 1]; for (int id = denomN; id-- != 0 && r < recipMpy;) { UInt64 test1 = (UInt64)r << Digit.BitN | Digit.MaxValue - (id > 0 ? denom[id - 1] : 0) , test2 = (UInt64)recipMpy * denom[id]; if (test2 > test1) { recipMpy -= 1; break; } test1 = test1 - test2; r = Digit2.Lo(test1); if (Digit2.Hi(test1) != 0) { break; } } recip._shiftBitN = recipBitShift; recip._multiplier = recipMpy; }