Finally, here's the patch to change double formatting in hexadecimal. As you
can see, I managed to find a way to fix it with little changes. Only a few
minor adjustments needed.
As for for formatting long doubles as doubles when their size is the same, the
evidence for it is in glibc's code:
if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
{
/* We have 52 bits of mantissa plus one implicit digit. Since
52 bits are representable without rest using hexadecimal
digits we use only the implicit digits for the number before
the decimal point. */
unsigned long long int num;
...
Tests:
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
int main(int argc, char **argv)
{
puts( " --- Doubles ---\n");
{
char buf[100];
snprintf(buf, sizeof buf, "%la", 6.07701e-322);
puts(buf);
char *end;
double v = strtod(buf, &end);
printf("%le\n", v);
if(v != 6.07701e-322)
puts("Test failed for formatting
6.07701e-322.");
else
puts("Test succeeded for formatting
6.07701e-322.");
}
printf("8.0 : %la\n", 8.0);
printf("1.5 : %la\n", 1.5);
printf("0.5 : %la\n", 0.5);
printf("2.0 : %la\n", 2.0);
printf("1.0 : %la\n", 1.0);
printf("0.0 : %la\n", 0.0);
printf("-8.0 : %la\n", -8.0);
printf("-1.5 : %la\n", -1.5);
printf("-0.5 : %la\n", -0.5);
printf("-2.0 : %la\n", -2.0);
printf("-1.0 : %la\n", -1.0);
printf("-0.0 : %la\n", -0.0);
printf("423.2323 : %la\n", 423.2323);
printf("-423.2323 : %la\n", -423.2323);
printf("999999.2323 : %la\n", 999999.2323);
printf("DBL_MAX : %la\n", DBL_MAX);
printf("-DBL_MAX : %la\n", -DBL_MAX);
puts( " [Denormalized]");
printf("6.07701e-322 : %la\n", 6.07701e-322);
printf("-6.07701e-322 : %la\n", -6.07701e-322);
printf("6.07701e-322 (.5) : %.5la\n", 6.07701e-322);
printf("-6.07701e-322 (.5) : %.5la\n", -6.07701e-322);
printf("0x0.0030p+0 : %la\n", 0x0.0030p+0);
printf("0x0.0040p+0 : %la\n", 0x0.0040p+0);
printf("0x0.0040p+0 : %40la\n", 0x0.0030p+0);
printf("0x0.0040p+0 : %#40la\n", 0x0.0040p+0);
printf("0x0.0040p+0 : %-40la\n", 0x0.0040p+0);
printf("0x0.0040p+0 : %#-40la\n", 0x0.0040p+0);
puts( " [Rounded]");
printf("423.2323 (.10) : %.10la\n", 423.2323);
printf("423.2323 (.20) : %.20la\n", 423.2323);
printf("423.2323 (.1) : %.1la\n", 423.2323);
printf("423.2323 (.0) : %.0la\n", 423.2323);
printf("0.0 (.10) : %.10la\n", 0.0);
printf("0.0 (.0) : %.0la\n", 0.0);
printf("-423.2323 (.10) : %.10la\n", -423.2323);
printf("-423.2323 (.20) : %.20la\n", -423.2323);
printf("-423.2323 (.1) : %.1la\n", -423.2323);
printf("-423.2323 (.0) : %.0la\n", -423.2323);
printf("-0.0 (.10) : %.10la\n", -0.0);
printf("-0.0 (.0) : %.0la\n", -0.0);
printf("0x0.F8p+0 (.2) : %.2la\n", 0x0.F8p+0);
printf("0x0.F7p+0 (.2) : %.2la\n", 0x0.F7p+0);
printf("0x1.F8p+0 (.1) : %.1la\n", 0x1.F8p+0);
printf("0x1.F7p+0 (.1) : %.1la\n", 0x1.F7p+0);
printf("0x0.000000000008p+0 (.1) : %.1la\n", 0x0.000000000008p+0);
printf("0x0.000000000007p+0 (.1) : %.1la\n", 0x0.000000000007p+0);
printf("DBL_MAX (.5) : %.5la\n", DBL_MAX);
puts("");
puts( " --- Long doubles ---\n");
{
char buf[100];
snprintf(buf, sizeof buf, "%La", 4.483595e-4949l);
puts(buf);
char *end;
long double v = strtold(buf, &end);
printf("%Le\n", v);
if(v != 4.483595e-4949l)
puts("Test failed for formatting
4.483595e-4949l.");
else
puts("Test succeeded for formatting
4.483595e-4949l.");
}
printf("8.0l : %La\n", 8.0l);
printf("1.5l : %La\n", 1.5l);
printf("0.5l : %La\n", 0.5l);
printf("2.0l : %La\n", 2.0l);
printf("1.0l : %La\n", 1.0l);
printf("0.0l : %La\n", 0.0l);
printf("-8.0l : %La\n", -8.0l);
printf("-1.5l : %La\n", -1.5l);
printf("-0.5l : %La\n", -0.5l);
printf("-2.0l : %La\n", -2.0l);
printf("-1.0l : %La\n", -1.0l);
printf("-0.0l : %La\n", -0.0l);
printf("423.2323l : %La\n", 423.2323l);
printf("-423.2323l : %La\n", -423.2323l);
printf("LDBL_MAX : %La\n", LDBL_MAX);
printf("-LDBL_MAX : %La\n", -LDBL_MAX);
puts( " [Denormalized]");
printf("4.4836e-4949l : %La\n", 4.4836e-4949l);
printf("-4.4836e-4949l : %La\n", -4.4836e-4949l);
printf("4.4836e-4949l (.5) : %.5La\n", 4.4836e-4949l);
printf("-4.4836e-4949l (.5) : %.5La\n", -4.4836e-4949l);
printf("0x0.0030p+0l : %La\n", 0x0.0030p+0l);
printf("0x0.0040p+0l : %La\n", 0x0.0040p+0l);
printf("0x0.0040p+0l : %40La\n", 0x0.0030p+0l);
printf("0x0.0040p+0l : %#40La\n", 0x0.0040p+0l);
printf("0x0.0040p+0l : %-40La\n", 0x0.0040p+0l);
printf("0x0.0040p+0l : %#-40La\n", 0x0.0040p+0l);
printf("0x2.0p-16385l : %La\n", 0x2.0p-16385l);
puts( " [Rounded]");
printf("423.2323l (.10) : %.10La\n", 423.2323l);
printf("423.2323l (.20) : %.20La\n", 423.2323l);
printf("423.2323l (.1) : %.1La\n", 423.2323l);
printf("423.2323l (.0) : %.0La\n", 423.2323l);
printf("0.0l (.10) : %.10La\n", 0.0l);
printf("0.0l (.0) : %.0La\n", 0.0l);
printf("-423.2323l (.10) : %.10La\n", -423.2323l);
printf("-423.2323l (.20) : %.20La\n", -423.2323l);
printf("-423.2323l (.1) : %.1La\n", -423.2323l);
printf("-423.2323l (.0) : %.0La\n", -423.2323l);
printf("-0.0l (.10) : %.10La\n", -0.0l);
printf("-0.0l (.0) : %.0La\n", -0.0l);
printf("0xF.8p+0l (.0) : %.0La\n", 0xF.8p+0l);
printf("0xF.7p+0l (.0) : %.0La\n", 0xF.7p+0l);
printf("0xF.F8p+0l (.1) : %.1La\n", 0xF.F8p+0l);
printf("0xF.F7p+0l (.1) : %.1La\n", 0xF.F7p+0l);
printf("0x0.000000000000008p+0l (.1) : %.1La\n",
0x0.000000000000008p+0l);
printf("0x0.000000000000007p+0l (.1) : %.1La\n",
0x0.000000000000007p+0l);
printf("LDBL_MAX (.5) : %.5La\n", LDBL_MAX);
return EXIT_SUCCESS;
}>From e91ad288e5a7da80c2f43a1065d228bf0214c2cb Mon Sep 17 00:00:00 2001
From: Patrick Northon <[email protected]>
Date: Fri, 10 Sep 2021 12:43:01 -0400
Subject: [PATCH] Change formatting of double precision floating-points in
hexadecimal to match glibc.
- Add new code path for doubles.
- Format long double as double if their size is the same.
Signed-off-by: Patrick Northon <[email protected]>
---
mingw-w64-crt/stdio/mingw_pformat.c | 82 ++++++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 2 deletions(-)
diff --git a/mingw-w64-crt/stdio/mingw_pformat.c b/mingw-w64-crt/stdio/mingw_pformat.c
index 3f1513516..b6fddb193 100644
--- a/mingw-w64-crt/stdio/mingw_pformat.c
+++ b/mingw-w64-crt/stdio/mingw_pformat.c
@@ -2319,6 +2319,84 @@ void __pformat_xldouble( long double x, __pformat_t *stream )
}
}
+static
+void __pformat_xdouble( double x, __pformat_t *stream )
+{
+ /* Handler for `%la' and `%lA' format specifiers, (with argument
+ * value specified as `double' type).
+ */
+ unsigned sign_bit = 0;
+ __pformat_fpreg_t z = init_fpreg_ldouble( (long double)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_exponent & 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...
+ * extract the effective value of the biased exponent...
+ */
+ z.__pformat_fpreg_exponent &= 0x7FFF;
+
+ /* If the double value was a denormalized number, it might have been renormalized by
+ * the conversion to long double. We will redenormalize it.
+ */
+ if( z.__pformat_fpreg_exponent != 0 && z.__pformat_fpreg_exponent <= (0x3FFF - 0x3FF) )
+ {
+ int shifted = (0x3FFF - 0x3FF) - z.__pformat_fpreg_exponent + 1;
+ z.__pformat_fpreg_mantissa >>= shifted;
+ z.__pformat_fpreg_exponent += shifted;
+ }
+
+ 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.
+ */
+ z.__pformat_fpreg_exponent = 1 - 0x3FF + 3;
+ }
+ }
+ else
+ /* This argument represents a non-zero normal number;
+ * eliminate the bias from the exponent...
+ */
+ z.__pformat_fpreg_exponent -= 0x3FFF - 3;
+
+ /* Shift the mantissa so the leading 4 bits digit is 0 or 1.
+ * The exponent was also adjusted by 3 previously.
+ */
+ z.__pformat_fpreg_mantissa >>= 3;
+
+ /* Finally, hand the adjusted representation off to the
+ * generalised hexadecimal floating point format handler...
+ */
+ __pformat_emit_xfloat( z, stream );
+ }
+ }
+}
+
int
__pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv)
{
@@ -2765,7 +2843,7 @@ __pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv)
* Hexadecimal floating point format; handles radix and
* exponent indicators in either upper or lower case...
*/
- if( stream.flags & PFORMAT_LDOUBLE )
+ if( sizeof( double ) != sizeof( long double ) && stream.flags & PFORMAT_LDOUBLE )
/*
* with a `long double' argument...
*/
@@ -2774,7 +2852,7 @@ __pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv)
else
/* or just a `double'.
*/
- __pformat_xldouble( (long double)(va_arg( argv, double )), &stream );
+ __pformat_xdouble( va_arg( argv, double ), &stream );
goto format_scan;
--
2.33.0
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public