]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
Fixed cosf(x) when x is a "negative" NaNs. I broke this in rev.1.10.
authorbde <bde@FreeBSD.org>
Wed, 30 Nov 2005 06:47:18 +0000 (06:47 +0000)
committerbde <bde@FreeBSD.org>
Wed, 30 Nov 2005 06:47:18 +0000 (06:47 +0000)
commit6142ede46fe62dfc695679f3ca3adb48bfc415b2
tree5f7f59aeb72c0c1eeeea034021a19022694e4795
parent5d50adf57dd3eb3f8996480fa4dd26e4756e268e
Fixed cosf(x) when x is a "negative" NaNs.  I broke this in rev.1.10.
cosf(x) is supposed to return something like x when x is a NaN, and
we actually fairly consistently return x-x which is normally very like
x (on i386 and and it is x if x is a quiet NaN and x with the quiet bit
set if x is a signaling NaN.  Rev.1.10 broke this by normalising x to
fabsf(x).  It's not clear if fabsf(x) is should preserve x if x is a NaN,
but it actually clears the sign bit, and other parts of the code depended
on this.

The bugs can be fixed by saving x before normalizing it, and using the
saved x only for NaNs, and using uint32_t instead of int32_t for ix
so that negative NaNs are not misclassified even if fabsf() doesn't
clear their sign bit, but gcc pessimizes the saving very well, especially
on Athlon XPs (it generates extra loads and stores, and mixes use of
the SSE and i387, and this somehow messes up pipelines).  Normalizing
x is not a very good optimization anyway, so stop doing it.  (It adds
latency to the FPU pipelines, but in previous versions it helped except
for |x| <= 3pi/4 by simplifying the integer pipelines.)  Use the same
organization as in s_sinf.c and s_tanf.c with some branches reordered.
These changes combined recover most of the performance of the unfixed
version on A64 but still lose 10% on AXP with gcc-3.4 -O1 but not with
gcc-3.3 -O1.
lib/msun/src/s_cosf.c