campo-sirio/gfm/dsub.c
alex ba237a9d91 Patch level : no patch
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
Aggiunti i sorgenti per Greenleaf Math Library (gfm.dll)


git-svn-id: svn://10.65.10.50/trunk@10079 c028cbd2-c16b-5b4b-a496-9718f37d4682
2002-02-26 12:19:02 +00:00

131 lines
2.7 KiB
C
Executable File

/* DEC *SubtractDecimal(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 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
* Jared Levy
* Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved.
*
* MODIFICATIONS
*
*/
#include <stdio.h>
#include "gmsystem.h"
DEC *SubtractDecimal(pDst,pSrc1,pSrc2)
DEC *pDst;
DEC *pSrc1,*pSrc2;
{
DEC t1, t2, *pts;
register int i,j;
int s1, s2;
_MacStart(GM_DSUB);
_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);
_MacDChgs(pts);
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 (j<i)
_DivUnsArrByPwrOf10(pSrc2->dc.sl, 4, 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_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, 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;
}
}
_MacRet(pDst);
}