Fix a regression introduced in r226371: When the high part of x*y
exactly cancels with z, return the low part of x*y instead of discarding it.
This commit is contained in:
parent
bc23acdc32
commit
0c7e4d5fc1
@ -250,6 +250,8 @@ fma(double x, double y, double z)
|
||||
xy = dd_mul(xs, ys);
|
||||
r = dd_add(xy.hi, zs);
|
||||
|
||||
spread = ex + ey;
|
||||
|
||||
if (r.hi == 0.0) {
|
||||
/*
|
||||
* When the addends cancel to 0, ensure that the result has
|
||||
@ -257,11 +259,9 @@ fma(double x, double y, double z)
|
||||
*/
|
||||
fesetround(oround);
|
||||
volatile double vzs = zs; /* XXX gcc CSE bug workaround */
|
||||
return (xy.hi + vzs);
|
||||
return (xy.hi + vzs + ldexp(xy.lo, spread));
|
||||
}
|
||||
|
||||
spread = ex + ey;
|
||||
|
||||
if (oround != FE_TONEAREST) {
|
||||
/*
|
||||
* There is no need to worry about double rounding in directed
|
||||
|
@ -238,6 +238,8 @@ fmal(long double x, long double y, long double z)
|
||||
xy = dd_mul(xs, ys);
|
||||
r = dd_add(xy.hi, zs);
|
||||
|
||||
spread = ex + ey;
|
||||
|
||||
if (r.hi == 0.0) {
|
||||
/*
|
||||
* When the addends cancel to 0, ensure that the result has
|
||||
@ -245,11 +247,9 @@ fmal(long double x, long double y, long double z)
|
||||
*/
|
||||
fesetround(oround);
|
||||
volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
|
||||
return (xy.hi + vzs);
|
||||
return (xy.hi + vzs + ldexpl(xy.lo, spread));
|
||||
}
|
||||
|
||||
spread = ex + ey;
|
||||
|
||||
if (oround != FE_TONEAREST) {
|
||||
/*
|
||||
* There is no need to worry about double rounding in directed
|
||||
|
Loading…
x
Reference in New Issue
Block a user