/* DEC *AddDecimal(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 * Adds the value in pSrc1 DEC to the value in pSrc2 DEC * and puts the result in dest DEC structure. The sum is calculated * to the maximum possible accuracy. The routine requires MINID, * the minimum allowed implied decimal. * * SIDE EFFECTS * On overflow, the dest value is indeterminate. * * RETURNS * Returns a pointer to the dest structure unless overflow, * when it returns a GM_NULL. * * POSSIBLE ERROR CODES * * GM_NULLPOINTER * GM_OVERFLOW * * AUTHOR * Andy Anderson 13-JAN-1987 14:14 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * */ #include #include "gmsystem.h" DEC *AddDecimal(pDst,pSrc1,pSrc2) DEC *pDst; DEC *pSrc1,*pSrc2; { DEC t1, t2, *pts; register int i,j; int s1, s2; _MacStart(GM_DADD); _MacInVar(pSrc1,GM_NULL); _MacInVar(pSrc2,GM_NULL); _MacOutVar(pDst,GM_NULL); /* 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); if (i<0) { pSrc1 = &t1; pSrc2 = &t2; i = -i; } else { pSrc2 = &t1; pSrc1 = &t2; } j = _MulUnsArrByPwrOf10Limited( pSrc1->dc.sl, i, 4); pSrc1->dc.id += j; if (jdc.sl, 4, i-j); } /* add the numbers */ pDst->dc.id = pSrc1->dc.id; s1 = pSrc1->dc.attr & 0x0001; s2 = pSrc2->dc.attr & 0x0001; 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_MINID) { _MacErr(GM_OVERFLOW); _MacRet(GM_NULL); } _DivUnsArrByUns(pDst->dc.sl, 10, 4); 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, 4) >= 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; } } _MacRet(pDst); }