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

📄 ieee.c

📁 128位长双精度型数字运算包
💻 C
📖 第 1 页 / 共 5 页
字号:
/*							ieee.c * *    Extended precision IEEE binary floating point arithmetic routines * * Numbers are stored in C language as arrays of 16-bit unsigned * short integers.  The arguments of the routines are pointers to * the arrays. * * * External e type data structure, simulates Intel 8087 chip * temporary real format but possibly with a larger significand: * *	NE-1 significand words	(least significant word first, *				 most significant bit is normally set) *	exponent		(value = EXONE for 1.0, *				top bit is the sign) * * * Internal data structure of a number (a "word" is 16 bits): * * ei[0]	sign word	(0 for positive, 0xffff for negative) * ei[1]	biased exponent	(value = EXONE for the number 1.0) * ei[2]	high guard word	(always zero after normalization) * ei[3] * to ei[NI-2]	significand	(NI-4 significand words, *				 most significant word first, *				 most significant bit is set) * ei[NI-1]	low guard word	(0x8000 bit is rounding place) * * * *		Routines for external format numbers * *	asctoe( string, e )	ASCII string to extended double e type *	asctoe64( string, &d )	ASCII string to long double *	asctoe53( string, &d )	ASCII string to double *	asctoe24( string, &f )	ASCII string to single *	asctoeg( string, e, prec ) ASCII string to specified precision *	e24toe( &f, e )		IEEE single precision to e type *	e53toe( &d, e )		IEEE double precision to e type *	e64toe( &d, e )		IEEE long double precision to e type *	eabs(e)			absolute value *	eadd( a, b, c )		c = b + a *	eclear(e)		e = 0 *	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. *	ediv( a, b, c )		c = b / a *	efloor( a, b )		truncate to integer, toward -infinity *	efrexp( a, exp, s )	extract exponent and significand *	eifrac( e, &l, frac )   e to long integer and e type fraction *	euifrac( e, &l, frac )  e to unsigned long integer and e type fraction *	einfin( e )		set e to infinity, leaving its sign alone *	eldexp( a, n, b )	multiply by 2**n *	emov( a, b )		b = a *	emul( a, b, c )		c = b * a *	eneg(e)			e = -e *	eround( a, b )		b = nearest integer value to a *	esub( a, b, c )		c = b - a *	e24toasc( &f, str, n )	single to ASCII string, n digits after decimal *	e53toasc( &d, str, n )	double to ASCII string, n digits after decimal *	e64toasc( &d, str, n )	long double to ASCII string *	etoasc( e, str, n )	e to ASCII string, n digits after decimal *	etoe24( e, &f )		convert e type to IEEE single precision *	etoe53( e, &d )		convert e type to IEEE double precision *	etoe64( e, &d )		convert e type to IEEE long double precision *	ltoe( &l, e )		long (32 bit) integer to e type *	ultoe( &l, e )		unsigned long (32 bit) integer to e type *      eisneg( e )             1 if sign bit of e != 0, else 0 *      eisinf( e )             1 if e has maximum exponent (non-IEEE) *				or is infinite (IEEE) *      eisnan( e )             1 if e is a NaN *	esqrt( a, b )		b = square root of a * * *		Routines for internal format numbers * *	eaddm( ai, bi )		add significands, bi = bi + ai *	ecleaz(ei)		ei = 0 *	ecleazs(ei)		set ei = 0 but leave its sign alone *	ecmpm( ai, bi )		compare significands, return 1, 0, or -1 *	edivm( ai, bi )		divide  significands, bi = bi / ai *	emdnorm(ai,l,s,exp)	normalize and round off *	emovi( a, ai )		convert external a to internal ai *	emovo( ai, a )		convert internal ai to external a *	emovz( ai, bi )		bi = ai, low guard word of bi = 0 *	emulm( ai, bi )		multiply significands, bi = bi * ai *	enormlz(ei)		left-justify the significand *	eshdn1( ai )		shift significand and guards down 1 bit *	eshdn8( ai )		shift down 8 bits *	eshdn6( ai )		shift down 16 bits *	eshift( ai, n )		shift ai n bits up (or down if n < 0) *	eshup1( ai )		shift significand and guards up 1 bit *	eshup8( ai )		shift up 8 bits *	eshup6( ai )		shift up 16 bits *	esubm( ai, bi )		subtract significands, bi = bi - ai * * * The result is always normalized and rounded to NI-4 word precision * after each arithmetic operation. * * Exception flags are NOT fully supported. * * Define INFINITIES in mconf.h for support of infinity; otherwise a * saturation arithmetic is implemented. * * Define NANS for support of Not-a-Number items; otherwise the * arithmetic will never produce a NaN output, and might be confused * by a NaN input. * If NaN's are supported, the output of ecmp(a,b) is -2 if * either a or b is a NaN. This means asking if(ecmp(a,b) < 0) * may not be legitimate. Use if(ecmp(a,b) == -1) for less-than * if in doubt. * Signaling NaN's are NOT supported; they are treated the same * as quiet NaN's. * * Denormals are always supported here where appropriate (e.g., not * for conversion to DEC numbers). *//* * Revision history: * *  5 Jan 84	PDP-11 assembly language version *  2 Mar 86	fixed bug in asctoq() *  6 Dec 86	C language version * 30 Aug 88	100 digit version, improved rounding * 15 May 92    80-bit long double support * * Author:  S. L. Moshier. */#include <stdio.h>#include "mconf.h"#include "ehead.h"/* Change UNK into something else. */#ifdef UNK#undef UNK#if BIGENDIAN#define MIEEE 1#else#define IBMPC 1#endif#endif/* NaN's require infinity support. */#ifdef NANS#ifndef INFINITIES#define INFINITIES#endif#endif/* This handles 64-bit long ints. */#define LONGBITS (8 * sizeof(long))/* Control register for rounding precision. * This can be set to 80 (if NE=6), 64, 56, 53, or 24 bits. */int rndprc = NBITS;extern int rndprc;void eaddm(), esubm(), emdnorm(), asctoeg(), enan();static void toe24(), toe53(), toe64(), toe113();void eremain(), einit(), eiremain();int ecmpm(), edivm(), emulm(), eisneg(), eisinf();void emovi(), emovo(), emovz(), ecleaz(), eadd1();void etodec(), todec(), dectoe();int eisnan(), eiisnan();void einit(){}/*; Clear out entire external format number.;; unsigned short x[];; eclear( x );*/void eclear( x )register unsigned short *x;{register int i;for( i=0; i<NE; i++ )	*x++ = 0;}/* Move external format number from a to b. * * emov( a, b ); */void emov( a, b )register unsigned short *a, *b;{register int i;for( i=0; i<NE; i++ )	*b++ = *a++;}/*;	Absolute value of external format number;;	short x[NE];;	eabs( x );*/void eabs(x)unsigned short x[];	/* x is the memory address of a short */{x[NE-1] &= 0x7fff; /* sign is top bit of last word of external format */}/*;	Negate external format number;;	unsigned short x[NE];;	eneg( x );*/void eneg(x)unsigned short x[];{#ifdef NANSif( eisnan(x) )	return;#endifx[NE-1] ^= 0x8000; /* Toggle the sign bit */}/* Return 1 if external format number is negative, * else return zero. */int eisneg(x)unsigned short x[];{#ifdef NANSif( eisnan(x) )	return( 0 );#endifif( x[NE-1] & 0x8000 )	return( 1 );else	return( 0 );}/* Return 1 if external format number has maximum possible exponent, * else return zero. */int eisinf(x)unsigned short x[];{if( (x[NE-1] & 0x7fff) == 0x7fff )	{#ifdef NANS	if( eisnan(x) )		return( 0 );#endif	return( 1 );	}else	return( 0 );}/* Check if e-type number is not a number. */int eisnan(x)unsigned short x[];{#ifdef NANSint i;/* NaN has maximum exponent */if( (x[NE-1] & 0x7fff) != 0x7fff )	return (0);/* ... and non-zero significand field. */for( i=0; i<NE-1; i++ )	{	if( *x++ != 0 )		return (1);	}#endifreturn (0);}/*; Fill entire number, including exponent and significand, with; largest possible number.  These programs implement a saturation; value that is an ordinary, legal number.  A special value; "infinity" may also be implemented; this would require tests; for that value and implementation of special rules for arithmetic; operations involving inifinity.*/void einfin(x)register unsigned short *x;{register int i;#ifdef INFINITIESfor( i=0; i<NE-1; i++ )	*x++ = 0;*x |= 32767;#elsefor( i=0; i<NE-1; i++ )	*x++ = 0xffff;*x |= 32766;if( rndprc < NBITS )	{	if (rndprc == 113)		{		*(x - 9) = 0;		*(x - 8) = 0;		}	if( rndprc == 64 )		{		*(x-5) = 0;		}	if( rndprc == 53 )		{		*(x-4) = 0xf800;		}	else		{		*(x-4) = 0;		*(x-3) = 0;		*(x-2) = 0xff00;		}	}#endif}/* Move in external format number, * converting it to internal format. */void emovi( a, b )unsigned short *a, *b;{register unsigned short *p, *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 INFINITIESif( (*(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;}/* Move internal format number out, * converting it to external format. */void emovo( a, b )unsigned short *a, *b;{register unsigned short *p, *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 INFINITIESif( *(p-1) == 0x7fff )	{#ifdef NANS	if( eiisnan(a) )		{		enan( b, NBITS );		return;		}#endif	einfin(b);	return;	}#endif/* skip over guard word */++p;/* move the significand */for( i=0; i<NE-1; i++ )	*q-- = *p++;}/* Clear out internal format number. */void ecleaz( xi )register unsigned short *xi;{register int i;for( i=0; i<NI; i++ )	*xi++ = 0;}/* same, but don't touch the sign. */void ecleazs( xi )register unsigned short *xi;{register int i;++xi;for(i=0; i<NI-1; i++)	*xi++ = 0;}/* Move internal format number from a to b. */void emovz( a, b )register unsigned short *a, *b;{register int i;for( i=0; i<NI-1; i++ )	*b++ = *a++;/* clear low guard word */*b = 0;}/* Return nonzero if internal format number is a NaN. */int eiisnan (x)unsigned short x[];{int i;if( (x[E] & 0x7fff) == 0x7fff )	{	for( i=M+1; i<NI; i++ )		{		if( x[i] != 0 )			return(1);		}	}return(0);}#ifdef INFINITIES/* Return nonzero if internal format number is infinite. */static int eiisinf (x)     unsigned short x[];{#ifdef NANS  if (eiisnan (x))    return (0);#endif  if ((x[E] & 0x7fff) == 0x7fff)    return (1);  return (0);}#endif/*;	Compare significands of numbers in internal format.;	Guard words are included in the comparison.;;	unsigned short a[NI], b[NI];;	cmpm( a, b );;;	for the significands:;	returns	+1 if a > b;		 0 if a == b;		-1 if a < b*/int ecmpm( a, b )register unsigned short *a, *b;{int i;a += M; /* skip up to significand area */b += M;for( i=M; i<NI; i++ )	{	if( *a++ != *b++ )		goto difrnt;	}return(0);difrnt:if( *(--a) > *(--b) )	return(1);else	return(-1);}/*;	Shift significand down by 1 bit*/void eshdn1(x)register unsigned short *x;{register unsigned short bits;int i;x += M;	/* point to significand area */bits = 0;for( i=M; i<NI; i++ )	{	if( *x & 1 )		bits |= 1;	*x >>= 1;	if( bits & 2 )		*x |= 0x8000;	bits <<= 1;	++x;	}	}/*;	Shift significand up by 1 bit*/void eshup1(x)register unsigned short *x;{register unsigned short bits;int i;x += NI-1;bits = 0;for( i=M; i<NI; i++ )	{	if( *x & 0x8000 )		bits |= 1;	*x <<= 1;	if( bits & 2 )		*x |= 1;	bits <<= 1;	--x;	}}/*;	Shift significand down by 8 bits*/void eshdn8(x)register unsigned short *x;{register unsigned short newbyt, oldbyt;int i;x += M;oldbyt = 0;for( i=M; i<NI; i++ )	{	newbyt = *x << 8;	*x >>= 8;	*x |= oldbyt;	oldbyt = newbyt;	++x;	}}/*;	Shift significand up by 8 bits*/void eshup8(x)register unsigned short *x;{int i;register unsigned short newbyt, oldbyt;x += NI-1;oldbyt = 0;for( i=M; i<NI; i++ )	{	newbyt = *x >> 8;	*x <<= 8;	*x |= oldbyt;	oldbyt = newbyt;	--x;	}}/*;	Shift significand up by 16 bits*/void eshup6(x)register unsigned short *x;{int i;register unsigned short *p;p = x + M;x += M + 1;for( i=M; i<NI-1; i++ )	*p++ = *x++;*p = 0;}/*;	Shift significand down by 16 bits*/void eshdn6(x)register unsigned short *x;{int i;register unsigned short *p;x += NI-1;p = x + 1;for( i=M; i<NI-1; i++ )	*(--p) = *(--x);*(--p) = 0;}/*;	Add significands;	x + y replaces y*/void eaddm( x, y )unsigned short *x, *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( x, y )unsigned short *x, *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;	}}/* Divide significands */static unsigned short equot[NI] = {0}; /* was static */#if 0int edivm( den, num )unsigned short den[], num[];{int i;register unsigned short *p, *q;unsigned short j;p = &equot[0];*p++ = num[0];*p++ = num[1];for( i=M; i<NI; i++ )	{	*p++ = 0;	}/* Use faster compare and subtraction if denominator * has only 15 bits of significance. */p = &den[M+2];if( *p++ == 0 )	{	for( i=M+3; i<NI; i++ )		{		if( *p++ != 0 )			goto fulldiv;		}	if( (den[M+1] & 1) != 0 )		goto fulldiv;	eshdn1(num);	eshdn1(den);	p = &den[M+1];	q = &num[M+1];	for( i=0; i<NBITS+2; i++ )		{		if( *p <= *q )			{			*q -= *p;			j = 1;			}		else			{			j = 0;			}

⌨️ 快捷键说明

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