/* 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 <stdio.h>
#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 (j<i)
			_DivUnsArrByPwrOf10(pSrc2->dc.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);
}