1284 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1284 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
| /**
 | |
|  * This file has no copyright assigned and is placed in the Public Domain.
 | |
|  * This file is part of the mingw-w64 runtime package.
 | |
|  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
 | |
|  */
 | |
| #include "cephes_emath.h"
 | |
| 
 | |
| /*
 | |
|  * The constants are for 64 bit precision.
 | |
|  */
 | |
| 
 | |
| 
 | |
| /* Move in external format number,
 | |
|  * converting it to internal format.
 | |
|  */
 | |
| void __emovi(const short unsigned int * __restrict__ a,
 | |
| 	     short unsigned int * __restrict__ b)
 | |
| {
 | |
| 	register const unsigned short *p;
 | |
| 	register unsigned short *q;
 | |
| 	int i;
 | |
| 
 | |
| 	q = b;
 | |
| 	p = a + (NE-1);	/* point to last word of external number */
 | |
| 	/* get the sign bit */
 | |
| 	if (*p & 0x8000)
 | |
| 		*q++ = 0xffff;
 | |
| 	else
 | |
| 		*q++ = 0;
 | |
| 	/* get the exponent */
 | |
| 	*q = *p--;
 | |
| 	*q++ &= 0x7fff;	/* delete the sign bit */
 | |
| #ifdef INFINITY
 | |
| 	if ((*(q - 1) & 0x7fff) == 0x7fff)
 | |
| 	{
 | |
| #ifdef NANS
 | |
| 		if (__eisnan(a))
 | |
| 		{
 | |
| 			*q++ = 0;
 | |
| 			for (i = 3; i < NI; i++ )
 | |
| 				*q++ = *p--;
 | |
| 			return;
 | |
| 		}
 | |
| #endif
 | |
| 		for (i = 2; i < NI; i++)
 | |
| 			*q++ = 0;
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	/* clear high guard word */
 | |
| 	*q++ = 0;
 | |
| 	/* move in the significand */
 | |
| 	for (i = 0; i < NE - 1; i++ )
 | |
| 		*q++ = *p--;
 | |
| 	/* clear low guard word */
 | |
| 	*q = 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ;	Add significands
 | |
| ;	x + y replaces y
 | |
| */
 | |
| 
 | |
| void __eaddm(const short unsigned int * __restrict__ x,
 | |
| 		  short unsigned int * __restrict__ y)
 | |
| {
 | |
| 	register unsigned long a;
 | |
| 	int i;
 | |
| 	unsigned int carry;
 | |
| 
 | |
| 	x += NI - 1;
 | |
| 	y += NI - 1;
 | |
| 	carry = 0;
 | |
| 	for (i = M; i < NI; i++)
 | |
| 	{
 | |
| 		a = (unsigned long)(*x) + (unsigned long)(*y) + carry;
 | |
| 		if (a & 0x10000)
 | |
| 			carry = 1;
 | |
| 		else
 | |
| 			carry = 0;
 | |
| 		*y = (unsigned short)a;
 | |
| 		--x;
 | |
| 		--y;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
| ;	Subtract significands
 | |
| ;	y - x replaces y
 | |
| */
 | |
| 
 | |
| void __esubm(const short unsigned int * __restrict__ x,
 | |
| 		  short unsigned int * __restrict__ y)
 | |
| {
 | |
| 	unsigned long a;
 | |
| 	int i;
 | |
| 	unsigned int carry;
 | |
| 
 | |
| 	x += NI - 1;
 | |
| 	y += NI - 1;
 | |
| 	carry = 0;
 | |
| 	for (i = M; i < NI; i++)
 | |
| 	{
 | |
| 		a = (unsigned long)(*y) - (unsigned long)(*x) - carry;
 | |
| 		if (a & 0x10000)
 | |
| 			carry = 1;
 | |
| 		else
 | |
| 			carry = 0;
 | |
| 		*y = (unsigned short)a;
 | |
| 		--x;
 | |
| 		--y;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Multiply significand of e-type number b
 | |
| by 16-bit quantity a, e-type result to c. */
 | |
| 
 | |
| static void __m16m(short unsigned int a,
 | |
| 		   short unsigned int *  __restrict__ b,
 | |
| 		   short unsigned int *  __restrict__ c)
 | |
| {
 | |
| 	register unsigned short *pp;
 | |
| 	register unsigned long carry;
 | |
| 	unsigned short *ps;
 | |
| 	unsigned short p[NI];
 | |
| 	unsigned long aa, m;
 | |
| 	int i;
 | |
| 
 | |
| 	aa = a;
 | |
| 	pp = &p[NI - 2];
 | |
| 	*pp++ = 0;
 | |
| 	*pp = 0;
 | |
| 	ps = &b[NI - 1];
 | |
| 
 | |
| 	for(i = M + 1; i < NI; i++)
 | |
| 	{
 | |
| 		if (*ps == 0)
 | |
| 		{
 | |
| 			--ps;
 | |
| 			--pp;
 | |
| 			*(pp - 1) = 0;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			m = (unsigned long) aa * *ps--;
 | |
| 			carry = (m & 0xffff) + *pp;
 | |
| 			*pp-- = (unsigned short)carry;
 | |
| 			carry = (carry >> 16) + (m >> 16) + *pp;
 | |
| 			*pp = (unsigned short)carry;
 | |
| 			*(pp - 1) = carry >> 16;
 | |
| 		}
 | |
| 	}
 | |
| 	for (i = M; i < NI; i++)
 | |
| 	c[i] = p[i];
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Divide significands. Neither the numerator nor the denominator
 | |
| is permitted to have its high guard word nonzero.  */
 | |
| 
 | |
| int __edivm(short unsigned int * __restrict__ den,
 | |
| 		 short unsigned int * __restrict__ num)
 | |
| {
 | |
| 	int i;
 | |
| 	register unsigned short *p;
 | |
| 	unsigned long tnum;
 | |
| 	unsigned short j, tdenm, tquot;
 | |
| 	unsigned short tprod[NI + 1];
 | |
| 	unsigned short equot[NI];
 | |
| 
 | |
| 	p = &equot[0];
 | |
| 	*p++ = num[0];
 | |
| 	*p++ = num[1];
 | |
| 
 | |
| 	for (i = M; i < NI; i++)
 | |
| 	{
 | |
| 		*p++ = 0;
 | |
| 	}
 | |
| 	__eshdn1(num);
 | |
| 	tdenm = den[M + 1];
 | |
| 	for (i = M; i < NI; i++)
 | |
| 	{
 | |
| 		/* Find trial quotient digit (the radix is 65536). */
 | |
| 		tnum = (((unsigned long) num[M]) << 16) + num[M + 1];
 | |
| 
 | |
| 		/* Do not execute the divide instruction if it will overflow. */
 | |
| 		if ((tdenm * 0xffffUL) < tnum)
 | |
| 			tquot = 0xffff;
 | |
| 		else
 | |
| 			tquot = tnum / tdenm;
 | |
| 
 | |
| 		/* Prove that the divide worked. */
 | |
| 		/*
 | |
| 		tcheck = (unsigned long)tquot * tdenm;
 | |
| 		if (tnum - tcheck > tdenm)
 | |
| 			tquot = 0xffff;
 | |
| 		*/
 | |
| 		/* Multiply denominator by trial quotient digit. */
 | |
| 		__m16m(tquot, den, tprod);
 | |
| 		/* The quotient digit may have been overestimated. */
 | |
| 		if (__ecmpm(tprod, num) > 0)
 | |
| 		{
 | |
| 			tquot -= 1;
 | |
| 			__esubm(den, tprod);
 | |
| 			if(__ecmpm(tprod, num) > 0)
 | |
| 			{
 | |
| 				tquot -= 1;
 | |
| 				__esubm(den, tprod);
 | |
| 			}
 | |
| 		}
 | |
| 		__esubm(tprod, num);
 | |
| 		equot[i] = tquot;
 | |
| 		__eshup6(num);
 | |
| 	}
 | |
| 	/* test for nonzero remainder after roundoff bit */
 | |
| 	p = &num[M];
 | |
| 	j = 0;
 | |
| 	for (i = M; i < NI; i++)
 | |
| 	{
 | |
| 		j |= *p++;
 | |
| 	}
 | |
| 	if (j)
 | |
| 		j = 1;
 | |
| 
 | |
| 	for (i = 0; i < NI; i++)
 | |
| 		num[i] = equot[i];
 | |
| 
 | |
| 	return ( (int)j );
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Multiply significands */
 | |
| int __emulm(const short unsigned int * __restrict__ a,
 | |
| 		 short unsigned int * __restrict__ b)
 | |
| {
 | |
| 	const unsigned short *p;
 | |
| 	unsigned short *q;
 | |
| 	unsigned short pprod[NI];
 | |
| 	unsigned short equot[NI];
 | |
| 	unsigned short j;
 | |
| 	int i;
 | |
| 
 | |
| 	equot[0] = b[0];
 | |
| 	equot[1] = b[1];
 | |
| 	for (i = M; i < NI; i++)
 | |
| 		equot[i] = 0;
 | |
| 
 | |
| 	j = 0;
 | |
| 	p = &a[NI - 1];
 | |
| 	q = &equot[NI - 1];
 | |
| 	for (i = M + 1; i < NI; i++)
 | |
| 	{
 | |
| 		if (*p == 0)
 | |
| 		{
 | |
| 			--p;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			__m16m(*p--, b, pprod);
 | |
| 			__eaddm(pprod, equot);
 | |
| 		}
 | |
| 		j |= *q;
 | |
| 		__eshdn6(equot);
 | |
| 	}
 | |
| 
 | |
| 	for (i = 0; i < NI; i++)
 | |
| 		b[i] = equot[i];
 | |
| 
 | |
| 	/* return flag for lost nonzero bits */
 | |
| 	return ( (int)j );
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Normalize and round off.
 | |
|  *
 | |
|  * The internal format number to be rounded is "s".
 | |
|  * Input "lost" indicates whether the number is exact.
 | |
|  * This is the so-called sticky bit.
 | |
|  *
 | |
|  * Input "subflg" indicates whether the number was obtained
 | |
|  * by a subtraction operation.  In that case if lost is nonzero
 | |
|  * then the number is slightly smaller than indicated.
 | |
|  *
 | |
|  * Input "expo" is the biased exponent, which may be negative.
 | |
|  * the exponent field of "s" is ignored but is replaced by
 | |
|  * "expo" as adjusted by normalization and rounding.
 | |
|  *
 | |
|  * Input "rcntrl" is the rounding control.
 | |
|  *
 | |
|  * Input "rnprc" is precison control (64 or NBITS).
 | |
|  */
 | |
| 
 | |
| void __emdnorm(short unsigned int *s, int lost, int subflg, int expo, int rcntrl, int rndprc)
 | |
| {
 | |
| 	int i, j;
 | |
| 	unsigned short r;
 | |
| 	int rw = NI-1; /* low guard word */
 | |
| 	int re = NI-2;
 | |
| 	const unsigned short rmsk = 0xffff;
 | |
| 	const unsigned short rmbit = 0x8000;
 | |
| #if NE == 6
 | |
| 	unsigned short rbit[NI] = {0,0,0,0,0,0,0,1,0};
 | |
| #else
 | |
| 	unsigned short rbit[NI] = {0,0,0,0,0,0,0,0,0,0,0,1,0};
 | |
| #endif
 | |
| 
 | |
| 	/* Normalize */
 | |
| 	j = __enormlz(s);
 | |
| 
 | |
| 	/* a blank significand could mean either zero or infinity. */
 | |
| #ifndef INFINITY
 | |
| 	if (j > NBITS)
 | |
| 	{
 | |
| 		__ecleazs(s);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	expo -= j;
 | |
| #ifndef INFINITY
 | |
| 	if (expo >= 32767)
 | |
| 		goto overf;
 | |
| #else
 | |
| 	if ((j > NBITS) && (expo < 32767))
 | |
| 	{
 | |
| 		__ecleazs(s);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	if (expo < 0)
 | |
| 	{
 | |
| 		if (expo > (-NBITS - 1))
 | |
| 		{
 | |
| 			j = expo;
 | |
| 			i = __eshift(s, j);
 | |
| 			if (i)
 | |
| 				lost = 1;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			__ecleazs(s);
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 	/* Round off, unless told not to by rcntrl. */
 | |
| 	if (rcntrl == 0)
 | |
| 		goto mdfin;
 | |
| 	if (rndprc == 64)
 | |
| 	{
 | |
| 		rw = 7;
 | |
| 		re = 6;
 | |
| 		rbit[NI - 2] = 0;
 | |
| 		rbit[6] = 1;
 | |
| 	}
 | |
| 
 | |
| 	/* Shift down 1 temporarily if the data structure has an implied
 | |
| 	 * most significant bit and the number is denormal.
 | |
| 	 * For rndprc = 64 or NBITS, there is no implied bit.
 | |
| 	 * But Intel long double denormals lose one bit of significance even so.
 | |
| 	 */
 | |
| #if IBMPC
 | |
| 	if ((expo <= 0) && (rndprc != NBITS))
 | |
| #else
 | |
| 	if ((expo <= 0) && (rndprc != 64) && (rndprc != NBITS))
 | |
| #endif
 | |
| 	{
 | |
| 		lost |= s[NI - 1] & 1;
 | |
| 		__eshdn1(s);
 | |
| 	}
 | |
| 	/* Clear out all bits below the rounding bit,
 | |
| 	 * remembering in r if any were nonzero.
 | |
| 	 */
 | |
| 	r = s[rw] & rmsk;
 | |
| 	if (rndprc < NBITS)
 | |
| 	{
 | |
| 		i = rw + 1;
 | |
| 		while (i < NI)
 | |
| 		{
 | |
| 			if( s[i] )
 | |
| 				r |= 1;
 | |
| 			s[i] = 0;
 | |
| 			++i;
 | |
| 		}
 | |
| 	}
 | |
| 	s[rw] &= (rmsk ^ 0xffff);
 | |
| 	if ((r & rmbit) != 0)
 | |
| 	{
 | |
| 		if (r == rmbit)
 | |
| 		{
 | |
| 			if (lost == 0)
 | |
| 			{ /* round to even */
 | |
| 				if ((s[re] & 1) == 0)
 | |
| 					goto mddone;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				if (subflg != 0)
 | |
| 					goto mddone;
 | |
| 			}
 | |
| 		}
 | |
| 		__eaddm(rbit, s);
 | |
| 	}
 | |
| mddone:
 | |
| #if IBMPC
 | |
| 	if ((expo <= 0) && (rndprc != NBITS))
 | |
| #else
 | |
| 	if ((expo <= 0) && (rndprc != 64) && (rndprc != NBITS))
 | |
| #endif
 | |
| 	{
 | |
| 		__eshup1(s);
 | |
| 	}
 | |
| 	if (s[2] != 0)
 | |
| 	{ /* overflow on roundoff */
 | |
| 		__eshdn1(s);
 | |
| 		expo += 1;
 | |
| 	}
 | |
| mdfin:
 | |
| 	s[NI - 1] = 0;
 | |
| 	if (expo >= 32767)
 | |
| 	{
 | |
| #ifndef INFINITY
 | |
| overf:
 | |
| #endif
 | |
| #ifdef INFINITY
 | |
| 		s[1] = 32767;
 | |
| 		for (i = 2; i < NI - 1; i++ )
 | |
| 			s[i] = 0;
 | |
| #else
 | |
| 		s[1] = 32766;
 | |
| 		s[2] = 0;
 | |
| 		for (i = M + 1; i < NI - 1; i++)
 | |
| 			s[i] = 0xffff;
 | |
| 		s[NI - 1] = 0;
 | |
| 		if ((rndprc < 64) || (rndprc == 113))
 | |
| 			s[rw] &= (rmsk ^ 0xffff);
 | |
| #endif
 | |
| 		return;
 | |
| 	}
 | |
| 	if (expo < 0)
 | |
| 		s[1] = 0;
 | |
| 	else
 | |
| 		s[1] = (unsigned short)expo;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ;	Multiply.
 | |
| ;
 | |
| ;	unsigned short a[NE], b[NE], c[NE];
 | |
| ;	emul( a, b, c );	c = b * a
 | |
| */
 | |
| void __emul(const short unsigned int *a,
 | |
| 		 const short unsigned int *b,
 | |
| 		 short unsigned int *c)
 | |
| {
 | |
| 	unsigned short ai[NI], bi[NI];
 | |
| 	int i, j;
 | |
| 	long lt, lta, ltb;
 | |
| 
 | |
| #ifdef NANS
 | |
| 	/* NaN times anything is the same NaN. */
 | |
| 	if (__eisnan(a))
 | |
| 	{
 | |
| 		__emov(a, c);
 | |
| 		return;
 | |
| 	}
 | |
| 	if (__eisnan(b))
 | |
| 	{
 | |
| 		__emov(b, c);
 | |
| 		return;
 | |
| 	}
 | |
| 	/* Zero times infinity is a NaN. */
 | |
| 	if ((__eisinf(a) && __eiiszero(b))
 | |
| 	 || (__eisinf(b) && __eiiszero(a)))
 | |
| 	{
 | |
| 		mtherr( "emul", DOMAIN);
 | |
| 		__enan_NBITS(c);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| /* Infinity times anything else is infinity. */
 | |
| #ifdef INFINITY
 | |
| 	if (__eisinf(a) || __eisinf(b))
 | |
| 	{
 | |
| 		if (__eisneg(a) ^ __eisneg(b))
 | |
| 			*(c + (NE-1)) = 0x8000;
 | |
| 		else
 | |
| 			*(c + (NE-1)) = 0;
 | |
| 		__einfin(c);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	__emovi(a, ai);
 | |
| 	__emovi(b, bi);
 | |
| 	lta = ai[E];
 | |
| 	ltb = bi[E];
 | |
| 	if (ai[E] == 0)
 | |
| 	{
 | |
| 		for (i = 1; i < NI - 1; i++)
 | |
| 		{
 | |
| 			if (ai[i] != 0)
 | |
| 			{
 | |
| 				lta -= __enormlz( ai );
 | |
| 				goto mnzer1;
 | |
| 			}
 | |
| 		}
 | |
| 		__eclear(c);
 | |
| 		return;
 | |
| 	}
 | |
| mnzer1:
 | |
| 
 | |
| 	if (bi[E] == 0)
 | |
| 	{
 | |
| 		for (i = 1; i < NI - 1; i++)
 | |
| 		{
 | |
| 			if (bi[i] != 0)
 | |
| 			{
 | |
| 				ltb -= __enormlz(bi);
 | |
| 				goto mnzer2;
 | |
| 			}
 | |
| 		}
 | |
| 		__eclear(c);
 | |
| 		return;
 | |
| 	}
 | |
| mnzer2:
 | |
| 
 | |
| 	/* Multiply significands */
 | |
| 	j = __emulm(ai, bi);
 | |
| 	/* calculate exponent */
 | |
| 	lt = lta + ltb - (EXONE - 1);
 | |
| 	__emdnorm(bi, j, 0, lt, 64, NBITS);
 | |
| 	/* calculate sign of product */
 | |
| 	if (ai[0] == bi[0])
 | |
| 		bi[0] = 0;
 | |
| 	else
 | |
| 		bi[0] = 0xffff;
 | |
| 	__emovo(bi, c);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* move out internal format to ieee long double */
 | |
| void __toe64(short unsigned int *a, short unsigned int *b)
 | |
| {
 | |
| 	register unsigned short *p, *q;
 | |
| 	unsigned short i;
 | |
| 
 | |
| #ifdef NANS
 | |
| 	if (__eiisnan(a))
 | |
| 	{
 | |
| 		__enan_64(b);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| #ifdef IBMPC
 | |
| 	/* Shift Intel denormal significand down 1.  */
 | |
| 	if (a[E] == 0)
 | |
| 		__eshdn1(a);
 | |
| #endif
 | |
| 	p = a;
 | |
| #ifdef MIEEE
 | |
| 	q = b;
 | |
| #else
 | |
| 	q = b + 4; /* point to output exponent */
 | |
| #if 1
 | |
| 	/* NOTE: if data type is 96 bits wide, clear the last word here. */
 | |
| 	*(q + 1)= 0;
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| 	/* combine sign and exponent */
 | |
| 	i = *p++;
 | |
| #ifdef MIEEE
 | |
| 	if (i)
 | |
| 		*q++ = *p++ | 0x8000;
 | |
| 	else
 | |
| 		*q++ = *p++;
 | |
| 	*q++ = 0;
 | |
| #else
 | |
| 	if (i)
 | |
| 		*q-- = *p++ | 0x8000;
 | |
| 	else
 | |
| 		*q-- = *p++;
 | |
| #endif
 | |
| 	/* skip over guard word */
 | |
| 	++p;
 | |
| 	/* move the significand */
 | |
| #ifdef MIEEE
 | |
| 	for (i = 0; i < 4; i++)
 | |
| 		*q++ = *p++;
 | |
| #else
 | |
| #ifdef INFINITY
 | |
| 	if (__eiisinf(a))
 | |
|         {
 | |
| 	/* Intel long double infinity.  */
 | |
| 		*q-- = 0x8000;
 | |
| 		*q-- = 0;
 | |
| 		*q-- = 0;
 | |
| 		*q = 0;
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	for (i = 0; i < 4; i++)
 | |
| 		*q-- = *p++;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Compare two e type numbers.
 | |
|  *
 | |
|  * unsigned short a[NE], b[NE];
 | |
|  * ecmp( a, b );
 | |
|  *
 | |
|  *  returns +1 if a > b
 | |
|  *           0 if a == b
 | |
|  *          -1 if a < b
 | |
|  *          -2 if either a or b is a NaN.
 | |
|  */
 | |
| int __ecmp(const short unsigned int * __restrict__ a,
 | |
| 		const short unsigned int *  __restrict__ b)
 | |
| {
 | |
| 	unsigned short ai[NI], bi[NI];
 | |
| 	register unsigned short *p, *q;
 | |
| 	register int i;
 | |
| 	int msign;
 | |
| 
 | |
| #ifdef NANS
 | |
| 	if (__eisnan (a) || __eisnan (b))
 | |
| 		return (-2);
 | |
| #endif
 | |
| 	__emovi(a, ai);
 | |
| 	p = ai;
 | |
| 	__emovi(b, bi);
 | |
| 	q = bi;
 | |
| 
 | |
| 	if (*p != *q)
 | |
| 	{ /* the signs are different */
 | |
| 		/* -0 equals + 0 */
 | |
| 		for (i = 1; i < NI - 1; i++)
 | |
| 		{
 | |
| 			if (ai[i] != 0)
 | |
| 				goto nzro;
 | |
| 			if (bi[i] != 0)
 | |
| 				goto nzro;
 | |
| 		}
 | |
| 		return (0);
 | |
| nzro:
 | |
| 		if (*p == 0)
 | |
| 			return (1);
 | |
| 		else
 | |
| 			return (-1);
 | |
| 	}
 | |
| 	/* both are the same sign */
 | |
| 	if (*p == 0)
 | |
| 		msign = 1;
 | |
| 	else
 | |
| 		msign = -1;
 | |
| 	i = NI - 1;
 | |
| 	do
 | |
| 	{
 | |
| 		if (*p++ != *q++)
 | |
| 		{
 | |
| 			goto diff;
 | |
| 		}
 | |
| 	}
 | |
| 	while (--i > 0);
 | |
| 
 | |
| 	return (0);	/* equality */
 | |
| 
 | |
| diff:
 | |
| 	if ( *(--p) > *(--q) )
 | |
| 		return (msign);		/* p is bigger */
 | |
| 	else
 | |
| 		return (-msign);	/* p is littler */
 | |
| }
 | |
| 
 | |
| /*
 | |
| ;	Shift significand
 | |
| ;
 | |
| ;	Shifts significand area up or down by the number of bits
 | |
| ;	given by the variable sc.
 | |
| */
 | |
| int __eshift(short unsigned int *x, int sc)
 | |
| {
 | |
| 	unsigned short lost;
 | |
| 	unsigned short *p;
 | |
| 
 | |
| 	if (sc == 0)
 | |
| 		return (0);
 | |
| 
 | |
| 	lost = 0;
 | |
| 	p = x + NI - 1;
 | |
| 
 | |
| 	if (sc < 0)
 | |
| 	{
 | |
| 		sc = -sc;
 | |
| 		while (sc >= 16)
 | |
| 		{
 | |
| 			lost |= *p;	/* remember lost bits */
 | |
| 			__eshdn6(x);
 | |
| 			sc -= 16;
 | |
| 		}
 | |
| 
 | |
| 		while (sc >= 8)
 | |
| 		{
 | |
| 			lost |= *p & 0xff;
 | |
| 			__eshdn8(x);
 | |
| 			sc -= 8;
 | |
| 		}
 | |
| 
 | |
| 		while (sc > 0)
 | |
| 		{
 | |
| 			lost |= *p & 1;
 | |
| 			__eshdn1(x);
 | |
| 			sc -= 1;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		while (sc >= 16)
 | |
| 		{
 | |
| 			__eshup6(x);
 | |
| 			sc -= 16;
 | |
| 		}
 | |
| 
 | |
| 		while (sc >= 8)
 | |
| 		{
 | |
| 			__eshup8(x);
 | |
| 			sc -= 8;
 | |
| 		}
 | |
| 
 | |
| 		while (sc > 0)
 | |
| 		{
 | |
| 			__eshup1(x);
 | |
| 			sc -= 1;
 | |
| 		}
 | |
| 	}
 | |
| 	if (lost)
 | |
| 		lost = 1;
 | |
| 	return ( (int)lost );
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ;	normalize
 | |
| ;
 | |
| ; Shift normalizes the significand area pointed to by argument
 | |
| ; shift count (up = positive) is returned.
 | |
| */
 | |
| int __enormlz(short unsigned int *x)
 | |
| {
 | |
| 	register unsigned short *p;
 | |
| 	int sc;
 | |
| 
 | |
| 	sc = 0;
 | |
| 	p = &x[M];
 | |
| 	if (*p != 0)
 | |
| 		goto normdn;
 | |
| 	++p;
 | |
| 	if (*p & 0x8000)
 | |
| 		return (0);	/* already normalized */
 | |
| 	while (*p == 0)
 | |
| 	{
 | |
| 		__eshup6(x);
 | |
| 		sc += 16;
 | |
| 		/* With guard word, there are NBITS+16 bits available.
 | |
| 		 * return true if all are zero.
 | |
| 		 */
 | |
| 		if (sc > NBITS)
 | |
| 			return (sc);
 | |
| 	}
 | |
| 	/* see if high byte is zero */
 | |
| 	while ((*p & 0xff00) == 0)
 | |
| 	{
 | |
| 		__eshup8(x);
 | |
| 		sc += 8;
 | |
| 	}
 | |
| 	/* now shift 1 bit at a time */
 | |
| 	while ((*p  & 0x8000) == 0)
 | |
| 	{
 | |
| 		__eshup1(x);
 | |
| 		sc += 1;
 | |
| 		if (sc > (NBITS + 16))
 | |
| 		{
 | |
| 			mtherr( "enormlz", UNDERFLOW);
 | |
| 			return (sc);
 | |
| 		}
 | |
| 	}
 | |
| 	return (sc);
 | |
| 
 | |
| 	/* Normalize by shifting down out of the high guard word
 | |
| 	   of the significand */
 | |
| normdn:
 | |
| 	if (*p & 0xff00)
 | |
| 	{
 | |
| 		__eshdn8(x);
 | |
| 		sc -= 8;
 | |
| 	}
 | |
| 	while (*p != 0)
 | |
| 	{
 | |
| 		__eshdn1(x);
 | |
| 		sc -= 1;
 | |
| 
 | |
| 		if (sc < -NBITS)
 | |
| 		{
 | |
| 			mtherr("enormlz", OVERFLOW);
 | |
| 			return (sc);
 | |
| 		}
 | |
| 	}
 | |
| 	return (sc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Move internal format number out,
 | |
|  * converting it to external format.
 | |
|  */
 | |
| void __emovo(const short unsigned int * __restrict__ a,
 | |
| 		  short unsigned int * __restrict__ b)
 | |
| {
 | |
| 	register const unsigned short *p;
 | |
| 	register unsigned short *q;
 | |
| 	unsigned short i;
 | |
| 
 | |
| 	p = a;
 | |
| 	q = b + (NE - 1); /* point to output exponent */
 | |
| 	/* combine sign and exponent */
 | |
| 	i = *p++;
 | |
| 	if (i)
 | |
| 		*q-- = *p++ | 0x8000;
 | |
| 	else
 | |
| 		*q-- = *p++;
 | |
| #ifdef INFINITY
 | |
| 	if (*(p - 1) == 0x7fff)
 | |
| 	{
 | |
| #ifdef NANS
 | |
| 		if (__eiisnan(a))
 | |
| 		{
 | |
| 			__enan_NBITS(b);
 | |
| 			return;
 | |
| 		}
 | |
| #endif
 | |
| 		__einfin(b);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	/* skip over guard word */
 | |
| 	++p;
 | |
| 	/* move the significand */
 | |
| 	for (i = 0; i < NE - 1; i++)
 | |
| 		*q-- = *p++;
 | |
| }
 | |
| 
 | |
| 
 | |
| #if USE_LDTOA
 | |
| 
 | |
| void __eiremain(short unsigned int *den, short unsigned int *num,
 | |
| 	 short unsigned int *equot )
 | |
| {
 | |
| 	long ld, ln;
 | |
| 	unsigned short j;
 | |
| 
 | |
| 	ld = den[E];
 | |
| 	ld -= __enormlz(den);
 | |
| 	ln = num[E];
 | |
| 	ln -= __enormlz(num);
 | |
| 	__ecleaz(equot);
 | |
| 	while (ln >= ld)
 | |
| 	{
 | |
| 		if(__ecmpm(den,num) <= 0)
 | |
| 		{
 | |
| 			__esubm(den, num);
 | |
| 			j = 1;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			j = 0;
 | |
| 		}
 | |
| 		__eshup1(equot);
 | |
| 		equot[NI - 1] |= j;
 | |
| 		__eshup1(num);
 | |
| 		ln -= 1;
 | |
| 	}
 | |
| 	__emdnorm( num, 0, 0, ln, 0, NBITS );
 | |
| }
 | |
| 
 | |
| 
 | |
| void __eadd1(const short unsigned int *  __restrict__ a,
 | |
| 		  const short unsigned int *  __restrict__ b,
 | |
| 		  short unsigned int *  __restrict__ c,
 | |
| 		  int subflg)
 | |
| {
 | |
| 	unsigned short ai[NI], bi[NI], ci[NI];
 | |
| 	int i, lost, j, k;
 | |
| 	long lt, lta, ltb;
 | |
| 
 | |
| #ifdef INFINITY
 | |
| 	if (__eisinf(a))
 | |
| 	{
 | |
| 		__emov(a, c);
 | |
| 		if( subflg )
 | |
| 			__eneg(c);
 | |
| 		return;
 | |
| 	}
 | |
| 	if (__eisinf(b))
 | |
| 	{
 | |
| 		__emov(b, c);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	__emovi(a, ai);
 | |
| 	__emovi(b, bi);
 | |
| 	if (sub)
 | |
| 		ai[0] = ~ai[0];
 | |
| 
 | |
| 	/* compare exponents */
 | |
| 	lta = ai[E];
 | |
| 	ltb = bi[E];
 | |
| 	lt = lta - ltb;
 | |
| 	if (lt > 0L)
 | |
| 	{	/* put the larger number in bi */
 | |
| 		__emovz(bi, ci);
 | |
| 		__emovz(ai, bi);
 | |
| 		__emovz(ci, ai);
 | |
| 		ltb = bi[E];
 | |
| 		lt = -lt;
 | |
| 	}
 | |
| 	lost = 0;
 | |
| 	if (lt != 0L)
 | |
| 	{
 | |
| 		if (lt < (long)(-NBITS - 1))
 | |
| 			goto done;	/* answer same as larger addend */
 | |
| 		k = (int)lt;
 | |
| 		lost = __eshift(ai, k); /* shift the smaller number down */
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		/* exponents were the same, so must compare significands */
 | |
| 		i = __ecmpm(ai, bi);
 | |
| 		if (i == 0)
 | |
| 		{ /* the numbers are identical in magnitude */
 | |
| 			/* if different signs, result is zero */
 | |
| 			if (ai[0] != bi[0])
 | |
| 			{
 | |
| 				__eclear(c);
 | |
| 				return;
 | |
| 			}
 | |
| 			/* if same sign, result is double */
 | |
| 			/* double denomalized tiny number */
 | |
| 			if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0))
 | |
| 			{
 | |
| 				__eshup1( bi );
 | |
| 				goto done;
 | |
| 			}
 | |
| 			/* add 1 to exponent unless both are zero! */
 | |
| 			for (j = 1; j < NI - 1; j++)
 | |
| 			{
 | |
| 				if (bi[j] != 0)
 | |
| 				{
 | |
| 				/* This could overflow, but let emovo take care of that. */
 | |
| 					ltb += 1;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 			bi[E] = (unsigned short )ltb;
 | |
| 			goto done;
 | |
| 		}
 | |
| 		if (i > 0)
 | |
| 		{	/* put the larger number in bi */
 | |
| 			__emovz(bi, ci);
 | |
| 			__emovz(ai, bi);
 | |
| 			__emovz(ci, ai);
 | |
| 		}
 | |
| 	}
 | |
| 	if (ai[0] == bi[0])
 | |
| 	{
 | |
| 		__eaddm(ai, bi);
 | |
| 		subflg = 0;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		__esubm(ai, bi);
 | |
| 		subflg = 1;
 | |
| 	}
 | |
| 	__emdnorm(bi, lost, subflg, ltb, 64, NBITS);
 | |
| 
 | |
| done:
 | |
| 	__emovo(bi, c);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* y = largest integer not greater than x
 | |
|  * (truncated toward minus infinity)
 | |
|  *
 | |
|  * unsigned short x[NE], y[NE]
 | |
|  *
 | |
|  * efloor( x, y );
 | |
|  */
 | |
| 
 | |
| 
 | |
| void __efloor(short unsigned int *x, short unsigned int *y)
 | |
| {
 | |
| 	register unsigned short *p;
 | |
| 	int e, expon, i;
 | |
| 	unsigned short f[NE];
 | |
| 	const unsigned short bmask[] = {
 | |
| 				0xffff,
 | |
| 				0xfffe,
 | |
| 				0xfffc,
 | |
| 				0xfff8,
 | |
| 				0xfff0,
 | |
| 				0xffe0,
 | |
| 				0xffc0,
 | |
| 				0xff80,
 | |
| 				0xff00,
 | |
| 				0xfe00,
 | |
| 				0xfc00,
 | |
| 				0xf800,
 | |
| 				0xf000,
 | |
| 				0xe000,
 | |
| 				0xc000,
 | |
| 				0x8000,
 | |
| 				0x0000,
 | |
| 	};
 | |
| 
 | |
| 	__emov(x, f); /* leave in external format */
 | |
| 	expon = (int) f[NE - 1];
 | |
| 	e = (expon & 0x7fff) - (EXONE - 1);
 | |
| 	if (e <= 0)
 | |
| 	{
 | |
| 		__eclear(y);
 | |
| 		goto isitneg;
 | |
| 	}
 | |
| 	/* number of bits to clear out */
 | |
| 	e = NBITS - e;
 | |
| 	__emov(f, y);
 | |
| 	if (e <= 0)
 | |
| 		return;
 | |
| 
 | |
| 	p = &y[0];
 | |
| 	while (e >= 16)
 | |
| 	{
 | |
| 		*p++ = 0;
 | |
| 		e -= 16;
 | |
| 	}
 | |
| 	/* clear the remaining bits */
 | |
| 	*p &= bmask[e];
 | |
| 	/* truncate negatives toward minus infinity */
 | |
| isitneg:
 | |
| 
 | |
| 	if ((unsigned short)expon & (unsigned short)0x8000)
 | |
| 	{
 | |
| 		for (i = 0; i < NE - 1; i++)
 | |
| 		{
 | |
| 			if (f[i] != y[i])
 | |
| 			{
 | |
| 				__esub( __eone, y, y );
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
| ;	Subtract external format numbers.
 | |
| ;
 | |
| ;	unsigned short a[NE], b[NE], c[NE];
 | |
| ;	esub( a, b, c );	 c = b - a
 | |
| */
 | |
| 
 | |
| void __esub(const short unsigned int *  a,
 | |
| 		 const short unsigned int *  b,
 | |
| 		 short unsigned int *  c)
 | |
| {
 | |
| #ifdef NANS
 | |
| 	if (__eisnan(a))
 | |
| 	{
 | |
| 		__emov (a, c);
 | |
| 		return;
 | |
| 	}
 | |
| 	if ( __eisnan(b))
 | |
| 	{
 | |
| 		__emov(b, c);
 | |
| 		return;
 | |
| 	}
 | |
| 	/* Infinity minus infinity is a NaN.
 | |
| 	 * Test for subtracting infinities of the same sign.
 | |
| 	 */
 | |
| 	if (__eisinf(a) && __eisinf(b) && ((__eisneg (a) ^ __eisneg (b)) == 0))
 | |
| 	{
 | |
| 		mtherr("esub", DOMAIN);
 | |
| 		__enan_NBITS( c );
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	__eadd1(a, b, c, 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ;	Divide.
 | |
| ;
 | |
| ;	unsigned short a[NI], b[NI], c[NI];
 | |
| ;	ediv( a, b, c );	c = b / a
 | |
| */
 | |
| 
 | |
| void __ediv(const short unsigned int *a,
 | |
| 		 const short unsigned int *b,
 | |
| 		 short unsigned int *c)
 | |
| {
 | |
| 	unsigned short ai[NI], bi[NI];
 | |
| 	int i;
 | |
| 	long lt, lta, ltb;
 | |
| 
 | |
| #ifdef NANS
 | |
| 	/* Return any NaN input. */
 | |
| 	if (__eisnan(a))
 | |
| 	{
 | |
| 		__emov(a, c);
 | |
| 		return;
 | |
| 	}
 | |
| 	if (__eisnan(b))
 | |
| 	{
 | |
| 		__emov(b, c);
 | |
| 		return;
 | |
| 	}
 | |
| 	/* Zero over zero, or infinity over infinity, is a NaN. */
 | |
| 	if ((__eiszero(a) && __eiszero(b))
 | |
| 	 || (__eisinf (a) && __eisinf (b)))
 | |
| 	{
 | |
| 		mtherr("ediv", DOMAIN);
 | |
| 		__enan_NBITS( c );
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| /* Infinity over anything else is infinity. */
 | |
| #ifdef INFINITY
 | |
| 	if (__eisinf(b))
 | |
| 	{
 | |
| 		if (__eisneg(a) ^ __eisneg(b))
 | |
| 			*(c + (NE - 1)) = 0x8000;
 | |
| 		else
 | |
| 			*(c + (NE - 1)) = 0;
 | |
| 		__einfin(c);
 | |
| 		return;
 | |
| 	}
 | |
| 	if (__eisinf(a))
 | |
| 	{
 | |
| 		__eclear(c);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	__emovi(a, ai);
 | |
| 	__emovi(b, bi);
 | |
| 	lta = ai[E];
 | |
| 	ltb = bi[E];
 | |
| 	if (bi[E] == 0)
 | |
| 	{ /* See if numerator is zero. */
 | |
| 		for (i = 1; i < NI - 1; i++)
 | |
| 		{
 | |
| 			if (bi[i] != 0)
 | |
| 			{
 | |
| 				ltb -= __enormlz(bi);
 | |
| 				goto dnzro1;
 | |
| 			}
 | |
| 		}
 | |
| 		__eclear(c);
 | |
| 		return;
 | |
| 	}
 | |
| dnzro1:
 | |
| 
 | |
| 	if (ai[E] == 0)
 | |
| 	{	/* possible divide by zero */
 | |
| 		for (i = 1; i < NI - 1; i++)
 | |
| 		{
 | |
| 			if (ai[i] != 0)
 | |
| 			{
 | |
| 				lta -= __enormlz(ai);
 | |
| 				goto dnzro2;
 | |
| 			}
 | |
| 		}
 | |
| 		if (ai[0] == bi[0])
 | |
| 			*(c + (NE - 1)) = 0;
 | |
| 		else
 | |
| 			*(c + (NE - 1)) = 0x8000;
 | |
| 		__einfin(c);
 | |
| 		mtherr("ediv", SING);
 | |
| 		return;
 | |
| 	}
 | |
| dnzro2:
 | |
| 
 | |
| 	i = __edivm(ai, bi);
 | |
| 	/* calculate exponent */
 | |
| 	lt = ltb - lta + EXONE;
 | |
| 	__emdnorm(bi, i, 0, lt, 64, NBITS);
 | |
| 	/* set the sign */
 | |
| 	if (ai[0] == bi[0])
 | |
| 		bi[0] = 0;
 | |
| 	else
 | |
| 		bi[0] = 0Xffff;
 | |
| 	__emovo(bi, c);
 | |
| }
 | |
| 
 | |
| void __e64toe(short unsigned int *pe, short unsigned int *y)
 | |
| {
 | |
| 	unsigned short yy[NI];
 | |
| 	unsigned short *p, *q, *e;
 | |
| 	int i;
 | |
| 
 | |
| 	e = pe;
 | |
| 	p = yy;
 | |
| 	for (i = 0; i < NE - 5; i++)
 | |
| 		*p++ = 0;
 | |
| #ifdef IBMPC
 | |
| 	for (i = 0; i < 5; i++)
 | |
| 		*p++ = *e++;
 | |
| #endif
 | |
| #ifdef DEC
 | |
| 	for (i = 0; i < 5; i++)
 | |
| 		*p++ = *e++;
 | |
| #endif
 | |
| #ifdef MIEEE
 | |
| 	p = &yy[0] + (NE - 1);
 | |
| 	*p-- = *e++;
 | |
| 	++e;
 | |
| 	for (i = 0; i < 4; i++)
 | |
| 		*p-- = *e++;
 | |
| #endif
 | |
| 
 | |
| #ifdef IBMPC
 | |
| 	/* For Intel long double, shift denormal significand up 1
 | |
| 	   -- but only if the top significand bit is zero.  */
 | |
| 	if ((yy[NE - 1] & 0x7fff) == 0 && (yy[NE - 2] & 0x8000) == 0)
 | |
| 	{
 | |
| 		unsigned short temp[NI + 1];
 | |
| 		__emovi(yy, temp);
 | |
| 		__eshup1(temp);
 | |
| 		__emovo(temp,y);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| #ifdef INFINITY
 | |
| 	/* Point to the exponent field.  */
 | |
| 	p = &yy[NE - 1];
 | |
| 	if (*p == 0x7fff)
 | |
| 	{
 | |
| #ifdef NANS
 | |
| #ifdef IBMPC
 | |
| 		for (i = 0; i < 4; i++)
 | |
| 		{
 | |
| 			if ((i != 3 && pe[i] != 0)
 | |
| 			  /* Check for Intel long double infinity pattern.  */
 | |
| 			  || (i == 3 && pe[i] != 0x8000))
 | |
| 			{
 | |
| 				__enan_NBITS(y);
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| #else
 | |
| 		for (i = 1; i <= 4; i++)
 | |
| 		{
 | |
| 			if (pe[i] != 0)
 | |
| 			{
 | |
| 				__enan_NBITS(y);
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| #endif
 | |
| #endif /* NANS */
 | |
| 		__eclear(y);
 | |
| 		__einfin(y);
 | |
| 		if (*p & 0x8000)
 | |
| 			__eneg(y);
 | |
| 		return;
 | |
| 	}
 | |
| #endif
 | |
| 	p = yy;
 | |
| 	q = y;
 | |
| 	for (i = 0; i < NE; i++)
 | |
| 		*q++ = *p++;
 | |
| }
 | |
| 
 | |
| #endif /* USE_LDTOA */ 
 |