⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee.c

📁 128位长双精度型数字运算包
💻 C
📖 第 1 页 / 共 5 页
字号:
		eshup1(equot);		equot[NI-2] |= j;		eshup1(num);		}	goto divdon;	}/* The number of quotient bits to calculate is * NBITS + 1 scaling guard bit + 1 roundoff bit. */fulldiv:p = &equot[NI-2];for( i=0; i<NBITS+2; i++ )	{	if( ecmpm(den,num) <= 0 )		{		esubm(den, num);		j = 1;	/* quotient bit = 1 */		}	else		j = 0;	eshup1(equot);	*p |= j;	eshup1(num);	}divdon:eshdn1( equot );eshdn1( equot );/* 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( a, b )unsigned short a[], b[];{unsigned short *p, *q;int i, j, k;equot[0] = b[0];equot[1] = b[1];for( i=M; i<NI; i++ )	equot[i] = 0;p = &a[NI-2];k = NBITS;while( *p == 0 ) /* significand is not supposed to be all zero */	{	eshdn6(a);	k -= 16;	}if( (*p & 0xff) == 0 )	{	eshdn8(a);	k -= 8;	}q = &equot[NI-1];j = 0;for( i=0; i<k; i++ )	{	if( *p & 1 )		eaddm(b, equot);/* remember if there were any nonzero bits shifted out */	if( *q & 1 )		j |= 1;	eshdn1(a);	eshdn1(equot);	}for( i=0; i<NI; i++ )	b[i] = equot[i];/* return flag for lost nonzero bits */return(j);}#else/* Multiply significand of e-type number bby 16-bit quantity a, e-type result to c. */void m16m( a, b, c )unsigned short a;unsigned short b[], 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 denominatoris permitted to have its high guard word nonzero.  */int edivm( den, num )unsigned short den[], num[];{int i;register unsigned short *p;unsigned long tnum;unsigned short j, tdenm, tquot;unsigned short tprod[NI+1];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 * 0xffffL) < 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 );			}		}/*	if( ecmpm( tprod, num ) > 0 )		{		eshow( "tprod", tprod );		eshow( "num  ", num );		printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",			 tnum, den[M+1], tquot );		}*/	esubm( tprod, num );/*	if( ecmpm( num, den ) >= 0 )		{		eshow( "num  ", num );		eshow( "den  ", den );		printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",			 tnum, den[M+1], tquot );		}*/	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( a, b )unsigned short a[], b[];{unsigned short *p, *q;unsigned short pprod[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 );}/*eshow(str, x)char *str;unsigned short *x;{int i;printf( "%s ", str );for( i=0; i<NI; i++ )	printf( "%04x ", *x++ );printf( "\n" );}*/#endif/* * 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 "exp" is the biased exponent, which may be negative. * the exponent field of "s" is ignored but is replaced by * "exp" as adjusted by normalization and rounding. * * Input "rcntrl" is the rounding control. */static int rlast = -1;static int rw = 0;static unsigned short rmsk = 0;static unsigned short rmbit = 0;static unsigned short rebit = 0;static int re = 0;static unsigned short rbit[NI] = {0,0,0,0,0,0,0,0};void emdnorm( s, lost, subflg, exp, rcntrl )unsigned short s[];int lost;int subflg;long exp;int rcntrl;{int i, j;unsigned short r;/* Normalize */j = enormlz( s );/* a blank significand could mean either zero or infinity. */#ifndef INFINITIESif( j > NBITS )	{	ecleazs( s );	return;	}#endifexp -= j;#ifndef INFINITIESif( exp >= 32767L )	goto overf;#elseif( (j > NBITS) && (exp < 32767L) )	{	ecleazs( s );	return;	}#endifif( exp < 0L )	{	if( exp > (long )(-NBITS-1) )		{		j = (int )exp;		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;/* Set up rounding parameters if the control register changed. */if( rndprc != rlast )	{	ecleaz( rbit );	switch( rndprc )		{		default:		case NBITS:			rw = NI-1; /* low guard word */			rmsk = 0xffff;			rmbit = 0x8000;			rebit = 1;			re = rw - 1;			break;		case 113:			rw = 10;			rmsk = 0x7fff;			rmbit = 0x4000;			rebit = 0x8000;			re = rw;			break;		case 64:			rw = 7;			rmsk = 0xffff;			rmbit = 0x8000;			rebit = 1;			re = rw-1;			break;/* For DEC arithmetic */		case 56:			rw = 6;			rmsk = 0xff;			rmbit = 0x80;			rebit = 0x100;			re = rw;			break;		case 53:			rw = 6;			rmsk = 0x7ff;			rmbit = 0x0400;			rebit = 0x800;			re = rw;			break;		case 24:			rw = 4;			rmsk = 0xff;			rmbit = 0x80;			rebit = 0x100;			re = rw;			break;		}	rbit[re] = rebit;	rlast = rndprc;	}/* 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. */#ifdef IBMPCif( (exp <= 0) && (rndprc != NBITS) )#elseif( (exp <= 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;if( (r & rmbit) != 0 )	{	if( r == rmbit )		{		if( lost == 0 )			{ /* round to even */			if( (s[re] & rebit) == 0 )				goto mddone;			}		else			{			if( subflg != 0 )				goto mddone;			}		}	eaddm( rbit, s );	}mddone:#ifdef IBMPCif( (exp <= 0) && (rndprc != NBITS) )#elseif( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) )#endif	{	eshup1(s);	}if( s[2] != 0 )	{ /* overflow on roundoff */	eshdn1(s);	exp += 1;	}mdfin:s[NI-1] = 0;if( exp >= 32767L )	{#ifndef INFINITIESoverf:#endif#ifdef INFINITIES	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;		if( rndprc == 24 )			{			s[5] = 0;			s[6] = 0;			}		}#endif	return;	}if( exp < 0 )	s[1] = 0;else	s[1] = (unsigned short )exp;}/*;	Subtract external format numbers.;;	unsigned short a[NE], b[NE], c[NE];;	esub( a, b, c );	 c = b - a*/static int subflg = 0;void esub( a, b, c )unsigned short *a, *b, *c;{#ifdef NANSif( 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( c, NBITS );	return;	}#endifsubflg = 1;eadd1( a, b, c );}/*;	Add.;;	unsigned short a[NE], b[NE], c[NE];;	eadd( a, b, c );	 c = b + a*/void eadd( a, b, c )unsigned short *a, *b, *c;{#ifdef NANS/* NaN plus anything is a NaN. */if( eisnan(a) )	{	emov(a,c);	return;	}if( eisnan(b) )	{	emov(b,c);	return;	}/* Infinity minus infinity is a NaN. * Test for adding infinities of opposite signs. */if( eisinf(a) && eisinf(b)	&& ((eisneg(a) ^ eisneg(b)) != 0) )	{	mtherr( "eadd", DOMAIN );	enan( c, NBITS );	return;	}#endifsubflg = 0;eadd1( a, b, c );}void eadd1( a, b, c )unsigned short *a, *b, *c;{unsigned short ai[NI], bi[NI], ci[NI];int i, lost, j, k;long lt, lta, ltb;#ifdef INFINITIESif( eisinf(a) )	{	emov(a,c);	if( subflg )		eneg(c);	return;	}if( eisinf(b) )	{	emov(b,c);	return;	}#endifemovi( a, ai );emovi( b, bi );if( subflg )	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 )				{				ltb += 1;				if( ltb >= 0x7fff )					{					eclear(c);					einfin(c);					if( ai[0] != 0 )						eneg(c);					return;					}				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 );done:emovo( bi, c );}/*;	Divide.;;	unsigned short a[NE], b[NE], c[NE];;	ediv( a, b, c );	c = b / a*/void ediv( a, b, c )unsigned short *a, *b, *c;{unsigned short ai[NI], bi[NI];int i, sign;long lt, lta, ltb;/* IEEE says if result is not a NaN, the sign is "-" if and only if   operands have opposite signs -- but flush -0 to 0 later if not IEEE.  */sign = eisneg(a) ^ eisneg(b);#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( ((ecmp(a,ezero) == 0) && (ecmp(b,ezero) == 0))	|| (eisinf (a) && eisinf (b)) )	{	mtherr( "ediv", DOMAIN );	enan( c, NBITS );	return;	}#endif/* Infinity over anything else is infinity. */#ifdef INFINITIESif( eisinf(b) )	{	einfin(c);	goto divsign;	}if( eisinf(a) )	{	eclear(c);	goto divsign;	}#endifemovi( 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);	goto divsign;	}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;			}		}	einfin(c);	mtherr( "ediv", SING );	goto divsign;	}dnzro2:i = edivm( ai, bi );/* calculate exponent */lt = ltb - lta + EXONE;emdnorm( bi, i, 0, lt, 64 );emovo( bi, c );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -