public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* Re: libstdc++/5875: operator<<(double) doesn't allow printing full precision (3.0 regression)
@ 2002-03-11 12:16 paolo
  0 siblings, 0 replies; 4+ messages in thread
From: paolo @ 2002-03-11 12:16 UTC (permalink / raw)
  To: gcc-bugs, gcc-prs, paolo, snyder

Synopsis: operator<<(double) doesn't allow printing full precision (3.0 regression)

State-Changed-From-To: analyzed->closed
State-Changed-By: paolo
State-Changed-When: Mon Mar 11 12:16:33 2002
State-Changed-Why:
    Patch applied head and 3_1-branch. Thanks!
    Paolo.

http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=5875


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: libstdc++/5875: operator<<(double) doesn't allow printing full precision (3.0 regression)
@ 2002-03-08 12:16 Scott Snyder
  0 siblings, 0 replies; 4+ messages in thread
From: Scott Snyder @ 2002-03-08 12:16 UTC (permalink / raw)
  To: paolo; +Cc: gcc-prs

The following reply was made to PR libstdc++/5875; it has been noted by GNATS.

From: Scott Snyder <snyder@fnal.gov>
To: paolo@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
        gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: libstdc++/5875: operator<<(double) doesn't allow printing full precision (3.0 regression)
Date: 08 Mar 2002 14:09:01 -0600

 >    I think your analysis is correct (as it was the first time,
 >    by the way ;-) and I would suggest posting directly the
 >    patch in the libstdc++ list. However, if you want to
 >    provide a testcase, you should do this as a patch against
 >    the concerned testsuite file, in the standard form based on
 >    the use of VERIFY, portable (this is the tricky point)
 >    across archs characterized by different machine precisions.
 >    I mean, do you think it would be safe testing:
 >    VERIFY(d - pi == 0.0) ??
 >    I don't think so. What do you suggest then?
 
 
 Oops --- i see i forgot to include the testsuite patch.  Here's the full
 patch again.  I tried to ensure that they were equal to within a relative
 error of DBL_EPSILON --- it may be that that's a little bit too small though.
 I admit that as of this point, i've only tested it on linux/i86.
 
 sss
 
 
 2002-03-06  scott snyder  <snyder@fnal.gov>
 
 	* include/bits/locale_facets.tcc (num_put::_M_convert_float):
 	Allow one more digit of precision.
 	* testsuite/27_io/ostream_inserter_arith.cc: Test that we can
 	write a double and read back in the same value.
 
 Index: include/bits/locale_facets.tcc
 ===================================================================
 RCS file: /cvs/gcc/egcs/libstdc++-v3/include/bits/locale_facets.tcc,v
 retrieving revision 1.63.2.3
 diff -u -p -c -r1.63.2.3 locale_facets.tcc
 *** locale_facets.tcc	2002/03/05 19:05:05	1.63.2.3
 --- locale_facets.tcc	2002/03/08 19:52:00
 *************** namespace std
 *** 610,616 ****
         _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
   		       _ValueT __v) const
         {
 ! 	const int __max_digits = numeric_limits<_ValueT>::digits10;
   	streamsize __prec = __io.precision();
   	// Protect against sprintf() buffer overflows.
   	if (__prec > static_cast<streamsize>(__max_digits))
 --- 610,618 ----
         _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
   		       _ValueT __v) const
         {
 !         // Note: digits10 is rounded down.  We need to add 1 to ensure
 !         // we get the full available precision.
 ! 	const int __max_digits = numeric_limits<_ValueT>::digits10 + 1;
   	streamsize __prec = __io.precision();
   	// Protect against sprintf() buffer overflows.
   	if (__prec > static_cast<streamsize>(__max_digits))
 Index: testsuite/27_io/ostream_inserter_arith.cc
 ===================================================================
 RCS file: /cvs/gcc/egcs/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc,v
 retrieving revision 1.15
 diff -u -p -c -r1.15 ostream_inserter_arith.cc
 *** ostream_inserter_arith.cc	2002/01/31 00:03:31	1.15
 --- ostream_inserter_arith.cc	2002/03/08 19:51:23
 ***************
 *** 20,25 ****
 --- 20,27 ----
   // USA.
   
   #include <cstdio> // for sprintf
 + #include <cmath>  // for abs
 + #include <cfloat> // for DBL_EPSILON
   #include <iostream>
   #include <iomanip>
   #include <locale>
 *************** test04()
 *** 355,360 ****
 --- 357,377 ----
     return 0;
   }
   
 + int
 + test05()
 + {
 +   double pi = 3.14159265358979323846;
 +   ostringstream ostr;
 +   ostr.precision(20);
 +   ostr << pi;
 +   string sval = ostr.str();
 +   istringstream istr (sval);
 +   double d;
 +   istr >> d;
 +   VERIFY (abs(pi-d)/pi < DBL_EPSILON);
 +   return 0;
 + }
 + 
   int 
   main()
   {
 *************** main()
 *** 362,367 ****
 --- 379,385 ----
     test02();
     test03();
     test04();
 +   test05();
   #ifdef TEST_NUMPUT_VERBOSE
     cout << "Test passed!" << endl;
   #endif


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: libstdc++/5875: operator<<(double) doesn't allow printing full precision (3.0 regression)
@ 2002-03-07 16:38 paolo
  0 siblings, 0 replies; 4+ messages in thread
From: paolo @ 2002-03-07 16:38 UTC (permalink / raw)
  To: gcc-bugs, gcc-prs, nobody, paolo, snyder

Synopsis: operator<<(double) doesn't allow printing full precision (3.0 regression)

Responsible-Changed-From-To: unassigned->paolo
Responsible-Changed-By: paolo
Responsible-Changed-When: Thu Mar  7 16:38:24 2002
Responsible-Changed-Why:
    Triaged.
State-Changed-From-To: open->analyzed
State-Changed-By: paolo
State-Changed-When: Thu Mar  7 16:38:24 2002
State-Changed-Why:
    Hi!
    I think your analysis is correct (as it was the first time,
    by the way ;-) and I would suggest posting directly the
    patch in the libstdc++ list. However, if you want to
    provide a testcase, you should do this as a patch against
    the concerned testsuite file, in the standard form based on
    the use of VERIFY, portable (this is the tricky point)
    across archs characterized by different machine precisions.
    I mean, do you think it would be safe testing:
    VERIFY(d - pi == 0.0) ??
    I don't think so. What do you suggest then?
    Ciao, Paolo.

http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=5875


^ permalink raw reply	[flat|nested] 4+ messages in thread

* libstdc++/5875: operator<<(double) doesn't allow printing full precision (3.0 regression)
@ 2002-03-07 13:26 snyder
  0 siblings, 0 replies; 4+ messages in thread
From: snyder @ 2002-03-07 13:26 UTC (permalink / raw)
  To: gcc-gnats


>Number:         5875
>Category:       libstdc++
>Synopsis:       operator<<(double) doesn't allow printing full precision (3.0 regression)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 07 13:26:02 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     scott snyder
>Release:        3.1 20020303 (prerelease)
>Organization:
>Environment:
System: Linux karma 2.4.9-13 #1 Tue Oct 30 20:11:04 EST 2001 i686 unknown
Architecture: i686

	
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: ../egcs/configure --prefix=/usr/local/egcs --enable-threads=posix --enable-long-long --enable-languages=c,c++,f77 : (reconfigured) 
>Description:

We have code that expects, after suitably widening the precision,
to be able to write out a double to a stream using operator<<,
then read it back using operator>> and get the same value to within
a relative error of DBL_EPSILON.  This used to be the case with gcc 3.0,
but is no longer true with gcc 3.1.

A little test program is below.
When i build this (on linux/ia86) with gcc 3.0.2, it prints `0'.
But when i build this with the gcc 3.1 branch, it prints `-3.10862e-15'.
So this is a relative error of about 1e-15, which is about 5 times
larger than DBL_EPSILON.

This comes about because the precision that the user specifies is clamped
to a maximum of numeric_limits<T>::digits10.  However, this is the floor
of the `true' fractional value --- limiting yourself to that many digits
can lose a couple bits off the end.

Several years ago, i submitted a patch to increase this limit by a couple
to avoid this problem:

2000-03-29  scott snyder  <snyder@fnal.gov>

        * bits/locale_facets.tcc (do_put): Allow a couple extra digits of
        precision beyond that which we get from numeric_limits::digits10.

However, it looks like when the locale code was revised between 3.0 and 3.1,
this change got lost.

Below is a patch to fix this (along with an addition to the testsuite,
so that it doesn't get lost again).


>How-To-Repeat:

-- x.cc ------------------------------------------------------------------
#include <sstream>
#include <iostream>
#include <string>

int main ()
{
  double pi = 3.14159265358979323846;
  std::ostringstream ostr;
  ostr.precision(20);
  ostr << pi;
  std::string sval = ostr.str();
  std::istringstream istr (sval);
  double d;
  istr >> d;
  std::cout << d - pi << "\n";
  return 0;
}
--------------------------------------------------------------------------

>Fix:


2002-03-06  scott snyder  <snyder@fnal.gov>

	* include/bits/locale_facets.tcc (num_put::_M_convert_float):
	Allow one more digit of precision.
	* testsuite/27_io/ostream_inserter_arith.cc: Test that we can
	write a double and read back in the same value.

Index: include/bits/locale_facets.tcc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.63.2.3
diff -u -p -r1.63.2.3 locale_facets.tcc
--- locale_facets.tcc	2002/03/05 19:05:05	1.63.2.3
+++ locale_facets.tcc	2002/03/07 19:43:29
@@ -610,7 +610,9 @@ namespace std
       _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
 		       _ValueT __v) const
       {
-	const int __max_digits = numeric_limits<_ValueT>::digits10;
+        // Note: digits10 is rounded down.  We need to add 1 to ensure
+        // we get the full available precision.
+	const int __max_digits = numeric_limits<_ValueT>::digits10 + 1;
 	streamsize __prec = __io.precision();
 	// Protect against sprintf() buffer overflows.
 	if (__prec > static_cast<streamsize>(__max_digits))

>Release-Note:
>Audit-Trail:
>Unformatted:


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-03-11 20:16 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-03-11 12:16 libstdc++/5875: operator<<(double) doesn't allow printing full precision (3.0 regression) paolo
  -- strict thread matches above, loose matches on Subject: below --
2002-03-08 12:16 Scott Snyder
2002-03-07 16:38 paolo
2002-03-07 13:26 snyder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).