This is the mail archive of the
glibc-cvs@sourceware.org
mailing list for the glibc project.
GNU C Library master sources branch master updated. glibc-2.16-ports-merge-350-ga9f8e53
- From: jsm28 at sourceware dot org
- To: glibc-cvs at sourceware dot org
- Date: 24 Sep 2012 15:38:40 -0000
- Subject: GNU C Library master sources branch master updated. glibc-2.16-ports-merge-350-ga9f8e53
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".
The branch, master has been updated
via a9f8e53a5b14ba481999ded036b025554ea06362 (commit)
from eaf6f205fff7ca8a628869e3bc56800020a70f24 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a9f8e53a5b14ba481999ded036b025554ea06362
commit a9f8e53a5b14ba481999ded036b025554ea06362
Author: Joseph Myers <joseph@codesourcery.com>
Date: Mon Sep 24 15:38:21 2012 +0000
Make printf respect the rounding mode for hex output (bug 5044).
diff --git a/ChangeLog b/ChangeLog
index a04e104..b8c492e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2012-09-24 Joseph Myers <joseph@codesourcery.com>
+
+ [BZ #5044]
+ * stdio-common/printf_fphex.c: Include <stdbool.h> and
+ <rounding-mode.h>.
+ (__printf_fphex): Determine rounding using get_rounding_mode and
+ round_away.
+ * stdio-common/tst-printf-round.c (struct hex_test): New
+ structure.
+ (hex_tests): New variable.
+ (test_hex_in_one_mode): New function.
+ (do_test): Also run tests for hex float output.
+
2012-09-21 Joseph Myers <joseph@codesourcery.com>
* libio/iopopen.c [_IO_HAVE_SYS_WAIT]: Make code unconditional.
diff --git a/NEWS b/NEWS
index d9dfd20..84c05d5 100644
--- a/NEWS
+++ b/NEWS
@@ -9,12 +9,12 @@ Version 2.17
* The following bugs are resolved with this release:
- 1349, 3479, 5400, 6778, 6808, 9685, 9914, 10014, 10038, 11607, 13412,
- 13542, 13717, 13696, 13939, 13966, 14042, 14090, 14166, 14150, 14151,
- 14154, 14157, 14166, 14173, 14195, 14237, 14252, 14283, 14298, 14303,
- 14307, 14328, 14331, 14336, 14337, 14347, 14349, 14459, 14476, 14505,
- 14510, 14516, 14518, 14519, 14532, 14538, 14544, 14545, 14576, 14579,
- 14583, 14587.
+ 1349, 3479, 5044, 5400, 6778, 6808, 9685, 9914, 10014, 10038, 11607,
+ 13412, 13542, 13717, 13696, 13939, 13966, 14042, 14090, 14166, 14150,
+ 14151, 14154, 14157, 14166, 14173, 14195, 14237, 14252, 14283, 14298,
+ 14303, 14307, 14328, 14331, 14336, 14337, 14347, 14349, 14459, 14476,
+ 14505, 14510, 14516, 14518, 14519, 14532, 14538, 14544, 14545, 14576,
+ 14579, 14583, 14587.
* Support for STT_GNU_IFUNC symbols added for s390 and s390x.
Optimized versions of memcpy, memset, and memcmp added for System z10 and
diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c
index 1349145..2224196 100644
--- a/stdio-common/printf_fphex.c
+++ b/stdio-common/printf_fphex.c
@@ -28,6 +28,8 @@
#include <_itoa.h>
#include <_itowa.h>
#include <locale/localeinfo.h>
+#include <stdbool.h>
+#include <rounding-mode.h>
/* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
#include <assert.h>
@@ -343,21 +345,33 @@ __printf_fphex (FILE *fp,
--numend;
}
+ bool do_round_away = false;
+
+ if (precision != -1 && precision < numend - numstr)
+ {
+ char last_digit = precision > 0 ? numstr[precision - 1] : leading;
+ char next_digit = numstr[precision];
+ int last_digit_value = (last_digit >= 'A' && last_digit <= 'F'
+ ? last_digit - 'A' + 10
+ : (last_digit >= 'a' && last_digit <= 'f'
+ ? last_digit - 'a' + 10
+ : last_digit - '0'));
+ int next_digit_value = (next_digit >= 'A' && next_digit <= 'F'
+ ? next_digit - 'A' + 10
+ : (next_digit >= 'a' && next_digit <= 'f'
+ ? next_digit - 'a' + 10
+ : next_digit - '0'));
+ bool more_bits = ((next_digit_value & 7) != 0
+ || precision + 1 < numend - numstr);
+ int rounding_mode = get_rounding_mode ();
+ do_round_away = round_away (negative, last_digit_value & 1,
+ next_digit_value >= 8, more_bits,
+ rounding_mode);
+ }
+
if (precision == -1)
precision = numend - numstr;
- else if (precision < numend - numstr
- && (numstr[precision] > '8'
- || (('A' < '0' || 'a' < '0')
- && numstr[precision] < '0')
- || (numstr[precision] == '8'
- && (precision + 1 < numend - numstr
- /* Round to even. */
- || (precision > 0
- && ((numstr[precision - 1] & 1)
- ^ (isdigit (numstr[precision - 1]) == 0)))
- || (precision == 0
- && ((leading & 1)
- ^ (isdigit (leading) == 0)))))))
+ else if (do_round_away)
{
/* Round up. */
int cnt = precision;
diff --git a/stdio-common/tst-printf-round.c b/stdio-common/tst-printf-round.c
index 2bd4607..7cc19c5 100644
--- a/stdio-common/tst-printf-round.c
+++ b/stdio-common/tst-printf-round.c
@@ -68,6 +68,99 @@ test_dec_in_one_mode (double d, const char *fmt, const char *expected,
}
}
+struct hex_test
+{
+ double d;
+ const char *fmt;
+ const char *rd[4], *rn[4], *rz[4], *ru[4];
+};
+
+static const struct hex_test hex_tests[] =
+ {
+ {
+ 0x1.fffffp+4, "%.1a",
+ { "0x1.fp+4", "0x3.fp+3", "0x7.fp+2", "0xf.fp+1" },
+ { "0x2.0p+4", "0x4.0p+3", "0x8.0p+2", "0x1.0p+5" },
+ { "0x1.fp+4", "0x3.fp+3", "0x7.fp+2", "0xf.fp+1" },
+ { "0x2.0p+4", "0x4.0p+3", "0x8.0p+2", "0x1.0p+5" }
+ },
+ {
+ -0x1.fffffp+4, "%.1a",
+ { "-0x2.0p+4", "-0x4.0p+3", "-0x8.0p+2", "-0x1.0p+5" },
+ { "-0x2.0p+4", "-0x4.0p+3", "-0x8.0p+2", "-0x1.0p+5" },
+ { "-0x1.fp+4", "-0x3.fp+3", "-0x7.fp+2", "-0xf.fp+1" },
+ { "-0x1.fp+4", "-0x3.fp+3", "-0x7.fp+2", "-0xf.fp+1" }
+ },
+ {
+ 0x1.88p+4, "%.1a",
+ { "0x1.8p+4", "0x3.1p+3", "0x6.2p+2", "0xc.4p+1" },
+ { "0x1.8p+4", "0x3.1p+3", "0x6.2p+2", "0xc.4p+1" },
+ { "0x1.8p+4", "0x3.1p+3", "0x6.2p+2", "0xc.4p+1" },
+ { "0x1.9p+4", "0x3.1p+3", "0x6.2p+2", "0xc.4p+1" }
+ },
+ {
+ -0x1.88p+4, "%.1a",
+ { "-0x1.9p+4", "-0x3.1p+3", "-0x6.2p+2", "-0xc.4p+1" },
+ { "-0x1.8p+4", "-0x3.1p+3", "-0x6.2p+2", "-0xc.4p+1" },
+ { "-0x1.8p+4", "-0x3.1p+3", "-0x6.2p+2", "-0xc.4p+1" },
+ { "-0x1.8p+4", "-0x3.1p+3", "-0x6.2p+2", "-0xc.4p+1" }
+ },
+ {
+ 0x1.78p+4, "%.1a",
+ { "0x1.7p+4", "0x2.fp+3", "0x5.ep+2", "0xb.cp+1" },
+ { "0x1.8p+4", "0x2.fp+3", "0x5.ep+2", "0xb.cp+1" },
+ { "0x1.7p+4", "0x2.fp+3", "0x5.ep+2", "0xb.cp+1" },
+ { "0x1.8p+4", "0x2.fp+3", "0x5.ep+2", "0xb.cp+1" }
+ },
+ {
+ -0x1.78p+4, "%.1a",
+ { "-0x1.8p+4", "-0x2.fp+3", "-0x5.ep+2", "-0xb.cp+1" },
+ { "-0x1.8p+4", "-0x2.fp+3", "-0x5.ep+2", "-0xb.cp+1" },
+ { "-0x1.7p+4", "-0x2.fp+3", "-0x5.ep+2", "-0xb.cp+1" },
+ { "-0x1.7p+4", "-0x2.fp+3", "-0x5.ep+2", "-0xb.cp+1" }
+ },
+ {
+ 64.0 / 3.0, "%.1a",
+ { "0x1.5p+4", "0x2.ap+3", "0x5.5p+2", "0xa.ap+1" },
+ { "0x1.5p+4", "0x2.bp+3", "0x5.5p+2", "0xa.bp+1" },
+ { "0x1.5p+4", "0x2.ap+3", "0x5.5p+2", "0xa.ap+1" },
+ { "0x1.6p+4", "0x2.bp+3", "0x5.6p+2", "0xa.bp+1" }
+ },
+ {
+ -64.0 / 3.0, "%.1a",
+ { "-0x1.6p+4", "-0x2.bp+3", "-0x5.6p+2", "-0xa.bp+1" },
+ { "-0x1.5p+4", "-0x2.bp+3", "-0x5.5p+2", "-0xa.bp+1" },
+ { "-0x1.5p+4", "-0x2.ap+3", "-0x5.5p+2", "-0xa.ap+1" },
+ { "-0x1.5p+4", "-0x2.ap+3", "-0x5.5p+2", "-0xa.ap+1" }
+ },
+ };
+
+static int
+test_hex_in_one_mode (double d, const char *fmt, const char *expected[4],
+ const char *mode_name)
+{
+ char buf[100];
+ int ret = snprintf (buf, sizeof buf, fmt, d);
+ if (ret <= 0 || ret >= (int) sizeof buf)
+ {
+ printf ("snprintf for %a returned %d\n", d, ret);
+ return 1;
+ }
+ if (strcmp (buf, expected[0]) == 0
+ || strcmp (buf, expected[1]) == 0
+ || strcmp (buf, expected[2]) == 0
+ || strcmp (buf, expected[3]) == 0)
+ return 0;
+ else
+ {
+ printf ("snprintf (\"%s\", %a) returned \"%s\" not "
+ "\"%s\" or \"%s\" or \"%s\" or \"%s\" (%s)\n",
+ fmt, d, buf, expected[0], expected[1], expected[2], expected[3],
+ mode_name);
+ return 1;
+ }
+}
+
static int
do_test (void)
{
@@ -103,6 +196,37 @@ do_test (void)
}
#endif
}
+
+ for (size_t i = 0; i < sizeof (hex_tests) / sizeof (hex_tests[0]); i++)
+ {
+ result |= test_hex_in_one_mode (hex_tests[i].d, hex_tests[i].fmt,
+ hex_tests[i].rn, "default rounding mode");
+#ifdef FE_DOWNWARD
+ if (!fesetround (FE_DOWNWARD))
+ {
+ result |= test_hex_in_one_mode (hex_tests[i].d, hex_tests[i].fmt,
+ hex_tests[i].rd, "FE_DOWNWARD");
+ fesetround (save_round_mode);
+ }
+#endif
+#ifdef FE_TOWARDZERO
+ if (!fesetround (FE_TOWARDZERO))
+ {
+ result |= test_hex_in_one_mode (hex_tests[i].d, hex_tests[i].fmt,
+ hex_tests[i].rz, "FE_TOWARDZERO");
+ fesetround (save_round_mode);
+ }
+#endif
+#ifdef FE_UPWARD
+ if (!fesetround (FE_UPWARD))
+ {
+ result |= test_hex_in_one_mode (hex_tests[i].d, hex_tests[i].fmt,
+ hex_tests[i].ru, "FE_UPWARD");
+ fesetround (save_round_mode);
+ }
+#endif
+ }
+
return result;
}
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 13 ++++
NEWS | 12 ++--
stdio-common/printf_fphex.c | 40 +++++++++----
stdio-common/tst-printf-round.c | 124 +++++++++++++++++++++++++++++++++++++++
4 files changed, 170 insertions(+), 19 deletions(-)
hooks/post-receive
--
GNU C Library master sources