Summary: | sys-libs/glibc x86 cos(PI/2) off by a bit (sci-calculators/pcalc fails tests) | ||
---|---|---|---|
Product: | Gentoo Linux | Reporter: | Diego Elio Pettenò (RETIRED) <flameeyes> |
Component: | New packages | Assignee: | Gentoo Toolchain Maintainers <toolchain> |
Status: | RESOLVED WORKSFORME | ||
Severity: | normal | CC: | erhard_f |
Priority: | High | ||
Version: | unspecified | ||
Hardware: | All | ||
OS: | Linux | ||
Whiteboard: | |||
Package list: | Runtime testing required: | --- | |
Attachments: | Build log |
Description
Diego Elio Pettenò (RETIRED)
![]() Created attachment 196931 [details]
Build log
bug in glibc. its 32bit double math isnt as good as the 64bit version. $ cat test.c #include <math.h> #include <stdio.h> #define PI 3.14159265358979323846 main() { double x = PI / 2; printf("%-16.16g\n", cos(x)); } $ gcc test.c -lm -o 32 -m32 $ gcc test.c -lm -o 64 $ ./32; ./64 6.123031769111886e-17 6.123233995736766e-17 (In reply to comment #2) > bug in glibc. its 32bit double math isnt as good as the 64bit version. > > $ cat test.c > #include <math.h> > #include <stdio.h> > #define PI 3.14159265358979323846 > main() { double x = PI / 2; printf("%-16.16g\n", cos(x)); } > > $ gcc test.c -lm -o 32 -m32 > $ gcc test.c -lm -o 64 > $ ./32; ./64 > 6.123031769111886e-17 > 6.123233995736766e-17 (For reference, I get the same results.) Disassembling the output shows that the 32-bit version uses the FPU, and the 64-bit version uses the SSE registers. Compiling with -mfpmath=sse on 32-bit doesn't cause different results though ./testpi-32: 6.123031769111886e-17 ./testpi-32-sse: 6.123031769111886e-17 ./testpi-64: 6.123233995736766e-17 FYI, the program on alpha returns 6.123233995736766e-17 as well. Now, there's a define in math.h, M_PI_2. It seems that if and only if you call cos(M_PI_2) (ie, not "double x = M_PI_2; cos(x)") the 32-bit versions (SSE and FPU) give better correct results. #include <math.h> #include <stdio.h> main() { printf("%-16.16g\n", cos(x)); } Now, let's all realize that _all_ of these answers are wrong. cos(pi/2) is 0. So while the discrepancy between the 32/64-bit versions is strange, I cannot imagine any software depends on cos(PI/2) returning a result more accurate than either of the results we've seen. By my math, the 32-bit value only differs by 0.0033%. So, is there really a bug here to fix? i'm not sure your cos(M_PI_2) test is doing what you think it is ... are you sure gcc didnt optimize it away using its much more accurate mpfr/gmp library ? (In reply to comment #4) > i'm not sure your cos(M_PI_2) test is doing what you think it is ... are you > sure gcc didnt optimize it away using its much more accurate mpfr/gmp library ? Yes, after looking at objdump, in fact it is optimizing the cos call completely out. Unfortunate that it can't detect that cos(M_PI_2) can be represented a bit better and more precisely than 6.123233995736766e-17. so the latest glibc-2.21 has gotten much better: $ ./32; ./64 6.123233995736766e-17 6.123233995736766e-17 if it comes up again, i might re-evaluate the test. i understand a bit more that libm is hard to get "right", especially when there is no actual definition of "right" in the floating point world. i might have to truncate the test output down to a few significant digits. but i'm lazy and it's easier to punt ;). *** Bug 794985 has been marked as a duplicate of this bug. *** |