📄 ieee.c
字号:
{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 */
};
#endif
void 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 NANS
if( eisnan(x) )
{
sprintf( string, " NaN " );
goto bxit;
}
#endif
rndprc = 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 );
for( j=0; j<NE-1; j++ )
{
if( t[j] != w[j] )
goto noint;
}
emov( t, u );
expon += (int )m;
noint:
p += NE;
m >>= 1;
}
while( m != 0 );
/* Rescale from integer significand */
u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1);
emov( u, y );
/* Find power of 10 */
emov( eone, t );
m = MAXP;
p = &etens[0][0];
while( ecmp( ten, u ) <= 0 )
{
if( ecmp( p, u ) <= 0 )
{
ediv( p, u, u );
emul( p, t, t );
expon += (int )m;
}
m >>= 1;
if( m == 0 )
break;
p += NE;
}
}
else
{ /* Number is less than 1.0 */
/* Pad significand with trailing decimal zeros. */
if( y[NE-1] == 0 )
{
while( (y[NE-2] & 0x8000) == 0 )
{
emul( ten, y, y );
expon -= 1;
}
}
else
{
emovi( y, w );
for( i=0; i<NDEC+1; i++ )
{
if( (w[NI-1] & 0x7) != 0 )
break;
/* multiply by 10 */
emovz( w, u );
eshdn1( u );
eshdn1( u );
eaddm( w, u );
u[1] += 3;
while( u[2] != 0 )
{
eshdn1(u);
u[1] += 1;
}
if( u[NI-1] != 0 )
break;
if( eone[NE-1] <= u[1] )
break;
emovz( u, w );
expon -= 1;
}
emovo( w, y );
}
k = -MAXP;
p = &emtens[0][0];
r = &etens[0][0];
emov( y, w );
emov( eone, t );
while( ecmp( eone, w ) > 0 )
{
if( ecmp( p, w ) >= 0 )
{
emul( r, w, w );
emul( r, t, t );
expon += k;
}
k /= 2;
if( k == 0 )
break;
p += NE;
r += NE;
}
ediv( t, eone, t );
}
isone:
/* Find the first (leading) digit. */
emovi( t, w );
emovz( w, t );
emovi( y, w );
emovz( w, y );
eiremain( t, y );
digit = equot[NI-1];
while( (digit == 0) && (ecmp(y,ezero) != 0) )
{
eshup1( y );
emovz( y, u );
eshup1( u );
eshup1( u );
eaddm( u, y );
eiremain( t, y );
digit = equot[NI-1];
expon -= 1;
}
s = string;
if( sign )
*s++ = '-';
else
*s++ = ' ';
/* Examine number of digits requested by caller. */
if( ndigs < 0 )
ndigs = 0;
if( ndigs > NDEC )
ndigs = NDEC;
if( digit == 10 )
{
*s++ = '1';
*s++ = '.';
if( ndigs > 0 )
{
*s++ = '0';
ndigs -= 1;
}
expon += 1;
}
else
{
*s++ = (char )digit + '0';
*s++ = '.';
}
/* Generate digits after the decimal point. */
for( k=0; k<=ndigs; k++ )
{
/* multiply current number by 10, without normalizing */
eshup1( y );
emovz( y, u );
eshup1( u );
eshup1( u );
eaddm( u, y );
eiremain( t, y );
*s++ = (char )equot[NI-1] + '0';
}
digit = equot[NI-1];
--s;
ss = s;
/* round off the ASCII string */
if( digit > 4 )
{
/* Test for critical rounding case in ASCII output. */
if( digit == 5 )
{
emovo( y, t );
if( ecmp(t,ezero) != 0 )
goto roun; /* round to nearest */
if( (*(s-1) & 1) == 0 )
goto doexp; /* round to even */
}
/* Round up and propagate carry-outs */
roun:
--s;
k = *s & 0x7f;
/* Carry out to most significant digit? */
if( k == '.' )
{
--s;
k = *s;
k += 1;
*s = (char )k;
/* Most significant digit carries to 10? */
if( k > '9' )
{
expon += 1;
*s = '1';
}
goto doexp;
}
/* Round up and carry out from less significant digits */
k += 1;
*s = (char )k;
if( k > '9' )
{
*s = '0';
goto roun;
}
}
doexp:
/*
if( expon >= 0 )
sprintf( ss, "e+%d", expon );
else
sprintf( ss, "e%d", expon );
*/
sprintf( ss, "E%d", expon );
bxit:
rndprc = rndsav;
}
/*
; ASCTOQ
; ASCTOQ.MAC LATEST REV: 11 JAN 84
; SLM, 3 JAN 78
;
; Convert ASCII string to quadruple precision floating point
;
; Numeric input is free field decimal number
; with max of 15 digits with or without
; decimal point entered as ASCII from teletype.
; Entering E after the number followed by a second
; number causes the second number to be interpreted
; as a power of 10 to be multiplied by the first number
; (i.e., "scientific" notation).
;
; Usage:
; asctoq( string, q );
*/
/* ASCII to single */
void asctoe24( s, y )
char *s;
unsigned short *y;
{
asctoeg( s, y, 24 );
}
/* ASCII to double */
void asctoe53( s, y )
char *s;
unsigned short *y;
{
#ifdef DEC
asctoeg( s, y, 56 );
#else
asctoeg( s, y, 53 );
#endif
}
/* ASCII to long double */
void asctoe64( s, y )
char *s;
unsigned short *y;
{
asctoeg( s, y, 64 );
}
/* ASCII to 128-bit long double */
void asctoe113 (s, y)
char *s;
unsigned short *y;
{
asctoeg( s, y, 113 );
}
/* ASCII to super double */
void asctoe( s, y )
char *s;
unsigned short *y;
{
asctoeg( s, y, NBITS );
}
/* Space to make a copy of the input string: */
static char lstr[82] = {0};
void asctoeg( ss, y, oprec )
char *ss;
unsigned short *y;
int oprec;
{
unsigned short yy[NI], xt[NI], tt[NI];
int esign, decflg, sgnflg, nexp, exp, prec, lost;
int k, trail, c, rndsav;
long lexp;
unsigned short nsign, *p;
char *sp, *s;
/* Copy the input string. */
s = ss;
while( *s == ' ' ) /* skip leading spaces */
++s;
sp = lstr;
for( k=0; k<79; k++ )
{
if( (*sp++ = *s++) == '\0' )
break;
}
*sp = '\0';
s = lstr;
rndsav = rndprc;
rndprc = NBITS; /* Set to full precision */
lost = 0;
nsign = 0;
decflg = 0;
sgnflg = 0;
nexp = 0;
exp = 0;
prec = 0;
ecleaz( yy );
trail = 0;
nxtcom:
k = *s - '0';
if( (k >= 0) && (k <= 9) )
{
/* Ignore leading zeros */
if( (prec == 0) && (decflg == 0) && (k == 0) )
goto donchr;
/* Identify and strip trailing zeros after the decimal point. */
if( (trail == 0) && (decflg != 0) )
{
sp = s;
while( (*sp >= '0') && (*sp <= '9') )
++sp;
/* Check for syntax error */
c = *sp & 0x7f;
if( (c != 'e') && (c != 'E') && (c != '\0')
&& (c != '\n') && (c != '\r') && (c != ' ')
&& (c != ',') )
goto error;
--sp;
while( *sp == '0' )
*sp-- = 'z';
trail = 1;
if( *s == 'z' )
goto donchr;
}
/* If enough digits were given to more than fill up the yy register,
* continuing until overflow into the high guard word yy[2]
* guarantees that there will be a roundoff bit at the top
* of the low guard word after normalization.
*/
if( yy[2] == 0 )
{
if( decflg )
nexp += 1; /* count digits after decimal point */
eshup1( yy ); /* multiply current number by 10 */
emovz( yy, xt );
eshup1( xt );
eshup1( xt );
eaddm( xt, yy );
ecleaz( xt );
xt[NI-2] = (unsigned short )k;
eaddm( xt, yy );
}
else
{
/* Mark any lost non-zero digit. */
lost |= k;
/* Count lost digits before the decimal point. */
if (decflg == 0)
nexp -= 1;
}
prec += 1;
goto donchr;
}
switch( *s )
{
case 'z':
break;
case 'E':
case 'e':
goto expnt;
case '.': /* decimal point */
if( decflg )
goto error;
++decflg;
break;
case '-':
nsign = 0xffff;
if( sgnflg )
goto error;
++sgnflg;
break;
case '+':
if( sgnflg )
goto error;
++sgnflg;
break;
case ',':
case ' ':
case '\0':
case '\n':
case '\r':
goto daldone;
case 'i':
case 'I':
goto infinite;
default:
error:
#ifdef NANS
enan( yy, NI*16 );
#else
mtherr( "asctoe", DOMAIN );
ecleaz(yy);
#endif
goto aexit;
}
donchr:
++s;
goto nxtcom;
/* Exponent interpretation */
expnt:
esign = 1;
exp = 0;
++s;
/* check for + or - */
if( *s == '-' )
{
esign = -1;
++s;
}
if( *s == '+' )
++s;
while( (*s >= '0') && (*s <= '9') )
{
exp *= 10;
exp += *s++ - '0';
if (exp > 4977)
{
if (esign < 0)
goto zero;
else
goto infinite;
}
}
if( esign < 0 )
exp = -exp;
if( exp > 4932 )
{
infinite:
ecleaz(yy);
yy[E] = 0x7fff; /* infinity */
goto aexit;
}
if( exp < -4977 )
{
zero:
ecleaz(yy);
goto aexit;
}
daldone:
nexp = exp - nexp;
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
while( (nexp > 0) && (yy[2] == 0) )
{
emovz( yy, xt );
eshup1( xt );
eshup1( xt );
eaddm( yy, xt );
eshup1( xt );
if( xt[2] != 0 )
break;
nexp -= 1;
emovz( xt, yy );
}
if( (k = enormlz(yy)) > NBITS )
{
ecleaz(yy);
goto aexit;
}
lexp = (EXONE - 1 + NBITS) - k;
emdnorm( yy, lost, 0, lexp, 64 );
/* convert to external format */
/* Multiply by 10**nexp. If precision is 64 bits,
* the maximum relative error incurred in forming 10**n
* for 0 <= n <= 324 is 8.2e-20, at 10**180.
* For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
* For 0 >= n >= -999, it is -1.55e-19 at 10**-435.
*/
lexp = yy[E];
if( nexp == 0 )
{
k = 0;
goto expdon;
}
esign = 1;
if( nexp < 0 )
{
nexp = -nexp;
esign = -1;
if( nexp > 4096 )
{ /* Punt. Can't handle this without 2 divides. */
emovi( etens[0], tt );
lexp -= tt[E];
k = edivm( tt, yy );
lexp += EXONE;
nexp -= 4096;
}
}
p = &etens[NTEN][0];
emov( eone, xt );
exp = 1;
do
{
if( exp & nexp )
emul( p, xt, xt );
p -= NE;
exp = exp + exp;
}
while( exp <= MAXP );
emovi( xt, tt );
if( esign < 0 )
{
lexp -= tt[E];
k = edivm( tt, yy );
lexp += EXONE;
}
else
{
lexp += tt[E];
k = emulm( tt, yy );
lexp -= EXONE - 1;
}
expdon:
/* Round and convert directly to the destination type */
if( oprec == 53 )
lexp -= EXONE - 0x3ff;
else if( oprec == 24 )
lexp -= EXONE - 0177;
#ifdef DEC
else if( oprec == 56 )
lexp -= EXONE - 0201;
#endif
rndprc = oprec;
emdnorm( yy, k, 0, lexp, 64 );
aexit:
rndprc = rndsav;
yy[0] = nsign;
switch( oprec )
{
#ifdef DEC
case 56:
todec( yy, y ); /* see etodec.c */
break;
#endif
case 53:
toe53( yy, y );
break;
case 24:
toe24( yy, y );
break;
case 64:
toe64( yy, y );
break;
case 113:
toe113( yy, y );
break;
case NBITS:
emovo( yy, y );
break;
}
}
/* y = largest integer not greater than x
* (truncated toward minus infinity)
*
* unsigned short x[NE], y[NE]
*
* efloor( x, y );
*/
static unsigned short bmask[] = {
0xffff,
0xfffe,
0xfffc,
0xfff8,
0xfff0,
0xffe0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -