153430Sbostic /*- 253430Sbostic * Copyright (c) 1992 The Regents of the University of California. 353430Sbostic * All rights reserved. 453430Sbostic * 553430Sbostic * %sccs.include.redist.c% 653430Sbostic */ 753430Sbostic 853430Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*53455Sbostic static char sccsid[] = "@(#)qdivrem.c 5.4 (Berkeley) 05/12/92"; 1053430Sbostic #endif /* LIBC_SCCS and not lint */ 1153430Sbostic 12*53455Sbostic #include <unistd.h> 13*53455Sbostic 1451748Smckusick #include "longlong.h" 1551748Smckusick 1651748Smckusick static int bshift (); 1751748Smckusick 1851748Smckusick /* Divide a by b, producing quotient q and remainder r. 1951748Smckusick 2051748Smckusick sizeof a is m 2151748Smckusick sizeof b is n 2251748Smckusick sizeof q is m - n 2351748Smckusick sizeof r is n 2451748Smckusick 2551748Smckusick The quotient must fit in m - n bytes, i.e., the most significant 2651748Smckusick n digits of a must be less than b, and m must be greater than n. */ 2751748Smckusick 2851748Smckusick /* The name of this used to be __div_internal, 2951748Smckusick but that is too long for SYSV. */ 3051748Smckusick 3151748Smckusick void 3251748Smckusick __bdiv (a, b, q, r, m, n) 3351748Smckusick unsigned short *a, *b, *q, *r; 34*53455Sbostic unsigned long m, n; 3551748Smckusick { 3651748Smckusick unsigned long qhat, rhat; 3751748Smckusick unsigned long acc; 38*53455Sbostic unsigned short array[12]; 39*53455Sbostic unsigned short *u, *v, *u0, *u1, *u2; 4051748Smckusick unsigned short *v0; 4151748Smckusick int d, qn; 4251748Smckusick int i, j; 4351748Smckusick 44*53455Sbostic if (m > 16 || n > 8) { 45*53455Sbostic #ifdef KERNEL 46*53455Sbostic panic("bdiv: out of space"); 47*53455Sbostic #else 48*53455Sbostic #define EMSG "bdiv: out of space." 49*53455Sbostic (void)write(STDERR_FILENO, EMSG, sizeof(EMSG) - 1); 50*53455Sbostic abort(); 51*53455Sbostic #endif 52*53455Sbostic } 53*53455Sbostic u = &array[0]; 54*53455Sbostic v = &array[m / sizeof(unsigned short)]; 5551748Smckusick m /= sizeof *a; 5651748Smckusick n /= sizeof *b; 5751748Smckusick qn = m - n; 5851748Smckusick 5951748Smckusick /* Remove leading zero digits from divisor, and the same number of 6051748Smckusick digits (which must be zero) from dividend. */ 6151748Smckusick 6251748Smckusick while (b[big_end (n)] == 0) 6351748Smckusick { 6451748Smckusick r[big_end (n)] = 0; 6551748Smckusick 6651748Smckusick a += little_end (2); 6751748Smckusick b += little_end (2); 6851748Smckusick r += little_end (2); 6951748Smckusick m--; 7051748Smckusick n--; 7151748Smckusick 7251748Smckusick /* Check for zero divisor. */ 7351748Smckusick if (n == 0) 7451750Smckusick { 7551750Smckusick *r /= n; /* force a divide-by-zero trap */ 7651750Smckusick return; 7751750Smckusick } 7851748Smckusick } 7951748Smckusick 8051748Smckusick /* If divisor is a single digit, do short division. */ 8151748Smckusick 8251748Smckusick if (n == 1) 8351748Smckusick { 8451748Smckusick acc = a[big_end (m)]; 8551748Smckusick a += little_end (2); 8651748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 8751748Smckusick { 8851748Smckusick acc = (acc << 16) | a[j]; 8951748Smckusick q[j] = acc / *b; 9051748Smckusick acc = acc % *b; 9151748Smckusick } 9251748Smckusick *r = acc; 9351748Smckusick return; 9451748Smckusick } 9551748Smckusick 9651748Smckusick /* No such luck, must do long division. Shift divisor and dividend 9751748Smckusick left until the high bit of the divisor is 1. */ 9851748Smckusick 9951748Smckusick for (d = 0; d < 16; d++) 10051748Smckusick if (b[big_end (n)] & (1 << (16 - 1 - d))) 10151748Smckusick break; 10251748Smckusick 10351748Smckusick bshift (a, d, u, 0, m); 10451748Smckusick bshift (b, d, v, 0, n); 10551748Smckusick 10651748Smckusick /* Get pointers to the high dividend and divisor digits. */ 10751748Smckusick 10851748Smckusick u0 = u + big_end (m) - big_end (qn); 10951748Smckusick u1 = next_lsd (u0); 11051748Smckusick u2 = next_lsd (u1); 11151748Smckusick u += little_end (2); 11251748Smckusick 11351748Smckusick v0 = v + big_end (n); 11451748Smckusick 11551748Smckusick /* Main loop: find a quotient digit, multiply it by the divisor, 11651748Smckusick and subtract that from the dividend, shifted over the right amount. */ 11751748Smckusick 11851748Smckusick for (j = big_end (qn); is_not_lsd (j, qn); j = next_lsd (j)) 11951748Smckusick { 12051748Smckusick /* Quotient digit initial guess: high 2 dividend digits over high 12151748Smckusick divisor digit. */ 12251748Smckusick 12351748Smckusick if (u0[j] == *v0) 12451748Smckusick { 12551748Smckusick qhat = B - 1; 12651748Smckusick rhat = (unsigned long) *v0 + u1[j]; 12751748Smckusick } 12851748Smckusick else 12951748Smckusick { 13051748Smckusick unsigned long numerator = ((unsigned long) u0[j] << 16) | u1[j]; 13151748Smckusick qhat = numerator / *v0; 13251748Smckusick rhat = numerator % *v0; 13351748Smckusick } 13451748Smckusick 13551748Smckusick /* Now get the quotient right for high 3 dividend digits over 13651748Smckusick high 2 divisor digits. */ 13751748Smckusick 13851748Smckusick while (rhat < B && qhat * *next_lsd (v0) > ((rhat << 16) | u2[j])) 13951748Smckusick { 14051748Smckusick qhat -= 1; 14151748Smckusick rhat += *v0; 14251748Smckusick } 14351748Smckusick 14451748Smckusick /* Multiply quotient by divisor, subtract from dividend. */ 14551748Smckusick 14651748Smckusick acc = 0; 14751748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 14851748Smckusick { 14951748Smckusick acc += (unsigned long) (u + j)[i] - v[i] * qhat; 15051748Smckusick (u + j)[i] = acc & low16; 15151748Smckusick if (acc < B) 15251748Smckusick acc = 0; 15351748Smckusick else 15451748Smckusick acc = (acc >> 16) | -B; 15551748Smckusick } 15651748Smckusick 15751748Smckusick q[j] = qhat; 15851748Smckusick 15951748Smckusick /* Quotient may have been too high by 1. If dividend went negative, 16051748Smckusick decrement the quotient by 1 and add the divisor back. */ 16151748Smckusick 16251748Smckusick if ((signed long) (acc + u0[j]) < 0) 16351748Smckusick { 16451748Smckusick q[j] -= 1; 16551748Smckusick acc = 0; 16651748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 16751748Smckusick { 16851748Smckusick acc += (unsigned long) (u + j)[i] + v[i]; 16951748Smckusick (u + j)[i] = acc & low16; 17051748Smckusick acc = acc >> 16; 17151748Smckusick } 17251748Smckusick } 17351748Smckusick } 17451748Smckusick 17551748Smckusick /* Now the remainder is what's left of the dividend, shifted right 17651748Smckusick by the amount of the normalizing left shift at the top. */ 17751748Smckusick 17851748Smckusick r[big_end (n)] = bshift (u + 1 + little_end (j - 1), 17951748Smckusick 16 - d, 18051748Smckusick r + little_end (2), 18151748Smckusick u[little_end (m - 1)] >> d, 18251748Smckusick n - 1); 18351748Smckusick } 18451748Smckusick 18551748Smckusick /* Left shift U by K giving W; fill the introduced low-order bits with 18651748Smckusick CARRY_IN. Length of U and W is N. Return carry out. K must be 18751748Smckusick in 0 .. 16. */ 18851748Smckusick 18951748Smckusick static int 19051748Smckusick bshift (u, k, w, carry_in, n) 19151748Smckusick unsigned short *u, *w, carry_in; 19251748Smckusick int k, n; 19351748Smckusick { 19451748Smckusick unsigned long acc; 19551748Smckusick int i; 19651748Smckusick 19751748Smckusick if (k == 0) 19851748Smckusick { 19951750Smckusick while (n-- > 0) 20051750Smckusick *w++ = *u++; 20151748Smckusick return 0; 20251748Smckusick } 20351748Smckusick 20451748Smckusick acc = carry_in; 20551748Smckusick for (i = little_end (n); is_not_msd (i, n); i = next_msd (i)) 20651748Smckusick { 20751748Smckusick acc |= (unsigned long) u[i] << k; 20851748Smckusick w[i] = acc & low16; 20951748Smckusick acc = acc >> 16; 21051748Smckusick } 21151748Smckusick return acc; 21251748Smckusick } 213