📄 ieee.c
字号:
unsigned short i;
unsigned short *p;
#ifdef NANS
if( eiisnan(x) )
{
enan( y, 53 );
return;
}
#endif
p = &x[0];
#ifdef IBMPC
y += 3;
#endif
*y = 0; /* output high order */
if( *p++ )
*y = 0x8000; /* output sign bit */
i = *p++;
if( i >= (unsigned int )2047 )
{ /* Saturate at largest number less than infinity. */
#ifdef INFINITY
*y |= 0x7ff0;
#ifdef IBMPC
*(--y) = 0;
*(--y) = 0;
*(--y) = 0;
#endif
#ifdef MIEEE
++y;
*y++ = 0;
*y++ = 0;
*y++ = 0;
#endif
#else
*y |= (unsigned short )0x7fef;
#ifdef IBMPC
*(--y) = 0xffff;
*(--y) = 0xffff;
*(--y) = 0xffff;
#endif
#ifdef MIEEE
++y;
*y++ = 0xffff;
*y++ = 0xffff;
*y++ = 0xffff;
#endif
#endif
return;
}
if( i == 0 )
{
(void )eshift( x, 4 );
}
else
{
i <<= 4;
(void )eshift( x, 5 );
}
i |= *p++ & (unsigned short )0x0f; /* *p = xi[M] */
*y |= (unsigned short )i; /* high order output already has sign bit set */
#ifdef IBMPC
*(--y) = *p++;
*(--y) = *p++;
*(--y) = *p;
#endif
#ifdef MIEEE
++y;
*y++ = *p++;
*y++ = *p++;
*y++ = *p++;
#endif
}
#endif /* not DEC */
/*
; e type to IEEE single precision
; float d;
; unsigned short x[N+2];
; xtod( x, &d );
*/
void etoe24( x, e )
unsigned short *x, *e;
{
long exp;
unsigned short xi[NI];
int rndsav;
#ifdef NANS
if( eisnan(x) )
{
enan( e, 24 );
return;
}
#endif
emovi( x, xi );
exp = (long )xi[E] - (EXONE - 0177); /* adjust exponent for offsets */
#ifdef INFINITY
if( eisinf(x) )
goto nonorm;
#endif
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 24;
emdnorm( xi, 0, 0, exp, 64 );
rndprc = rndsav;
nonorm:
toe24( xi, e );
}
static void toe24( x, y )
unsigned short *x, *y;
{
unsigned short i;
unsigned short *p;
#ifdef NANS
if( eiisnan(x) )
{
enan( y, 24 );
return;
}
#endif
p = &x[0];
#ifdef IBMPC
y += 1;
#endif
#ifdef DEC
y += 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 INFINITY
*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 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 */
}
/* 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 == 10
static 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 */
};
#else
static 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,},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -