5 /* division ala knuth, seminumerical algorithms, pp 237-238 */
6 /* the numbers are stored backwards to what knuth expects so j */
7 /* counts down rather than up. */
10 mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder)
13 mpdigit qd, *up, *vp, *qp;
21 if(mpmagcmp(dividend, divisor) < 0){
23 mpassign(dividend, remainder);
25 mpassign(mpzero, quotient);
29 /* D1: shift until divisor, v, has hi bit set (needed to make trial */
30 /* divisor accurate) */
31 qd = divisor->p[divisor->top-1];
32 for(s = 0; (qd & mpdighi) == 0; s++)
34 u = mpnew((dividend->top+2)*Dbits + s);
35 if(s == 0 && divisor != quotient && divisor != remainder) {
36 mpassign(dividend, u);
39 mpleft(dividend, s, u);
40 v = mpnew(divisor->top*Dbits);
41 mpleft(divisor, s, v);
47 /* D1a: make sure high digit of dividend is less than high digit of divisor */
53 /* storage for multiplies */
58 mpbits(quotient, (u->top - v->top)*Dbits);
59 quotient->top = u->top - v->top;
60 qp = quotient->p+quotient->top-1;
63 /* D2, D7: loop on length of dividend */
64 for(j = u->top; j > vn; j--){
66 /* D3: calculate trial divisor */
67 mpdigdiv(up-1, *vp, &qd);
69 /* D3a: rule out trial divisors 2 greater than real divisor */
71 memset(t->p, 0, 3*Dbytes); /* mpvecdigmuladd adds to what's there */
72 mpvecdigmuladd(vp-1, 2, qd, t->p);
73 if(mpveccmp(t->p, 3, up-2, 3) > 0)
79 /* D4: u -= v*qd << j*Dbits */
80 sign = mpvecdigmulsub(v->p, vn, qd, up-vn);
83 /* D6: trial divisor was too high, add back borrowed */
84 /* value and decrease divisor */
85 mpvecadd(up-vn, vn+1, v->p, vn, up-vn);
89 /* D5: save quotient digit */
93 /* push top of u down one */
99 if(dividend->sign != divisor->sign)
103 if(remainder != nil){
104 mpright(u, s, remainder); /* u is the remainder shifted */
105 remainder->sign = dividend->sign;