/* int _DivDec80Bit(pDst,pSrc1,pSrc2); * * ARGUMENT * DEC *pDst; * DEC *pSrc1,pSrc2; * * DESCRIPTION * Divides pDst = pSrc1 / pSrc2. * * SIDE EFFECTS * None. * * RETURNS * Returns GM_SUCCESS if successful, otherwise the error code. * wGMError is not changed. * * AUTHOR * Jared Levy 05-JAN-1987 17:30 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * */ #include #include "gm.h" #include "gmsystem.h" int _DivDec80Bit(c,a,b) DEC *c; DEC *a,*b; { register int i,t; int maxp, p=0, mag2a, mag2b; unsigned SHORT an[14], bn[6], *cn, ad[5], as[14]; /* check that b is nonzero */ if (_MacIsDecZ(b)) return(GM_DIV0); /* check whether scr1 is zero */ if (_MacIsDecZ(a)) { _MacDCopy(c,a); return(GM_SUCCESS); } /* sets c = a / b, where a and b are positive DEC numbers, and the result is stored in c */ bn[0]=b->dc.sl[0]; bn[1]=b->dc.sl[1]; bn[2]=b->dc.sl[2]; bn[3]=b->dc.sl[3]; bn[4]=b->dc.msd; bn[5]=0; cn = c->dc.sl; an[0]=a->dc.sl[0]; an[1]=a->dc.sl[1]; an[2]=a->dc.sl[2]; an[3]=a->dc.sl[3]; an[4]=a->dc.msd; an[5] = 0; an[6] = 0; an[7] = 0; an[8] = 0; an[9] = 0; an[10]= 0; an[11]= 0; maxp = GM_IMAXID - (a->dc.id - b->dc.id); if (maxp > 0) { /* The following code uses up most of the time involved in divisions. It starts with two 64-bit number integers an and bh, both positive, along with an integer maxp. Two values are returned: a nonnegative integer p and a 160-bit number as = an * 10^p. p is the largest number satisfying the conditions (1) as < 2^160, (2) the highest 80 bits of as are less than bh (3) p <= maxp. */ i = 4; while (an[i] == 0) i--; mag2a = 16 * i; t = an[i]>>1; while (t) { t=t>>1; mag2a++; } i = 4; while ((bn[i] == 0) && (i>0)) i--; mag2b = 16 * i; t = bn[i]>>1; while (t) { t=t>>1; mag2b++; } p = (78 + mag2b - mag2a) * 3 / 10; if (p>maxp) p=maxp; if (p != 0) _MulUnsArrByPwrOf10(an,p,10); if (p != maxp) { for(i=0; i<14; i++) { as[i] = an[i]; } i = _MulUnsArrByPwrOf10(as,1,10); ad[0]=as[5]; ad[1]=as[6]; ad[2]=as[7]; ad[3]=as[8]; ad[4]=as[9]; _DoubleUnsArr(ad, 5); if (as[4]&0x8000) ad[0]=ad[0]+1; if ((i == GM_SUCCESS) && (_CompareUnsArr(ad,bn,5) == -1)) { p++; for(i=0; i<10; i++) an[i] = as[i]; } } /* p != maxp */ } /* maxp > 0 */ _DivUns10ArrByUns5Arr(cn,an,bn); /* adjust implied decimal to correct value */ i = a->dc.id - b->dc.id + p; if (idc.id = i; /* if the signs of the sources are different, c=-c */ c->dc.attr = (a->dc.attr^b->dc.attr); return(GM_SUCCESS); }