130 lines
2.7 KiB
C
130 lines
2.7 KiB
C
|
/* 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 <stdio.h>
|
||
|
#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);
|
||
|
}
|