151748Smckusick #include "longlong.h" 251748Smckusick 351748Smckusick static int bshift (); 451748Smckusick 551748Smckusick /* Divide a by b, producing quotient q and remainder r. 651748Smckusick 751748Smckusick sizeof a is m 851748Smckusick sizeof b is n 951748Smckusick sizeof q is m - n 1051748Smckusick sizeof r is n 1151748Smckusick 1251748Smckusick The quotient must fit in m - n bytes, i.e., the most significant 1351748Smckusick n digits of a must be less than b, and m must be greater than n. */ 1451748Smckusick 1551748Smckusick /* The name of this used to be __div_internal, 1651748Smckusick but that is too long for SYSV. */ 1751748Smckusick 1851748Smckusick void 1951748Smckusick __bdiv (a, b, q, r, m, n) 2051748Smckusick unsigned short *a, *b, *q, *r; 2151748Smckusick size_t m, n; 2251748Smckusick { 2351748Smckusick unsigned long qhat, rhat; 2451748Smckusick unsigned long acc; 2551748Smckusick unsigned short *u = (unsigned short *) alloca (m); 2651748Smckusick unsigned short *v = (unsigned short *) alloca (n); 2751748Smckusick unsigned short *u0, *u1, *u2; 2851748Smckusick unsigned short *v0; 2951748Smckusick int d, qn; 3051748Smckusick int i, j; 3151748Smckusick 3251748Smckusick m /= sizeof *a; 3351748Smckusick n /= sizeof *b; 3451748Smckusick qn = m - n; 3551748Smckusick 3651748Smckusick /* Remove leading zero digits from divisor, and the same number of 3751748Smckusick digits (which must be zero) from dividend. */ 3851748Smckusick 3951748Smckusick while (b[big_end (n)] == 0) 4051748Smckusick { 4151748Smckusick r[big_end (n)] = 0; 4251748Smckusick 4351748Smckusick a += little_end (2); 4451748Smckusick b += little_end (2); 4551748Smckusick r += little_end (2); 4651748Smckusick m--; 4751748Smckusick n--; 4851748Smckusick 4951748Smckusick /* Check for zero divisor. */ 5051748Smckusick if (n == 0) 51*51750Smckusick { 52*51750Smckusick *r /= n; /* force a divide-by-zero trap */ 53*51750Smckusick return; 54*51750Smckusick } 5551748Smckusick } 5651748Smckusick 5751748Smckusick /* If divisor is a single digit, do short division. */ 5851748Smckusick 5951748Smckusick if (n == 1) 6051748Smckusick { 6151748Smckusick acc = a[big_end (m)]; 6251748Smckusick a += little_end (2); 6351748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 6451748Smckusick { 6551748Smckusick acc = (acc << 16) | a[j]; 6651748Smckusick q[j] = acc / *b; 6751748Smckusick acc = acc % *b; 6851748Smckusick } 6951748Smckusick *r = acc; 7051748Smckusick return; 7151748Smckusick } 7251748Smckusick 7351748Smckusick /* No such luck, must do long division. Shift divisor and dividend 7451748Smckusick left until the high bit of the divisor is 1. */ 7551748Smckusick 7651748Smckusick for (d = 0; d < 16; d++) 7751748Smckusick if (b[big_end (n)] & (1 << (16 - 1 - d))) 7851748Smckusick break; 7951748Smckusick 8051748Smckusick bshift (a, d, u, 0, m); 8151748Smckusick bshift (b, d, v, 0, n); 8251748Smckusick 8351748Smckusick /* Get pointers to the high dividend and divisor digits. */ 8451748Smckusick 8551748Smckusick u0 = u + big_end (m) - big_end (qn); 8651748Smckusick u1 = next_lsd (u0); 8751748Smckusick u2 = next_lsd (u1); 8851748Smckusick u += little_end (2); 8951748Smckusick 9051748Smckusick v0 = v + big_end (n); 9151748Smckusick 9251748Smckusick /* Main loop: find a quotient digit, multiply it by the divisor, 9351748Smckusick and subtract that from the dividend, shifted over the right amount. */ 9451748Smckusick 9551748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 9651748Smckusick { 9751748Smckusick /* Quotient digit initial guess: high 2 dividend digits over high 9851748Smckusick divisor digit. */ 9951748Smckusick 10051748Smckusick if (u0[j] == *v0) 10151748Smckusick { 10251748Smckusick qhat = B - 1; 10351748Smckusick rhat = (unsigned long) *v0 + u1[j]; 10451748Smckusick } 10551748Smckusick else 10651748Smckusick { 10751748Smckusick unsigned long numerator = ((unsigned long) u0[j] << 16) | u1[j]; 10851748Smckusick qhat = numerator / *v0; 10951748Smckusick rhat = numerator % *v0; 11051748Smckusick } 11151748Smckusick 11251748Smckusick /* Now get the quotient right for high 3 dividend digits over 11351748Smckusick high 2 divisor digits. */ 11451748Smckusick 11551748Smckusick while (rhat < B && qhat * *next_lsd (v0) > ((rhat << 16) | u2[j])) 11651748Smckusick { 11751748Smckusick qhat -= 1; 11851748Smckusick rhat += *v0; 11951748Smckusick } 12051748Smckusick 12151748Smckusick /* Multiply quotient by divisor, subtract from dividend. */ 12251748Smckusick 12351748Smckusick acc = 0; 12451748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 12551748Smckusick { 12651748Smckusick acc += (unsigned long) (u + j)[i] - v[i] * qhat; 12751748Smckusick (u + j)[i] = acc & low16; 12851748Smckusick if (acc < B) 12951748Smckusick acc = 0; 13051748Smckusick else 13151748Smckusick acc = (acc >> 16) | -B; 13251748Smckusick } 13351748Smckusick 13451748Smckusick q[j] = qhat; 13551748Smckusick 13651748Smckusick /* Quotient may have been too high by 1. If dividend went negative, 13751748Smckusick decrement the quotient by 1 and add the divisor back. */ 13851748Smckusick 13951748Smckusick if ((signed long) (acc + u0[j]) < 0) 14051748Smckusick { 14151748Smckusick q[j] -= 1; 14251748Smckusick acc = 0; 14351748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 14451748Smckusick { 14551748Smckusick acc += (unsigned long) (u + j)[i] + v[i]; 14651748Smckusick (u + j)[i] = acc & low16; 14751748Smckusick acc = acc >> 16; 14851748Smckusick } 14951748Smckusick } 15051748Smckusick } 15151748Smckusick 15251748Smckusick /* Now the remainder is what's left of the dividend, shifted right 15351748Smckusick by the amount of the normalizing left shift at the top. */ 15451748Smckusick 15551748Smckusick r[big_end (n)] = bshift (u + 1 + little_end (j - 1), 15651748Smckusick 16 - d, 15751748Smckusick r + little_end (2), 15851748Smckusick u[little_end (m - 1)] >> d, 15951748Smckusick n - 1); 16051748Smckusick } 16151748Smckusick 16251748Smckusick /* Left shift U by K giving W; fill the introduced low-order bits with 16351748Smckusick CARRY_IN. Length of U and W is N. Return carry out. K must be 16451748Smckusick in 0 .. 16. */ 16551748Smckusick 16651748Smckusick static int 16751748Smckusick bshift (u, k, w, carry_in, n) 16851748Smckusick unsigned short *u, *w, carry_in; 16951748Smckusick int k, n; 17051748Smckusick { 17151748Smckusick unsigned long acc; 17251748Smckusick int i; 17351748Smckusick 17451748Smckusick if (k == 0) 17551748Smckusick { 176*51750Smckusick while (n-- > 0) 177*51750Smckusick *w++ = *u++; 17851748Smckusick return 0; 17951748Smckusick } 18051748Smckusick 18151748Smckusick acc = carry_in; 18251748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 18351748Smckusick { 18451748Smckusick acc |= (unsigned long) u[i] << k; 18551748Smckusick w[i] = acc & low16; 18651748Smckusick acc = acc >> 16; 18751748Smckusick } 18851748Smckusick return acc; 18951748Smckusick } 190