From 98ac2593b029d77021f65141b1f56672a524e8ec Mon Sep 17 00:00:00 2001 From: Keith Marshall Date: Fri, 7 Jan 2011 22:57:00 +0000 Subject: [PATCH] Correct hexadecimal formatting of double and long double values. --- winsup/mingw/ChangeLog | 9 +++ winsup/mingw/mingwex/stdio/pformat.c | 95 +++++++--------------------- 2 files changed, 32 insertions(+), 72 deletions(-) diff --git a/winsup/mingw/ChangeLog b/winsup/mingw/ChangeLog index fce92af24..bee0fa2ef 100644 --- a/winsup/mingw/ChangeLog +++ b/winsup/mingw/ChangeLog @@ -1,3 +1,12 @@ +2011-01-07 Jacky Lai + + Correct hexadecimal formatting of double and long double values. + + * mingwex/stdio/pformat.c (__pformat_xdouble): Delete function. + (__pformat) [A format]: Cast double values to long double, and use... + (__pformat_xldouble): ...this instead, with corrected adjustment of + exponent and alignment of mantissa, when formatting subnormals. + 2010-12-27 Ozkan Sezer * include/dirent.h (dd_handle): Define as intptr_t. diff --git a/winsup/mingw/mingwex/stdio/pformat.c b/winsup/mingw/mingwex/stdio/pformat.c index 55972fc45..de1daa91f 100644 --- a/winsup/mingw/mingwex/stdio/pformat.c +++ b/winsup/mingw/mingwex/stdio/pformat.c @@ -1660,74 +1660,6 @@ void __pformat_emit_xfloat( __pformat_fpreg_t value, __pformat_t *stream ) __pformat_int( exponent, stream ); } -static -void __pformat_xdouble( double x, __pformat_t *stream ) -{ - /* Handler for `%a' and `%A' format specifiers, (with argument - * value specified as `double' type). - */ - unsigned sign_bit = 0; - __pformat_fpreg_t z; z.__pformat_fpreg_double_t = x; - - /* First check for NaN; it is emitted unsigned... - */ - if( isnan( x ) ) - __pformat_emit_inf_or_nan( sign_bit, "NaN", stream ); - - else - { /* Capture the sign bit up-front, so we can show it correctly - * even when the argument value is zero or infinite. - */ - if( (sign_bit = (z.__pformat_fpreg_bitmap[3] & 0x8000)) != 0 ) - stream->flags |= PFORMAT_NEGATIVE; - - /* Check for infinity, (positive or negative)... - */ - if( isinf( x ) ) - /* - * displaying the appropriately signed indicator, - * when appropriate. - */ - __pformat_emit_inf_or_nan( sign_bit, "Inf", stream ); - - else - { /* The argument value is a representable number... - * first move its exponent into the appropriate field... - */ - z.__pformat_fpreg_bitmap[4] = (z.__pformat_fpreg_bitmap[3] >> 4) & 0x7FF; - - /* Realign the mantissa, leaving space for a - * normalised most significant digit... - */ - z.__pformat_fpreg_mantissa <<= 8; - z.__pformat_fpreg_bitmap[3] = (z.__pformat_fpreg_bitmap[3] & 0x0FFF); - - /* Check for zero value... - */ - if( z.__pformat_fpreg_exponent || z.__pformat_fpreg_mantissa ) - { - /* and only when the value is non-zero, - * eliminate the bias from the exponent... - */ - z.__pformat_fpreg_exponent -= 0x3FF; - - /* Check for a possible denormalised value... - */ - if( z.__pformat_fpreg_exponent > -126 ) - /* - * and normalise when it isn't. - */ - z.__pformat_fpreg_bitmap[3] += 0x1000; - } - - /* Finally, hand the adjusted representation off to the generalised - * hexadecimal floating point format handler... - */ - __pformat_emit_xfloat( z, stream ); - } - } -} - static void __pformat_xldouble( long double x, __pformat_t *stream ) { @@ -1763,9 +1695,28 @@ void __pformat_xldouble( long double x, __pformat_t *stream ) * extract the effective value of the biased exponent... */ z.__pformat_fpreg_exponent &= 0x7FFF; - if( z.__pformat_fpreg_exponent || z.__pformat_fpreg_mantissa ) - /* - * and if the argument value itself is non-zero, + if( z.__pformat_fpreg_exponent == 0 ) + { + /* A biased exponent value of zero means either a + * true zero value, if the mantissa field also has + * a zero value, otherwise... + */ + if( z.__pformat_fpreg_mantissa != 0 ) + { + /* ...this mantissa represents a subnormal value; + * adjust the exponent, while shifting the mantissa + * to the left, until its leading bit is 1. + */ + z.__pformat_fpreg_exponent = 1-0x3FFF; + while( (z.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0 ) + { + z.__pformat_fpreg_mantissa <<= 1; + --z.__pformat_fpreg_exponent; + } + } + } + else + /* This argument represents a non-zero normal number; * eliminate the bias from the exponent... */ z.__pformat_fpreg_exponent -= 0x3FFF; @@ -2147,7 +2098,7 @@ int __pformat( int flags, void *dest, int max, const char *fmt, va_list argv ) else /* or just a `double'. */ - __pformat_xdouble( va_arg( argv, double ), &stream ); + __pformat_xldouble( (long double)(va_arg( argv, double )), &stream ); goto format_scan;