/* int	_DivDec80Bit(pDst,pSrc1,pSrc2);
 *
 * ARGUMENT
 *	DEC	*pDst;
 *	DEC	*pSrc1,pSrc2;
 *
 * DESCRIPTION
 *	Divides	pDst = pSrc1 / pSrc2.
 *
 * SIDE	EFFECTS
 *	None.
 *
 * RETURNS
 *	Returns	GM_SUCCESS if successful, otherwise the	error code.
 *	wGMError is not	changed.
 *
 * AUTHOR
 *  Jared Levy	 05-JAN-1987  17:30
 *   Copyright (C) 1987-1990 Greenleaf Software	Inc.  All rights reserved.
 *
 * MODIFICATIONS
 *
 */

#include <stdio.h>
#include "gm.h"
#include "gmsystem.h"

int	_DivDec80Bit(c,a,b)
DEC	*c;
DEC	*a,*b;
{
	register int	i,t;
	int	maxp, p=0, mag2a, mag2b;
	unsigned SHORT	an[14],	bn[6], *cn, ad[5], as[14];

	/*  check that b is nonzero */
	if (_MacIsDecZ(b))
		return(GM_DIV0);

	/*  check whether scr1 is zero */
	if (_MacIsDecZ(a))  {
		_MacDCopy(c,a);
		return(GM_SUCCESS);
	}

/*  sets c = a / b,
    where a and	b are positive DEC numbers, and	the result is stored in	c */

	bn[0]=b->dc.sl[0];
	bn[1]=b->dc.sl[1];
	bn[2]=b->dc.sl[2];
	bn[3]=b->dc.sl[3];
	bn[4]=b->dc.msd;
	bn[5]=0;

	cn =  c->dc.sl;

	an[0]=a->dc.sl[0];
	an[1]=a->dc.sl[1];
	an[2]=a->dc.sl[2];
	an[3]=a->dc.sl[3];
	an[4]=a->dc.msd;
	an[5] =	0;
	an[6] =	0;
	an[7] =	0;
	an[8] =	0;
	an[9] =	0;
	an[10]=	0;
	an[11]=	0;

	maxp = GM_IMAXID - (a->dc.id - b->dc.id);
	if (maxp > 0)	{

/* The following code uses up most of the time involved	in divisions.
It starts with two 64-bit number integers an and bh, both positive,
along with an integer maxp.  Two values	are returned:  a nonnegative
integer	p and a	160-bit	number as = an * 10^p.	p is the largest number
satisfying the conditions (1) as < 2^160,
			  (2) the highest 80 bits of as	are less than bh
			  (3) p	<= maxp.
*/

	i = 4;
	while (an[i] ==	0)
		i--;
	mag2a =	16 * i;
	t = an[i]>>1;
	while (t)  {
		t=t>>1;
		mag2a++;
		}

	i = 4;
	while ((bn[i] == 0) && (i>0))
		i--;
	mag2b =	16 * i;
	t = bn[i]>>1;
	while (t)  {
		t=t>>1;
		mag2b++;
		}

	p = (78	+ mag2b	- mag2a) * 3 / 10;
	if (p>maxp)
		p=maxp;


	if (p != 0)
	     _MulUnsArrByPwrOf10(an,p,10);

	if (p != maxp)	{

		for(i=0; i<14; i++) {
			as[i] =	an[i];
		}

		i = _MulUnsArrByPwrOf10(as,1,10);

		ad[0]=as[5];
		ad[1]=as[6];
		ad[2]=as[7];
		ad[3]=as[8];
		ad[4]=as[9];
		_DoubleUnsArr(ad, 5);
		if (as[4]&0x8000)
			ad[0]=ad[0]+1;

		if ((i == GM_SUCCESS) &&
			(_CompareUnsArr(ad,bn,5) == -1))  {
			p++;
			for(i=0; i<10; i++)
				an[i] =	as[i];
			}
		}
		/*  p != maxp */
	}	/* maxp	> 0 */

	_DivUns10ArrByUns5Arr(cn,an,bn);

/* adjust implied decimal to correct value */
	i = a->dc.id - b->dc.id	+ p;
	if (i<GM_IMINID)
		 return(GM_OVERFLOW);
	c->dc.id = i;

/*  if the signs of the	sources	are different, c=-c */
	c->dc.attr = (a->dc.attr^b->dc.attr);

	return(GM_SUCCESS);
}