mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-05 16:10:55 +00:00
Simplified the fix in rev.1.3. Instead of using long double for
TWO52[sx] to trick gcc into correctly converting TWO52[sx]+x to double on assignment to "double w", force a correct assignment by assigning to *(double *)&w. This is cleaner and avoids the double rounding problem on machines that evaluate double expressions in double precision. It is not necessary to convert w-TWO52[sx] to double precision on return as implied in the comment in rev.1.3, since the difference is exact.
This commit is contained in:
parent
7441377544
commit
3fc5a433e9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=153043
|
@ -27,13 +27,7 @@ static char rcsid[] = "$FreeBSD$";
|
|||
#include "math.h"
|
||||
#include "math_private.h"
|
||||
|
||||
/*
|
||||
* TWO23 is long double instead of double to avoid a bug in gcc. Without
|
||||
* this, gcc thinks that TWO23[sx]+x and w-TWO23[sx] already have double
|
||||
* precision and doesn't clip them to double precision when they are
|
||||
* assigned and returned.
|
||||
*/
|
||||
static const long double
|
||||
static const double
|
||||
TWO52[2]={
|
||||
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
|
||||
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
|
||||
|
@ -88,6 +82,6 @@ rint(double x)
|
|||
if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
|
||||
}
|
||||
INSERT_WORDS(x,i0,i1);
|
||||
w = TWO52[sx]+x;
|
||||
*(volatile double *)&w = TWO52[sx]+x; /* clip any extra precision */
|
||||
return w-TWO52[sx];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue