📄 ieee.c
字号:
static void toe24( x, y )unsigned short *x, *y;{unsigned short i;unsigned short *p;#ifdef NANSif( eiisnan(x) ) { enan( y, 24 ); return; }#endifp = &x[0];#ifdef IBMPCy += 1;#endif#ifdef DECy += 1;#endif*y = 0; /* output high order */if( *p++ ) *y = 0x8000; /* output sign bit */i = *p++;if( i >= 255 ) { /* Saturate at largest number less than infinity. */#ifdef INFINITIES *y |= (unsigned short )0x7f80;#ifdef IBMPC *(--y) = 0;#endif#ifdef DEC *(--y) = 0;#endif#ifdef MIEEE ++y; *y = 0;#endif#else *y |= (unsigned short )0x7f7f;#ifdef IBMPC *(--y) = 0xffff;#endif#ifdef DEC *(--y) = 0xffff;#endif#ifdef MIEEE ++y; *y = 0xffff;#endif#endif return; }if( i == 0 ) { (void )eshift( x, 7 ); }else { i <<= 7; (void )eshift( x, 8 ); }i |= *p++ & (unsigned short )0x7f; /* *p = xi[M] */*y |= i; /* high order output already has sign bit set */#ifdef IBMPC*(--y) = *p;#endif#ifdef DEC*(--y) = *p;#endif#ifdef MIEEE++y;*y = *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( a, b )unsigned short *a, *b;{unsigned short ai[NI], bi[NI];register unsigned short *p, *q;register int i;int msign;#ifdef NANSif (eisnan (a) || eisnan (b)) return( -2 );#endifemovi( 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 */}/* Find nearest integer to x = floor( x + 0.5 ) * * unsigned short x[NE], y[NE] * eround( x, y ); */void eround( x, y )unsigned short *x, *y;{eadd( ehalf, x, y );efloor( y, y );}/*; convert long (32-bit) integer to e type;; long l;; unsigned short x[NE];; ltoe( &l, x );; note &l is the memory address of l*/void ltoe( lp, y )long *lp; /* lp is the memory address of a long integer */unsigned short *y; /* y is the address of a short */{unsigned short yi[NI];unsigned long ll;int k;ecleaz( yi );if( *lp < 0 ) { ll = (unsigned long )( -(*lp) ); /* make it positive */ yi[0] = 0xffff; /* put correct sign in the e type number */ }else { ll = (unsigned long )( *lp ); }/* move the long integer to yi significand area */if( sizeof(long) == 8 ) { yi[M] = (unsigned short) (ll >> (LONGBITS - 16)); yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32)); yi[M + 2] = (unsigned short) (ll >> 16); yi[M + 3] = (unsigned short) ll; yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */ }else { yi[M] = (unsigned short )(ll >> 16); yi[M+1] = (unsigned short )ll; yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */ }if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */ ecleaz( yi ); /* it was zero */else yi[E] -= (unsigned short )k; /* subtract shift count from exponent */emovo( yi, y ); /* output the answer */}/*; convert unsigned long (32-bit) integer to e type;; unsigned long l;; unsigned short x[NE];; ltox( &l, x );; note &l is the memory address of l*/void ultoe( lp, y )unsigned long *lp; /* lp is the memory address of a long integer */unsigned short *y; /* y is the address of a short */{unsigned short yi[NI];unsigned long ll;int k;ecleaz( yi );ll = *lp;/* move the long integer to ayi significand area */if( sizeof(long) == 8 ) { yi[M] = (unsigned short) (ll >> (LONGBITS - 16)); yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32)); yi[M + 2] = (unsigned short) (ll >> 16); yi[M + 3] = (unsigned short) ll; yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */ }else { yi[M] = (unsigned short )(ll >> 16); yi[M+1] = (unsigned short )ll; yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */ }if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */ ecleaz( yi ); /* it was zero */else yi[E] -= (unsigned short )k; /* subtract shift count from exponent */emovo( yi, y ); /* output the answer */}/*; Find long integer and fractional parts; long i;; unsigned short x[NE], frac[NE];; xifrac( x, &i, frac ); The integer output has the sign of the input. The fraction is the positive fractional part of abs(x).*/void eifrac( x, i, frac )unsigned short *x;long *i;unsigned short *frac;{unsigned short xi[NI];int j, k;unsigned long ll;emovi( x, xi );k = (int )xi[E] - (EXONE - 1);if( k <= 0 ) {/* if exponent <= 0, integer = 0 and real output is fraction */ *i = 0L; emovo( xi, frac ); return; }if( k > (8 * sizeof(long) - 1) ) {/*; long integer overflow: output large integer; and correct fraction*/ j = 8 * sizeof(long) - 1; if( xi[0] ) *i = (long) ((unsigned long) 1) << j; else *i = (long) (((unsigned long) (~(0L))) >> 1); (void )eshift( xi, k ); }if( k > 16 ) {/* Shift more than 16 bits: shift up k-16 mod 16 then shift by 16's.*/ j = k - ((k >> 4) << 4); eshift (xi, j); ll = xi[M]; k -= j; do { eshup6 (xi); ll = (ll << 16) | xi[M]; } while ((k -= 16) > 0); *i = ll; if (xi[0]) *i = -(*i); }else {/* shift not more than 16 bits */ eshift( xi, k ); *i = (long )xi[M] & 0xffff; if( xi[0] ) *i = -(*i); }xi[0] = 0;xi[E] = EXONE - 1;xi[M] = 0;if( (k = enormlz( xi )) > NBITS ) ecleaz( xi );else xi[E] -= (unsigned short )k;emovo( xi, frac );}/*; Find unsigned long integer and fractional parts; unsigned long i;; unsigned short x[NE], frac[NE];; xifrac( x, &i, frac ); A negative e type input yields integer output = 0 but correct fraction.*/void euifrac( x, i, frac )unsigned short *x;unsigned long *i;unsigned short *frac;{unsigned short xi[NI];int j, k;unsigned long ll;emovi( x, xi );k = (int )xi[E] - (EXONE - 1);if( k <= 0 ) {/* if exponent <= 0, integer = 0 and argument is fraction */ *i = 0L; emovo( xi, frac ); return; }if( k > (8 * sizeof(long)) ) {/*; long integer overflow: output large integer; and correct fraction*/ *i = ~(0L); (void )eshift( xi, k ); }else if( k > 16 ) {/* Shift more than 16 bits: shift up k-16 mod 16 then shift up by 16's.*/ j = k - ((k >> 4) << 4); eshift (xi, j); ll = xi[M]; k -= j; do { eshup6 (xi); ll = (ll << 16) | xi[M]; } while ((k -= 16) > 0); *i = ll; }else {/* shift not more than 16 bits */ eshift( xi, k ); *i = (long )xi[M] & 0xffff; }if( xi[0] ) /* A negative value yields unsigned integer 0. */ *i = 0L;xi[0] = 0;xi[E] = EXONE - 1;xi[M] = 0;if( (k = enormlz( xi )) > NBITS ) ecleaz( xi );else xi[E] -= (unsigned short )k;emovo( xi, frac );}/*; Shift significand;; Shifts significand area up or down by the number of bits; given by the variable sc.*/int eshift( x, sc )unsigned short *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(x)unsigned short 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 );}/* Convert e type number to decimal format ASCII string. * The constants are for 64 bit precision. */#define NTEN 12#define MAXP 4096#if NE == 10static unsigned short etens[NTEN + 1][NE] ={ {0x6576, 0x4a92, 0x804a, 0x153f, 0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */ {0x6a32, 0xce52, 0x329a, 0x28ce, 0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */ {0x526c, 0x50ce, 0xf18b, 0x3d28, 0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,}, {0x9c66, 0x58f8, 0xbc50, 0x5c54, 0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,}, {0x851e, 0xeab7, 0x98fe, 0x901b, 0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,}, {0x0235, 0x0137, 0x36b1, 0x336c, 0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,}, {0x50f8, 0x25fb, 0xc76b, 0x6b71, 0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,}, {0x0000, 0x0000, 0x0000, 0x0000, 0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,}, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,}, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,}, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,}, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,}, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */};static unsigned short emtens[NTEN + 1][NE] ={ {0x2030, 0xcffc, 0xa1c3, 0x8123, 0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */ {0x8264, 0xd2cb, 0xf2ea, 0x12d4, 0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */ {0xf53f, 0xf698, 0x6bd3, 0x0158, 0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,}, {0xe731, 0x04d4, 0xe3f2, 0xd332, 0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,}, {0xa23e, 0x5308, 0xfefb, 0x1155, 0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,}, {0xe26d, 0xdbde, 0xd05d, 0xb3f6, 0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,}, {0x2a20, 0x6224, 0x47b3, 0x98d7, 0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,}, {0x0b5b, 0x4af2, 0xa581, 0x18ed, 0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,}, {0xbf71, 0xa9b3, 0x7989, 0xbe68, 0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,}, {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b, 0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,}, {0xc155, 0xa4a8, 0x404e, 0x6113, 0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,}, {0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,}, {0xcccd, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */};#elsestatic unsigned short etens[NTEN+1][NE] = {{0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */{0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */{0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,},{0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,},{0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,},{0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,},{0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,},{0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,},{0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,},{0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,},{0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,},{0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,},{0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */};static unsigned short emtens[NTEN+1][NE] = {{0x2de4,0x9fde,0xd2ce,0x04c8,0xa6dd,0x0ad8,}, /* 10**-4096 */{0x4925,0x2de4,0x3436,0x534f,0xceae,0x256b,}, /* 10**-2048 */{0x87a6,0xc0bd,0xda57,0x82a5,0xa2a6,0x32b5,},{0x7133,0xd21c,0xdb23,0xee32,0x9049,0x395a,},{0xfa91,0x1939,0x637a,0x4325,0xc031,0x3cac,},{0xac7d,0xe4a0,0x64bc,0x467c,0xddd0,0x3e55,},{0x3f24,0xe9a5,0xa539,0xea27,0xa87f,0x3f2a,},{0x67de,0x94ba,0x4539,0x1ead,0xcfb1,0x3f94,},{0x4c2f,0xe15b,0xc44d,0x94be,0xe695,0x3fc9,},{0xfdc2,0xcefc,0x8461,0x7711,0xabcc,0x3fe4,},{0xd3c3,0x652b,0xe219,0x1758,0xd1b7,0x3ff1,},{0x3d71,0xd70a,0x70a3,0x0a3d,0xa3d7,0x3ff8,},{0xcccd,0xcccc,0xcccc,0xcccc,0xcccc,0x3ffb,}, /* 10**-1 */};#endifvoid e24toasc( x, string, ndigs )unsigned short x[];char *string;int ndigs;{unsigned short w[NI];e24toe( x, w );etoasc( w, string, ndigs );}void e53toasc( x, string, ndigs )unsigned short x[];char *string;int ndigs;{unsigned short w[NI];e53toe( x, w );etoasc( w, string, ndigs );}void e64toasc( x, string, ndigs )unsigned short x[];char *string;int ndigs;{unsigned short w[NI];e64toe( x, w );etoasc( w, string, ndigs );}void e113toasc (x, string, ndigs)unsigned short x[];char *string;int ndigs;{unsigned short w[NI];e113toe (x, w);etoasc (w, string, ndigs);}void etoasc( x, string, ndigs )unsigned short x[];char *string;int ndigs;{long digit;unsigned short y[NI], t[NI], u[NI], w[NI];unsigned short *p, *r, *ten;unsigned short sign;int i, j, k, expon, rndsav;char *s, *ss;unsigned short m;rndsav = rndprc;#ifdef NANSif( eisnan(x) ) { sprintf( string, " NaN " ); goto bxit; }#endifrndprc = NBITS; /* set to full precision */emov( x, y ); /* retain external format */if( y[NE-1] & 0x8000 ) { sign = 0xffff; y[NE-1] &= 0x7fff; }else { sign = 0; }expon = 0;ten = &etens[NTEN][0];emov( eone, t );/* Test for zero exponent */if( y[NE-1] == 0 ) { for( k=0; k<NE-1; k++ ) { if( y[k] != 0 ) goto tnzro; /* denormalized number */ } goto isone; /* legal all zeros */ }tnzro:/* Test for infinity. */if( y[NE-1] == 0x7fff ) { if( sign ) sprintf( string, " -Infinity " ); else sprintf( string, " Infinity " ); goto bxit; }/* Test for exponent nonzero but significand denormalized. * This is an error condition. */if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) ) { mtherr( "etoasc", DOMAIN ); sprintf( string, "NaN" ); goto bxit; }/* Compare to 1.0 */i = ecmp( eone, y );if( i == 0 ) goto isone;if( i < 0 ) { /* Number is greater than 1 *//* Convert significand to an integer and strip trailing decimal zeros. */ emov( y, u ); u[NE-1] = EXONE + NBITS - 1; p = &etens[NTEN-4][0]; m = 16;do { ediv( p, u, t ); efloor( t, w );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -