Hello, Please consider this reduced testcase: #define _GNU_SOURCE #include <math.h> #include <stdio.h> double degreesToRadians(double degrees) { return degrees * (M_PI / 180); } double __attribute__ ((noinline)) a(double rad) { return sin(rad); } double __attribute__ ((noinline)) b(double rad) { double s; double c; sincos(rad, &s, &c); if (c > 100) return 0.0; return s; } int main() { double d = 297; double rad = degreesToRadians(d); printf("%a\n%a\n", a(rad), b(rad)); } Godbolt: https://c.godbolt.org/z/z45GGWEEK Under GCC 12.1 -O2 -fno-builtin, the output is: -0x1.c83201d3d2c6ep-1 -0x1.c83201d3d2c6dp-1 In other words, sincos seems to be introducing ~1ULP of error when compared to calling sin/cos separately. This is annoying, because GCC has a specific optimization where it replaces nearby sin/cos calls with a call to sincos (slightly modified example here: https://c.godbolt.org/z/rYEhrcPcx ). However, by doing so, it actually changes the results. As sincos is not documented to be any different from sin+cos, the optimization is correct, in principle. (If, on the other hand, sincos could generate different results than sin/cos, then GCC must stop employing such optimization without -ffast-math or similar flags).
Which specific optimized sin function are you using? With __sin_avx I cannot reproduce that. Note that sincos always uses a non-optimized sin/cos computation.
I cannot reproduce that with __sin_sse2 either.
Hello, I'm actually not sure; running gdb on the binary and stepping through instructions leads me to __sin_fma: (gdb) bt #0 __sin_fma (x=5.1836278784231586) at ../sysdeps/ieee754/dbl-64/s_sin.c:202 #1 0x00005555555550d9 in main () at test.c:30 This is on Ubuntu 20.04 on a Broadwell CPU.
As a data point, if I run the testcase under GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX2_Usable then I get identical results: -0x1.c83201d3d2c6dp-1 -0x1.c83201d3d2c6dp-1 With that environment variable, I end up into __sin_avx.
Hello, In a nutshell, there are a few things crossing each other: 1) `__sin_fma` returns slightly different results than `__sin_avx` or `__sin_sse2`. I don't think that this is a problem at all, but I might be wrong, I just lack the necessary knowledge about what glibc specifically promises here. 2) `sincos` seems to be consistent with `__sin_sse2`, and therefore inconsistent with `__sin_fma`. Is this inconsistency OK? Should it be documented? 3) In general, this opens the question: within the very same "environment" (same process, CPU, libm, fpenv, etc.), is there any guarantee that `sin(x)` always yields the very same result for identical values of `x`? Is `sin(x)` meant to be perfectly reproducible? If yes, should GCC stop turning pairs of `sin(x)` and `cos(x)` calls into one call to `sincos`?
Fixed in 2.36.
Thank you very much!