1*51748Smckusick #include "longlong.h" 2*51748Smckusick 3*51748Smckusick static int bshift (); 4*51748Smckusick 5*51748Smckusick /* Divide a by b, producing quotient q and remainder r. 6*51748Smckusick 7*51748Smckusick sizeof a is m 8*51748Smckusick sizeof b is n 9*51748Smckusick sizeof q is m - n 10*51748Smckusick sizeof r is n 11*51748Smckusick 12*51748Smckusick The quotient must fit in m - n bytes, i.e., the most significant 13*51748Smckusick n digits of a must be less than b, and m must be greater than n. */ 14*51748Smckusick 15*51748Smckusick /* The name of this used to be __div_internal, 16*51748Smckusick but that is too long for SYSV. */ 17*51748Smckusick 18*51748Smckusick void 19*51748Smckusick __bdiv (a, b, q, r, m, n) 20*51748Smckusick unsigned short *a, *b, *q, *r; 21*51748Smckusick size_t m, n; 22*51748Smckusick { 23*51748Smckusick unsigned long qhat, rhat; 24*51748Smckusick unsigned long acc; 25*51748Smckusick unsigned short *u = (unsigned short *) alloca (m); 26*51748Smckusick unsigned short *v = (unsigned short *) alloca (n); 27*51748Smckusick unsigned short *u0, *u1, *u2; 28*51748Smckusick unsigned short *v0; 29*51748Smckusick int d, qn; 30*51748Smckusick int i, j; 31*51748Smckusick 32*51748Smckusick m /= sizeof *a; 33*51748Smckusick n /= sizeof *b; 34*51748Smckusick qn = m - n; 35*51748Smckusick 36*51748Smckusick /* Remove leading zero digits from divisor, and the same number of 37*51748Smckusick digits (which must be zero) from dividend. */ 38*51748Smckusick 39*51748Smckusick while (b[big_end (n)] == 0) 40*51748Smckusick { 41*51748Smckusick r[big_end (n)] = 0; 42*51748Smckusick 43*51748Smckusick a += little_end (2); 44*51748Smckusick b += little_end (2); 45*51748Smckusick r += little_end (2); 46*51748Smckusick m--; 47*51748Smckusick n--; 48*51748Smckusick 49*51748Smckusick /* Check for zero divisor. */ 50*51748Smckusick if (n == 0) 51*51748Smckusick abort (); 52*51748Smckusick } 53*51748Smckusick 54*51748Smckusick /* If divisor is a single digit, do short division. */ 55*51748Smckusick 56*51748Smckusick if (n == 1) 57*51748Smckusick { 58*51748Smckusick acc = a[big_end (m)]; 59*51748Smckusick a += little_end (2); 60*51748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 61*51748Smckusick { 62*51748Smckusick acc = (acc << 16) | a[j]; 63*51748Smckusick q[j] = acc / *b; 64*51748Smckusick acc = acc % *b; 65*51748Smckusick } 66*51748Smckusick *r = acc; 67*51748Smckusick return; 68*51748Smckusick } 69*51748Smckusick 70*51748Smckusick /* No such luck, must do long division. Shift divisor and dividend 71*51748Smckusick left until the high bit of the divisor is 1. */ 72*51748Smckusick 73*51748Smckusick for (d = 0; d < 16; d++) 74*51748Smckusick if (b[big_end (n)] & (1 << (16 - 1 - d))) 75*51748Smckusick break; 76*51748Smckusick 77*51748Smckusick bshift (a, d, u, 0, m); 78*51748Smckusick bshift (b, d, v, 0, n); 79*51748Smckusick 80*51748Smckusick /* Get pointers to the high dividend and divisor digits. */ 81*51748Smckusick 82*51748Smckusick u0 = u + big_end (m) - big_end (qn); 83*51748Smckusick u1 = next_lsd (u0); 84*51748Smckusick u2 = next_lsd (u1); 85*51748Smckusick u += little_end (2); 86*51748Smckusick 87*51748Smckusick v0 = v + big_end (n); 88*51748Smckusick 89*51748Smckusick /* Main loop: find a quotient digit, multiply it by the divisor, 90*51748Smckusick and subtract that from the dividend, shifted over the right amount. */ 91*51748Smckusick 92*51748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 93*51748Smckusick { 94*51748Smckusick /* Quotient digit initial guess: high 2 dividend digits over high 95*51748Smckusick divisor digit. */ 96*51748Smckusick 97*51748Smckusick if (u0[j] == *v0) 98*51748Smckusick { 99*51748Smckusick qhat = B - 1; 100*51748Smckusick rhat = (unsigned long) *v0 + u1[j]; 101*51748Smckusick } 102*51748Smckusick else 103*51748Smckusick { 104*51748Smckusick unsigned long numerator = ((unsigned long) u0[j] << 16) | u1[j]; 105*51748Smckusick qhat = numerator / *v0; 106*51748Smckusick rhat = numerator % *v0; 107*51748Smckusick } 108*51748Smckusick 109*51748Smckusick /* Now get the quotient right for high 3 dividend digits over 110*51748Smckusick high 2 divisor digits. */ 111*51748Smckusick 112*51748Smckusick while (rhat < B && qhat * *next_lsd (v0) > ((rhat << 16) | u2[j])) 113*51748Smckusick { 114*51748Smckusick qhat -= 1; 115*51748Smckusick rhat += *v0; 116*51748Smckusick } 117*51748Smckusick 118*51748Smckusick /* Multiply quotient by divisor, subtract from dividend. */ 119*51748Smckusick 120*51748Smckusick acc = 0; 121*51748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 122*51748Smckusick { 123*51748Smckusick acc += (unsigned long) (u + j)[i] - v[i] * qhat; 124*51748Smckusick (u + j)[i] = acc & low16; 125*51748Smckusick if (acc < B) 126*51748Smckusick acc = 0; 127*51748Smckusick else 128*51748Smckusick acc = (acc >> 16) | -B; 129*51748Smckusick } 130*51748Smckusick 131*51748Smckusick q[j] = qhat; 132*51748Smckusick 133*51748Smckusick /* Quotient may have been too high by 1. If dividend went negative, 134*51748Smckusick decrement the quotient by 1 and add the divisor back. */ 135*51748Smckusick 136*51748Smckusick if ((signed long) (acc + u0[j]) < 0) 137*51748Smckusick { 138*51748Smckusick q[j] -= 1; 139*51748Smckusick acc = 0; 140*51748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 141*51748Smckusick { 142*51748Smckusick acc += (unsigned long) (u + j)[i] + v[i]; 143*51748Smckusick (u + j)[i] = acc & low16; 144*51748Smckusick acc = acc >> 16; 145*51748Smckusick } 146*51748Smckusick } 147*51748Smckusick } 148*51748Smckusick 149*51748Smckusick /* Now the remainder is what's left of the dividend, shifted right 150*51748Smckusick by the amount of the normalizing left shift at the top. */ 151*51748Smckusick 152*51748Smckusick r[big_end (n)] = bshift (u + 1 + little_end (j - 1), 153*51748Smckusick 16 - d, 154*51748Smckusick r + little_end (2), 155*51748Smckusick u[little_end (m - 1)] >> d, 156*51748Smckusick n - 1); 157*51748Smckusick } 158*51748Smckusick 159*51748Smckusick /* Left shift U by K giving W; fill the introduced low-order bits with 160*51748Smckusick CARRY_IN. Length of U and W is N. Return carry out. K must be 161*51748Smckusick in 0 .. 16. */ 162*51748Smckusick 163*51748Smckusick static int 164*51748Smckusick bshift (u, k, w, carry_in, n) 165*51748Smckusick unsigned short *u, *w, carry_in; 166*51748Smckusick int k, n; 167*51748Smckusick { 168*51748Smckusick unsigned long acc; 169*51748Smckusick int i; 170*51748Smckusick 171*51748Smckusick if (k == 0) 172*51748Smckusick { 173*51748Smckusick bcopy (u, w, n * sizeof *u); 174*51748Smckusick return 0; 175*51748Smckusick } 176*51748Smckusick 177*51748Smckusick acc = carry_in; 178*51748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 179*51748Smckusick { 180*51748Smckusick acc |= (unsigned long) u[i] << k; 181*51748Smckusick w[i] = acc & low16; 182*51748Smckusick acc = acc >> 16; 183*51748Smckusick } 184*51748Smckusick return acc; 185*51748Smckusick } 186