This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[3.3 Patch] Fix libstdc++/14220
- From: Paolo Carlini <pcarlini at suse dot de>
- To: Gabriel Dos Reis <gdr at integrable-solutions dot net>
- Cc: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Sun, 22 Feb 2004 18:41:47 +0100
- Subject: [3.3 Patch] Fix libstdc++/14220
Hi all, hi Gaby,
I'd like to apply this fix to the branch *before* mainline and 3_4,
since seems quite obvious and there we are still working on the fast
output of floats, which will change completely the affected function.
In a nutshell, without the patch this testcase outputs two different
numbers, whereas, according to 22.2.2.2.2, those should be identical
since everything must go as if printf were called:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
cout << fixed << setprecision(25) << 5.55555555e-17 << '\n';
printf("%.25f\n", 5.55555555e-17);
}
Tested x86-linux.
Ok?
Paolo.
////////////
2004-02-22 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/14220
* include/bits/locale_facets.tcc (num_put<>::_M_convert_float):
Don't clip the precision passed down to __convert_from_v:
22.2.2.2.2 nowhere says so.
diff -urN libstdc++-v3-orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
--- libstdc++-v3-orig/include/bits/locale_facets.tcc 2004-01-29 03:52:24.000000000 +0100
+++ libstdc++-v3/include/bits/locale_facets.tcc 2004-02-22 18:28:31.000000000 +0100
@@ -884,22 +884,13 @@
_M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
_ValueT __v) const
{
- // Note: digits10 is rounded down: add 1 to ensure the maximum
- // available precision. Then, in general, one more 1 needs to
- // be added since, when the %{g,G} conversion specifiers are
- // chosen inside _S_format_float, the precision field is "the
- // maximum number of significant digits", *not* the "number of
- // digits to appear after the decimal point", as happens for
- // %{e,E,f,F} (C99, 7.19.6.1,4).
- const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
-
// Use default precision if out of range.
streamsize __prec = __io.precision();
- if (__prec > static_cast<streamsize>(__max_digits))
- __prec = static_cast<streamsize>(__max_digits);
- else if (__prec < static_cast<streamsize>(0))
+ if (__prec < static_cast<streamsize>(0))
__prec = static_cast<streamsize>(6);
+ const int __max_digits = numeric_limits<_ValueT>::digits10;
+
typedef numpunct<_CharT> __facet_type;
typedef __locale_cache<numpunct<_CharT> > __cache_type;
const locale __loc = __io._M_getloc();
@@ -911,7 +902,7 @@
char __fbuf[16];
#ifdef _GLIBCPP_USE_C99
- // First try a buffer perhaps big enough (for sure sufficient
+ // First try a buffer perhaps big enough (most probably sufficient
// for non-ios_base::fixed outputs)
int __cs_size = __max_digits * 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
@@ -933,13 +924,13 @@
const bool __fixed = __io.flags() & ios_base::fixed;
const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
- // ios_base::fixed outputs may need up to __max_exp+1 chars
- // for the integer part + up to __max_digits chars for the
- // fractional part + 3 chars for sign, decimal point, '\0'. On
- // the other hand, for non-fixed outputs __max_digits*3 chars
- // are largely sufficient.
- const int __cs_size = __fixed ? __max_exp + __max_digits + 4
- : __max_digits * 3;
+ // ios_base::fixed outputs may need up to __max_exp + 1 chars
+ // for the integer part + __prec chars for the fractional part
+ // + 3 chars for sign, decimal point, '\0'. On the other hand,
+ // for non-fixed outputs __max_digits * 2 chars + __prec are
+ // largely sufficient.
+ const int __cs_size = __fixed ? __max_exp + __prec + 4
+ : __max_digits * 2 + __prec;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
_S_format_float(__io, __fbuf, __mod, __prec);