#252 double and long double printing broken

pending-fixed
nobody
crt (84)
5
2012-05-07
2011-11-11
Robert Rossi
No

I've written some examples that show that double and long double printing are broke
in all the cases I could think of. That is, __mingw_printf, printf, std::cout.

I compiled this file as C (with C++ stuff removed) and C++ with only -m32 and saw these errors.

The output is always some form of zeros, except for the case that is documented
as having output, but the precision is smaller than mingw.org.

I am using the most recent TDM version of the compiler.

Any idea if and when these issues will be fixed?

#include <iostream>
#include <iomanip>
#include <limits>
#include <stdio.h>

char buf[256];

int
main()
{
// mingw prinf isn't working for double or long double
__mingw_printf("%.21f\n", 1.17549435082228750797e-38);
__mingw_printf("%.21Lf\n", 1.17549435082228750797e-38L);

// mingw sprintf isn't working for double or long double
__mingw_sprintf(buf, "%.21f", 1.17549435082228750797e-38);
printf("%s\n", buf);
__mingw_sprintf(buf, "%.21Lf", 1.17549435082228750797e-38L);
printf("%s\n", buf);

// sprintf isn't working for double or long double
sprintf(buf, "%.21f", 1.17549435082228750797e-38);
printf("%s\n", buf);
sprintf(buf, "%.21Lf", 1.17549435082228750797e-38L);
printf("%s\n", buf);

// cout double prints 1.1754943508222875 instead of 1.17549435082228750797
std::cout << std::setprecision(21) << 1.17549435082228750797e-38 << std::endl;
// cout long double isn't working
std::cout << std::setprecision(21) << 1.17549435082228750797e-38L << std::endl;

return 0;
}

Discussion

  • Ozkan Sezer
    Ozkan Sezer
    2011-11-14

    Is the broken behavior reproducible with mingw.org ?

     
  • Ozkan Sezer
    Ozkan Sezer
    2011-11-17

    Hmm, just tested using a mingw.org toolchain, and the brokenness is there too:

    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    -0.000000000000000000000
    1.17549435082228750797e-038
    1.17549435082228750797e-038

    With our own 32 bit toolchain (specifically sezero_4.5_20111101 plus today's
    v1.x crt+headers rev. 4620), I get:

    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    -0.000000000000000000000
    1.1754943508222875e-038
    -0

    So yes:
    1. I see the minor precision loss std::cout + double
    2. Interestingly std::cout + ldouble seems to work with mingw but not with us
    3. sprintf() is already not supposed to work with ldouble
    4. Neither mingw.org nor us work with __mingw_[s]printf() + double or ldouble

    Kai? Jon?

     
  • Robert Rossi
    Robert Rossi
    2011-11-22

    The cases you found,
    1. I see the minor precision loss std::cout + double
    2. Interestingly std::cout + ldouble seems to work with mingw but not with us
    are the cases that blocked my application from working.

    They work with mingw.org with gcc 4.4.1 TDM.
    They do not work with mingw w64.

    I tried to use different examples like sprintf to demonstrate the issues. But 1. and 2. is what I really
    care about.

     
  • Ozkan Sezer
    Ozkan Sezer
    2011-11-22

    Just tested your src with linux (x86):
    (s)printf outputs:
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    std::cout outputs:
    1.17549435082228750797e-38
    1.17549435082228750797e-38

    Then looked at it carefully and noticed that you are using %f, which is wrong: you need %e instead: see printf man page. With that change I get:
    1.175494350822287507969e-38
    1.175494350822287507969e-38
    1.175494350822287507969e-38
    1.175494350822287507969e-38
    1.17549435082228750797e-38
    1.17549435082228750797e-38

    Can't test windows at the moment, so please try.

     
  • Robert Rossi
    Robert Rossi
    2011-11-23

    This bug report was cast a little to wide. The two issues that I noticed different between mingw.org and mingw w64 is this:
    1. I see the minor precision loss std::cout + double
    2. Interestingly std::cout + ldouble seems to work with mingw but not with mingw w64
    Both of those are using the C++ iostream << operator. So they don't involve the format specifiers.

    Perhaps we should treat that as one case, since it's a regression from mingw.org.

    Then we could track other printing issues in a separate ticket. What do you think?

     
  • Kai Tietz
    Kai Tietz
    2011-12-13

    Hmm, I thought this issue is fixed with our trunk version. All those changes to _mingw_printf & co were about this. Are those changes backported to 2.x branch?

    Kai

     
  • Ozkan Sezer
    Ozkan Sezer
    2011-12-13

    Yes, to v2.x and to v1.x as well. (I do hope that a recompile of libstdc++ is not necesary, because I remember that I reproduced Robert's issue by using old libstdc++ plus updated crt/headers.)

     
  • Kai Tietz
    Kai Tietz
    2011-12-13

    well, I assume for libstdc++ in shared version a rebuild of it is required. For static header-update should be enough.

     
  • Ozkan Sezer
    Ozkan Sezer
    2011-12-13

    I see. Can't remember what version I tested with. Were you able to reproduce his issues?

     
  • Kai Tietz
    Kai Tietz
    2011-12-13

    Well, I see proper value by using %g instead of %f. So I need to look into code what actually happens here for %f.
    But yes, I can reproduce it.

     
  • Kai Tietz
    Kai Tietz
    2011-12-14

    Well, I found the cause that it resists to use here our POSIX vsnprintf. Instead it uses that one from libmiingwex.a which is indeed bad here.
    I need to take a closer look why it uses that one instead.

     
  • Kai Tietz
    Kai Tietz
    2011-12-14

    So the rest of the issue is caused by libstdc++ itself. The failure is in generic/locale, which uses here __builtin_vsnprintf, which of course isn't overriden by stdio.h. Even if we would do so (as now by latest patch on trunk is done) it won't help, as it doesn't includes <cstdio> before ...

    So if somebody could open a bug for it on gcc, that would be good. And I am sure it is an issue, which happens for mingw.org stuff too.

    Kai

     
  • Kai Tietz
    Kai Tietz
    2011-12-16

    • status: open --> pending-fixed
     
  • Kai Tietz
    Kai Tietz
    2011-12-16

    Should be fixed with trunk runtime. Verification is missing. Therefore I set it to pending.

     
  • Robert Rossi
    Robert Rossi
    2012-04-20

    • status: pending-fixed --> open-fixed
     
  • Robert Rossi
    Robert Rossi
    2012-04-20

    This is fixed in gcc 4.7. Thanks!

     
  • Kai Tietz
    Kai Tietz
    2012-05-07

    • status: open-fixed --> pending-fixed
     
  • Kai Tietz
    Kai Tietz
    2012-05-07

    The issue is caused by the not-backported fix of print/scanf routine adjustments on trunk to older branches.

    By using our trunk version I get for this example (with f)

    $ x86_64-w64-mingw32-g++.exe -o tst t_pri.C -O2

    ktietz@neptun ~/test/g++
    $ ./tst.exe
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    0.000000000000000000000
    1.17549435082228750797e-038
    1.17549435082228750797e-038

    what is absolutely correct, as 'f' implies here a rounding. The c++ code doesn't use 'f'. It use 'e', which provides proper result.

    By using proper 'e' formatter here we get:
    $ ./tst.exe
    1.175494350822287507969e-038
    1.175494350822287507969e-038
    1.175494350822287507969e-038
    1.175494350822287507969e-038
    1.175494350822287507969e-038
    1.175494350822287507969e-038
    1.17549435082228750797e-038
    1.17549435082228750797e-038

    So I close this bug as pending.

     
  • Ozkan Sezer
    Ozkan Sezer
    2012-05-07

    I am willing to merge printf/scanf fixes from trunk to stable branches however, IIRC, they were scattered among many commits on the trunk: so, if anyone can point me to correct commits I can do it, or if anyone else is up to it please do so as I am OK with that too.