Bug 34473 - casting negative __int128_t to float/double rounds to nearest multiple of 2048
Summary: casting negative __int128_t to float/double rounds to nearest multiple of 2048
Status: RESOLVED DUPLICATE of bug 25028
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.1.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-12-14 23:20 UTC by James Hogan
Modified: 2007-12-16 23:27 UTC (History)
5 users (show)

See Also:
Host: x86_64-redhat-linux
Target: x86_64-redhat-linux
Build: x86_64-redhat-linux
Known to work: 4.3.0
Known to fail:
Last reconfirmed:


Attachments
Very simple failure test case (77 bytes, text/plain)
2007-12-14 23:27 UTC, James Hogan
Details

Note You need to log in before you can comment on or make changes to this bug.
Description James Hogan 2007-12-14 23:20:51 UTC
casting a negative _int128_t value to a float or double rounds the resulting floating point number to the nearest multiple of 2048.

the following C program demonstrates which I compiled with the compile string "gcc":

int main()
{
	__int128_t x = -1025;
	double f = x;
	return f < -1500.0;
}

I would expect the exit code of the program to be 0. f should get set to -1025.0, which is not < -1500.0.

However when I compile and run this the exit code is 1.

Further examination shows that f gets the following values:
    0.0 for x in the range -1024 to 0
-2048.0 for x in the range -3060 to -1025
    ...etc...

When x is positive f gets set to the expected (the same) value.

"gcc -v" output:

Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
Comment 1 James Hogan 2007-12-14 23:27:18 UTC
Created attachment 14758 [details]
Very simple failure test case

exit code is 0 for pass, 1 for fail
compiled with compile line "gcc"
Comment 2 James Hogan 2007-12-14 23:30:43 UTC
Oh and i forgot to mention: casting negative __int128_t to "long double" instead of "float" or "double" compiles correctly.
Comment 3 Uroš Bizjak 2007-12-16 16:02:09 UTC
From libgcc2.c, __floatdisf():

  /* Protect against double-rounding error.
     Represent any low-order bits, that might be truncated by a bit that
     won't be lost.  The bit can go in anywhere below the rounding position
     of the SFmode.  A fixed mask and bit position handles all usual
     configurations.  It doesn't handle the case of 128-bit DImode, however.  */

Please note that "di" in fact represents TImode for 64bit x86_64. I guess that __floatdidf() also can't handle 128bit DImode values properly.

This works OK for 4.3.0, beacuse 4.3 branch implements 128bit TFmode floating point mode and _floatdi{s,d}f function is changed to use this mode.
Comment 4 jsm-csl@polyomino.org.uk 2007-12-16 16:44:27 UTC
Subject: Re:  casting negative __int128_t to float/double
 rounds to nearest multiple of 2048

On Sun, 16 Dec 2007, ubizjak at gmail dot com wrote:

> This works OK for 4.3.0, beacuse 4.3 branch implements 128bit TFmode floating
> point mode and _floatdi{s,d}f function is changed to use this mode.

I think the fix was actually

2005-12-15  Joseph S. Myers  <joseph@codesourcery.com>

        PR other/25028
        * libgcc2.h (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Define.
        * libgcc2.c (__floatdixf, __floatundixf, __floatditf,
        __floatunditf): Use #error if type sizes don't match requirements
        of implementation.
        (__floatdisf, __floatdidf): Unify.  Possibly use XFmode or TFmode
        as wider floating-point type.  Use #error if type sizes don't
        match requirements of implementation.  Avoid overflow in computing
        Wtype_MAXp1_F * Wtype_MAXp1_F.  When special casing conversion,
        shift one more bit.  Cast 1 to DWtype or UDWtype for shifting.
        (__floatundisf, __floatundidf): Likewise.
        * config/ia64/hpux.h (XF_SIZE, TF_SIZE): Define.
        * config/ia64/ia64.c (ia64_init_libfuncs): Use
        _U_Qfcnvfxt_quad_to_quad and _U_Qfcnvxf_quad_to_quad for
        TFmode-TImode conversions.
        * doc/tm.texi (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Document.

(which is in 4.2) and that this is a duplicate of that bug.  If software 
TFmode is being used internally in conversions for narrower modes, that's 
a bug caused by x86_64 not defining WIDEST_HARDWARE_FP_SIZE.

Comment 5 Uroš Bizjak 2007-12-16 23:27:15 UTC
Reopened ...
Comment 6 Uroš Bizjak 2007-12-16 23:27:53 UTC
... to close as duplicate of PR 25028.

*** This bug has been marked as a duplicate of 25028 ***