/* DEC *MultiplyDecimal(pDst,pSrc1,pSrc2); * * ARGUMENT * DEC *pDst; * DEC *pSrc1,pSrc2; * * DESCRIPTION * Multiplies pSrc1 times pSrc2 and puts it into pDst. * pSrc1 and pSrc2 remain unchanged. * Additionally, if either number is negative, it * is temporarily converted a positive for the mult. and a flag is set * to convert the answer if unlike signs. * * SIDE EFFECTS * pDst is indeterminate on error. * * RETURNS * Returns pointer to pDst if successful, otherwise a GM_NULL. The * type error (GM_OVERFLOW, GM_UNDERFLOW, GM_NOMEMORY) is in wGMError * if wGMError didn't contain a previous error on entry. * * POSSIBLE ERROR CODES * * GM_NULLPOINTER * GM_OVERFLOW * GM_UNDERFLOW * * AUTHOR * Andy Anderson 29-JAN-1987 16:30 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * */ #include #include "gm.h" #include "gmsystem.h" DEC *MultiplyDecimal(pDst,pSrc1,pSrc2) DEC *pDst; DEC *pSrc1,*pSrc2; { register int i,p; int r=0,stktmp=0; unsigned SHORT dtp[10]; _MacStart(GM_DMUL); _MacInVarD(pSrc1); _MacInVarD(pSrc2); _MacOutVarD(pDst); /* First, if either of the numbers is zero, the result is alway zero */ if((_MacIsDecZ(pSrc1)) || (_MacIsDecZ(pSrc2))) { i = pSrc1->dc.id + pSrc2->dc.id; _MacDZero(pDst); pDst->dc.id = (i > GM_MAXID) ? GM_MAXID : i; _MacRet(pDst); } /* Find out number of 16-bit int's in each number */ i = 3; while ( pSrc1->dc.sl[i] ==0 && i>=0 ) i--; p = 3; while ( pSrc2->dc.sl[p] == 0 && p>=0 ) p--; /* allow user to specify pDst as one of the sources */ _MulUnsArrByUnsArr(pSrc1->dc.sl, pSrc2->dc.sl, dtp, i+1,p+1,stktmp); /* squeeze eight digits down to four */ p=0; while ((dtp[4] >= 500) || (dtp[5] != 0) || (dtp[6] != 0) || (dtp[7] != 0)) { r = _DivUnsArrByUns(dtp, 10000, 8); p+=4; } if (!dtp[4] && dtp[3]<=32767) { if (r>=5000) (void) _IncrementUnsArr(dtp); } else if (dtp[4] >= 50) { _DivUnsArrByUnsRound(dtp, 1000, 5); p+=3; } else if (dtp[4] >= 5) { _DivUnsArrByUnsRound(dtp, 100, 5); p+=2; } else { _DivUnsArrByUnsRound(dtp, 10, 5); p++; } /* now p is the power of 10 which was divided */ i = pSrc1->dc.id + pSrc2->dc.id - p; if (i < GM_MINID) { _MacErr(GM_OVERFLOW); _MacRet(GM_NULL); } pDst->dc.sl[0] = dtp[0]; pDst->dc.sl[1] = dtp[1]; pDst->dc.sl[2] = dtp[2]; pDst->dc.sl[3] = dtp[3]; pDst->dc.sl[4] = dtp[4]; /* if the signs of the sources are different, pDst=-pDst */ pDst->dc.attr = (pSrc1->dc.attr^pSrc2->dc.attr); if (i > GM_MAXID) { _DivUnsArrByPwrOf10(pDst->dc.sl, 4, i - GM_MAXID); pDst->dc.id = GM_MAXID; if (_MacIsDecZ(pDst)) _MacErr(GM_UNDERFLOW); } pDst->dc.id = i; _MacRet(pDst); }