aboutsummaryrefslogtreecommitdiff
path: root/stdio-common
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-02-21 08:57:44 +0000
committerUlrich Drepper <drepper@redhat.com>2007-02-21 08:57:44 +0000
commit0f7769f736a22aa930bebe3aa4f9656b671072b5 (patch)
treeebc113e13a24df6bd8aeadf0515d5ddfb918fd76 /stdio-common
parent4c02bf1adf285060e809ef5df8f796c8cf3fb04d (diff)
downloadglibc-0f7769f736a22aa930bebe3aa4f9656b671072b5.zip
glibc-0f7769f736a22aa930bebe3aa4f9656b671072b5.tar.gz
glibc-0f7769f736a22aa930bebe3aa4f9656b671072b5.tar.bz2
[BZ #4070]
2007-02-21 Ulrich Drepper <drepper@redhat.com> [BZ #4070] * stdio-common/printf_fp.c (___printf_fp): Handle a few more * stdio-common/tfformat.c (sprint_doubles): Some more tests. special cases.
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/printf_fp.c79
-rw-r--r--stdio-common/tfformat.c15
2 files changed, 62 insertions, 32 deletions
diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index cbc3143..c27c0d4 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -926,7 +926,8 @@ ___printf_fp (FILE *fp,
/* Generate the needed number of fractional digits. */
int fracdig_no = 0;
- while (fracdig_no < fracdig_min
+ int added_zeros = 0;
+ while (fracdig_no < fracdig_min + added_zeros
|| (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0)))
{
++fracdig_no;
@@ -937,7 +938,7 @@ ___printf_fp (FILE *fp,
{
++fracdig_max;
if (fracdig_min > 0)
- ++fracdig_min;
+ ++added_zeros;
}
}
@@ -974,11 +975,23 @@ ___printf_fp (FILE *fp,
{
/* Process fractional digits. Terminate if not rounded or
radix character is reached. */
+ int removed = 0;
while (*--wtp != decimalwc && *wtp == L'9')
- *wtp = L'0';
+ {
+ *wtp = L'0';
+ ++removed;
+ }
+ if (removed == fracdig_min && added_zeros > 0)
+ --added_zeros;
if (*wtp != decimalwc)
/* Round up. */
(*wtp)++;
+ else if (__builtin_expect (spec == 'g' && type == 'f' && info->alt,
+ 0))
+ /* This is a special case: the rounded number is 1.0,
+ the format is 'g' or 'G', and the alternative format
+ is selected. This means the result mist be "1.". */
+ --added_zeros;
}
if (fracdig_no == 0 || *wtp == decimalwc)
@@ -1045,7 +1058,7 @@ ___printf_fp (FILE *fp,
do_expo:
/* Now remove unnecessary '0' at the end of the string. */
- while (fracdig_no > fracdig_min && *(wcp - 1) == L'0')
+ while (fracdig_no > fracdig_min + added_zeros && *(wcp - 1) == L'0')
{
--wcp;
--fracdig_no;
@@ -1063,26 +1076,41 @@ ___printf_fp (FILE *fp,
/* Write the exponent if it is needed. */
if (type != 'f')
{
- *wcp++ = (wchar_t) type;
- *wcp++ = expsign ? L'-' : L'+';
+ if (__builtin_expect (expsign != 0 && exponent == 4 && spec == 'g', 0))
+ {
+ /* This is another special case. The exponent of the number is
+ really smaller than -4, which requires the 'e'/'E' format.
+ But after rounding the number has an exponent of -4. */
+ assert (wcp >= wstartp + 2);
+ assert (wstartp[0] == L'1');
+ __wmemcpy (wstartp, L"0.0001", 6);
+ wstartp[1] = decimalwc;
+ wmemset (wstartp + 6, L'0', wcp - (wstartp + 2));
+ wcp += 4;
+ }
+ else
+ {
+ *wcp++ = (wchar_t) type;
+ *wcp++ = expsign ? L'-' : L'+';
- /* Find the magnitude of the exponent. */
- expscale = 10;
- while (expscale <= exponent)
- expscale *= 10;
+ /* Find the magnitude of the exponent. */
+ expscale = 10;
+ while (expscale <= exponent)
+ expscale *= 10;
- if (exponent < 10)
- /* Exponent always has at least two digits. */
- *wcp++ = L'0';
- else
- do
- {
- expscale /= 10;
- *wcp++ = L'0' + (exponent / expscale);
- exponent %= expscale;
- }
- while (expscale > 10);
- *wcp++ = L'0' + exponent;
+ if (exponent < 10)
+ /* Exponent always has at least two digits. */
+ *wcp++ = L'0';
+ else
+ do
+ {
+ expscale /= 10;
+ *wcp++ = L'0' + (exponent / expscale);
+ exponent %= expscale;
+ }
+ while (expscale > 10);
+ *wcp++ = L'0' + exponent;
+ }
}
/* Compute number of characters which must be filled with the padding
@@ -1123,15 +1151,14 @@ ___printf_fp (FILE *fp,
else
thousands_sep_len = strlen (thousands_sep);
- if (buffer_malloced)
+ if (__builtin_expect (buffer_malloced, 0))
{
buffer = (char *) malloc (2 + chars_needed + decimal_len
+ ngroups * thousands_sep_len);
if (buffer == NULL)
{
/* Signal an error to the caller. */
- if (buffer_malloced)
- free (wbuffer);
+ free (wbuffer);
return -1;
}
}
@@ -1165,7 +1192,7 @@ ___printf_fp (FILE *fp,
PRINT (tmpptr, wstartp, wide ? wcp - wstartp : cp - tmpptr);
/* Free the memory if necessary. */
- if (buffer_malloced)
+ if (__builtin_expect (buffer_malloced, 0))
{
free (buffer);
free (wbuffer);
diff --git a/stdio-common/tfformat.c b/stdio-common/tfformat.c
index ea7365b..0370834 100644
--- a/stdio-common/tfformat.c
+++ b/stdio-common/tfformat.c
@@ -4012,6 +4012,14 @@ sprint_double_type sprint_doubles[] =
{__LINE__, 16, "0x1.0p+4", "%.1a"},
{__LINE__, 16, "0x1.00000000000000000000p+4", "%.20a"},
{__LINE__, 4444.88888888, "4445", "%2.F"},
+ {__LINE__, 0.956, "1", "%.0g"},
+ {__LINE__, 1.0956, "1.", "%#.0g"},
+ {__LINE__, 0.956, "1.", "%#.0g"},
+ {__LINE__, 0.0956, "0.1", "%#.0g"},
+ {__LINE__, 0.00956, "0.01", "%#.0g"},
+ {__LINE__, 0.000956, "0.001", "%#.0g"},
+ {__LINE__, 0.000098, "0.0001", "%#.0g"},
+ {__LINE__, 0.0000996, "0.00010", "%#.2g"},
{0 }
@@ -4023,13 +4031,8 @@ sprint_double_type sprint_doubles[] =
int required_precision = 13;
-#if defined(__STDC__) || defined(__cplusplus)
static int
matches (register char *result, register const char *desired)
-#else
-int matches(result, desired)
- register char *result; register const char *desired;
-#endif
{
int digits_seen = 0;
for (;; result++, desired++) {
@@ -4080,7 +4083,7 @@ int main(int argc, char *argv[])
/* And one special test. */
{
- const char ref[] = "1.7763568394002504646778106689453125e-15";
+ static const char ref[] = "1.7763568394002504646778106689453125e-15";
int i;
d = 1.0;
for (i = 1; i < 50; ++i)