asciifp.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 568 行 · 第 1/2 页
C
568 行
int low, high;
int index = 0;
if( type != FLOAT && type != DOUBLE && type != EXTENDED ) return -1;
if( type == FLOAT ) {
parseFloat( *(float*)src, &temp, &e );
p = float_precision;
} else if( type == DOUBLE ) {
parseDouble( *(double*)src, &temp, &e );
p = double_precision;
} else {
parseExtended( src, &temp, &e );
p = extended_precision;
}
e++;
mp_init( &f, temp );
mp_init( &R, 0 );
mp_init( &S, 1 );
mp_init( &Mp, 0 );
mp_init( &Mn, 1 );
mp_init( &U, 0 );
mp_init( &mptemp, 1 );
mp_init( &mptemp2, 0 );
/* f * 2^(e-p) = src */
mp_shiftleft( &R, &f, max( e-p, 0 ) );
mp_shiftleft( &S, &S, max( 0, -(e-p) ) );
/* assert R/S = f * 2^(e-p) = src */
mp_shiftleft( &Mn, &Mn, max( e-p, 0 ) );
mp_copy( &Mp, &Mn );
mp_shiftleft( &mptemp, &mptemp, p - 1 );
if( mp_eq( &f, &mptemp ) ) {
/* border case: src is a power of 2 */
mp_shiftleft( &Mp, &Mp, 1 );
mp_shiftleft( &R, &R, 1 );
mp_shiftleft( &S, &S, 1 );
}
for(;;) {
mp_divsc( &mptemp, &S, 10, CEILING );
if( mp_gte( &R, &mptemp ) ) break;
k--;
mp_mulsc( &R, &R, 10 );
mp_mulsc( &Mn, &Mn, 10 );
mp_mulsc( &Mp, &Mp, 10 );
}
/* assert k = min( 0, 1 + floor( logv ) ) */
mp_mulsc( &mptemp, &R, 2 );
mp_add( &mptemp, &mptemp, &Mp );
for(;;) {
mp_mulsc( &mptemp2, &S, 2 );
if( mp_lt( &mptemp, &mptemp2 ) ) break;
mp_mulsc( &S, &S, 10 );
k++;
}
*H = k - 1;
for(;;) {
k--;
mp_mulsc( &R, &R, 10 );
mp_div( &U, &R, &R, &S );
mp_mulsc( &Mn, &Mn, 10 );
mp_mulsc( &Mp, &Mp, 10 );
mp_mulsc( &mptemp, &R, 2 );
mp_mulsc( &mptemp2, &S, 2 );
mp_sub( &mptemp2, &mptemp2, &Mp );
low = mp_lt( &mptemp, &Mn );
high = mp_gt( &mptemp, &mptemp2 );
if( high || low ) break;
D[index++] = U.num[0] + '0';
}
if( low && high ) {
mp_mulsc( &mptemp, &R, 2 );
if( mp_lte( &mptemp, &S ) ) {
D[index++] = U.num[0] + '0';
} else {
D[index++] = U.num[0] + '1';
}
} else if( low ) {
D[index++] = U.num[0] + '0';
} else if( high ) {
D[index++] = U.num[0] + '1';
}
D[index] = '\0';
*N = k;
mp_free( &f );
mp_free( &R );
mp_free( &S );
mp_free( &Mn );
mp_free( &Mp );
mp_free( &U );
mp_free( &mptemp );
mp_free( &mptemp2 );
return 0;
}
/* This function will round the decimal string at the given location and then
* set the character after the location to NULL.
* Return 1 when a number like "99999" rounds to "1". (Most significant bit
* is in a new location.)
*/
int RoundString( char *str, int loc )
{
int cur = loc + 1;
int round = 0;
if( str[cur] > '5' ) {
round = 1; /* round up */
} else if( str[cur] < '5' ) {
round = -1; /* round down */
} else {
cur++;
while( str[cur] != '\0' ) {
if( str[cur] > '0' ) {
round = 1; /* round up */
break;
}
cur++;
}
if( round == 0 ) {
if( (str[loc] - '0') % 2 == 0 ) {
round = -1; /* round down */
} else {
round = 1; /* round up */
}
}
}
cur = loc;
if( round == 1 ) {
while( cur >= 0 && str[cur] == '9' ) {
str[cur] = '0';
cur--;
}
if( cur == -1 ) {
str[0] = '1';
str[1] = '\0';
return 1;
}
str[cur] = str[cur] + 1;
}
str[cur+1] = '\0';
return 0;
}
/* This function formats a string generated by the GenerateString function.
* The formated string will use E notation of the number is between 1e+10
* and 1e-4 and will just output the decimal number in normal notation
* otherwise. If there isn't enough room to fit the full mantissa and the
* exponent, it rounds the mantissa.
* Returns -1 if maxlen is too small to display a rounded mantissa and
* exponent in E notation.
*/
int FormatString( char *dst, char *src, int least, int most, int maxlen )
{
int i, j, src_index = 0, dst_index = 0, exp_size;
if( most > 9 || most < -3 || most - least >= maxlen ) {
/* use E notation */
char buf[10];
/* determine size of exponent part */
if( most > 99 || most < -99 ) {
exp_size = 5;
} else if( most > 9 || most < -9 ) {
exp_size = 4;
} else {
exp_size = 3;
}
if( maxlen < exp_size + 3 ) return -1; /* not enough room */
if( most - least + exp_size >= maxlen ) {
/* need to round */
if( RoundString( src, maxlen - exp_size - 3 ) == 1 ) {
most++;
}
}
dst[dst_index++] = src[src_index++];
if( most - least > 0 ) dst[dst_index++] = '.';
for( i = most - 1; i >= least; i-- ) {
if( src[src_index] == '\0' ) break;
dst[dst_index++] = src[src_index++];
}
dst[dst_index++] = 'E';
if( most > 0 ) dst[dst_index++] = '+';
itoa( most, buf, 10 );
i = 0;
while( buf[i] != '\0' ) {
dst[dst_index++] = buf[i++];
}
} else {
i = most;
j = least;
if( i < 0 ) i = 0;
if( j > 0 ) j = 0;
for( ; i >= j; i-- ) {
if( i > most ) {
if( i == -1 ) dst[dst_index++] = '.';
dst[dst_index++] = '0';
} else if( i < least ) {
dst[dst_index++] = '0';
} else {
if( i == -1 ) dst[dst_index++] = '.';
dst[dst_index++] = src[src_index++];
}
}
}
dst[dst_index] = '\0';
return 0;
}
/* Convert a binary floating-point number to a string */
int r2a( char *dst, void *src, int type, int maxlen )
{
int rc;
int N, H;
char str[20];
rc = GenerateString( str, src, type, &N, &H );
rc = FormatString( dst, str, N, H, maxlen );
return rc;
}
int e2a( char *ascii, char *ext, int maxlen )
{
/* NYI */
return( r2a( ascii, ext, EXTENDED, maxlen ) );
}
int d2a( char *ascii, double *dbl, int maxlen )
{
/* first check special cases */
if( *(uint64*)dbl == DOUBLE_POS_ZERO ) {
strcpy( ascii, ASCII_POS_ZERO );
} else if( *(uint64*)dbl == DOUBLE_NEG_ZERO ) {
strcpy( ascii, ASCII_NEG_ZERO );
} else if( *(uint64*)dbl == DOUBLE_POS_INF ) {
strcpy( ascii, ASCII_POS_INF );
} else if( *(uint64*)dbl == DOUBLE_NEG_INF ) {
strcpy( ascii, ASCII_NEG_INF );
} else if( d_isNan( dbl ) ) {
strcpy( ascii, ASCII_NAN );
} else {
/* handle negative sign */
if( d_isNeg( dbl ) ) {
*ascii = '-';
ascii++;
dneg( dbl, dbl );
maxlen--;
}
return( r2a( ascii, dbl, DOUBLE, maxlen ) );
}
return 0;
}
int f2a( char *ascii, float *flt, int maxlen )
{
/* first check special cases */
if( *(uint32*)flt == FLOAT_POS_ZERO ) {
strcpy( ascii, ASCII_POS_ZERO );
} else if( *(uint32*)flt == FLOAT_NEG_ZERO ) {
strcpy( ascii, ASCII_NEG_ZERO );
} else if( *(uint32*)flt == FLOAT_POS_INF ) {
strcpy( ascii, ASCII_POS_INF );
} else if( *(uint32*)flt == FLOAT_NEG_INF ) {
strcpy( ascii, ASCII_NEG_INF );
} else if( f_isNan( flt ) ) {
strcpy( ascii, ASCII_NAN );
} else {
/* handle negative sign */
if( f_isNeg( flt ) ) {
*ascii = '-';
ascii++;
fneg( flt, flt );
maxlen--;
}
return( r2a( ascii, flt, FLOAT, maxlen ) );
}
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?