xref: /plan9/sys/src/libmp/port/mpdigdiv.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include "os.h"
2*7dd7cddfSDavid du Colombier #include <mp.h>
3*7dd7cddfSDavid du Colombier #include "dat.h"
4*7dd7cddfSDavid du Colombier 
5*7dd7cddfSDavid du Colombier //
6*7dd7cddfSDavid du Colombier //	divide two digits by one and return quotient
7*7dd7cddfSDavid du Colombier //
8*7dd7cddfSDavid du Colombier void
mpdigdiv(mpdigit * dividend,mpdigit divisor,mpdigit * quotient)9*7dd7cddfSDavid du Colombier mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient)
10*7dd7cddfSDavid du Colombier {
11*7dd7cddfSDavid du Colombier 	mpdigit hi, lo, q, x, y;
12*7dd7cddfSDavid du Colombier 	int i;
13*7dd7cddfSDavid du Colombier 
14*7dd7cddfSDavid du Colombier 	hi = dividend[1];
15*7dd7cddfSDavid du Colombier 	lo = dividend[0];
16*7dd7cddfSDavid du Colombier 
17*7dd7cddfSDavid du Colombier 	// return highest digit value if the result >= 2**32
18*7dd7cddfSDavid du Colombier 	if(hi >= divisor || divisor == 0){
19*7dd7cddfSDavid du Colombier 		divisor = 0;
20*7dd7cddfSDavid du Colombier 		*quotient = ~divisor;
21*7dd7cddfSDavid du Colombier 		return;
22*7dd7cddfSDavid du Colombier 	}
23*7dd7cddfSDavid du Colombier 
24*7dd7cddfSDavid du Colombier 	// at this point we know that hi < divisor
25*7dd7cddfSDavid du Colombier 	// just shift and subtract till we're done
26*7dd7cddfSDavid du Colombier 	q = 0;
27*7dd7cddfSDavid du Colombier 	x = divisor;
28*7dd7cddfSDavid du Colombier 	for(i = Dbits-1; hi > 0 && i >= 0; i--){
29*7dd7cddfSDavid du Colombier 		x >>= 1;
30*7dd7cddfSDavid du Colombier 		if(x > hi)
31*7dd7cddfSDavid du Colombier 			continue;
32*7dd7cddfSDavid du Colombier 		y = divisor<<i;
33*7dd7cddfSDavid du Colombier 		if(x == hi && y > lo)
34*7dd7cddfSDavid du Colombier 			continue;
35*7dd7cddfSDavid du Colombier 		if(y > lo)
36*7dd7cddfSDavid du Colombier 			hi--;
37*7dd7cddfSDavid du Colombier 		lo -= y;
38*7dd7cddfSDavid du Colombier 		hi -= x;
39*7dd7cddfSDavid du Colombier 		q |= 1<<i;
40*7dd7cddfSDavid du Colombier 	}
41*7dd7cddfSDavid du Colombier 	q += lo/divisor;
42*7dd7cddfSDavid du Colombier 	*quotient = q;
43*7dd7cddfSDavid du Colombier }
44