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)
Created attachment 14758 [details] Very simple failure test case exit code is 0 for pass, 1 for fail compiled with compile line "gcc"
Oh and i forgot to mention: casting negative __int128_t to "long double" instead of "float" or "double" compiles correctly.
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.
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.
Reopened ...
... to close as duplicate of PR 25028. *** This bug has been marked as a duplicate of 25028 ***