/* int _SubDec80Bit(pDst,pSrc1,pSrc2) * * ARGUMENT * pDst is a pointer to the destination DEC structure. * pSrc1 is a ptr to the source1 DEC structure. * pSrc2 is a ptr to the source2 DEC structure. * * DESCRIPTION * Subtracts the value in pSrc2 from the value in pSrc1 * and puts the result in pDst DEC structure. The difference is calculated * to the maximum possible accuracy. * * SIDE EFFECTS * On overflow, the dest value is indeterminate. * * RETURNS * Returns GM_SUCCESS unless an error, in which case the specific * error code is returned. * * Note: uses an assembly language routine for the actual math * * AUTHOR * Andy Anderson 13-JUL-87 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * */ #include #include "gm.h" #include "gmsystem.h" int _SubDec80Bit(pDst,pSrc1,pSrc2) DEC *pDst; DEC *pSrc1,*pSrc2; { DEC t1, t2, *pts; register int i,j; int s1, s2; /* if the source id's are different, make them equal with as much accuracy as is possible, and protect source fields from change */ /* line up decimal places */ i = pSrc1->dc.id-pSrc2->dc.id; if (i) { pts = &t1; _MacDCopy(pts, pSrc1); pts = &t2; _MacDCopy(pts, pSrc2); _MacDChgs(pts); if (i<0) { pSrc1 = &t1; pSrc2 = &t2; i = -i; } else { pSrc2 = &t1; pSrc1 = &t2; } j = _MulUnsArrByPwrOf10Limited( pSrc1->dc.sl, i, 5); pSrc1->dc.id += j; if (jdc.sl, 5, i-j); } s1 = pSrc1->dc.attr & 0x0001; s2 = pSrc2->dc.attr & 0x0001; if (i==0) s2=1-s2; /* Subtract the numbers */ pDst->dc.id = pSrc1->dc.id; if (s1 == s2) { /* Add absolute values if signs are equal */ _AddUnsArrToUnsArr(pSrc1->dc.sl, pSrc2->dc.sl, pDst->dc.sl,5); /* if the first addition is an overflow, round down and try again */ if (pDst->dc.sl[3] >= 32768L) { if (pSrc1->dc.id <= GM_IMINID) return(GM_OVERFLOW); _DivUnsArrByUns(pDst->dc.sl, 10, 5); pDst->dc.id--; } /* sign of pDst same as sign of sources */ pDst->dc.attr = s1; } else { /* subtract larger absolute value from smaller if signs are different */ if (_CompareUnsArr(pSrc1->dc.sl, pSrc2->dc.sl, 5) >= 0) { /* pSrc1 has larger absolute value */ (void) _SubUnsArrFromUnsArr(pSrc1->dc.sl, pSrc2->dc.sl, pDst->dc.sl,5); /* sum has same sign as pSrc1 */ pDst->dc.attr = s1; } else { /* pSrc2 has larger absolute value */ (void) _SubUnsArrFromUnsArr(pSrc2->dc.sl, pSrc1->dc.sl, pDst->dc.sl,5); /* sum has same sign as pSrc2 */ pDst->dc.attr = s2; } } return(GM_SUCCESS); }