提交 2e77dc13 编写于 作者: R Rich Felker

make fma and lrint functions build without full fenv support

this is necessary to support archs where fenv is incomplete or
unavailable (presently arm). fma, fmal, and the lrint family should
work perfectly fine with this change; fmaf is slightly broken with
respect to rounding as it depends on non-default rounding modes to do
its work.
上级 8c071f87
......@@ -199,27 +199,37 @@ double fma(double x, double y, double z)
* modes other than FE_TONEAREST are painful.
*/
if (spread < -DBL_MANT_DIG) {
#ifdef FE_INEXACT
feraiseexcept(FE_INEXACT);
#endif
#ifdef FE_UNDERFLOW
if (!isnormal(z))
feraiseexcept(FE_UNDERFLOW);
#endif
switch (oround) {
case FE_TONEAREST:
default: /* FE_TONEAREST */
return (z);
#ifdef FE_TOWARDZERO
case FE_TOWARDZERO:
if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
return (z);
else
return (nextafter(z, 0));
#endif
#ifdef FE_DOWNWARD
case FE_DOWNWARD:
if (x > 0.0 ^ y < 0.0)
return (z);
else
return (nextafter(z, -INFINITY));
default: /* FE_UPWARD */
#endif
#ifdef FE_UPWARD
case FE_UPWARD:
if (x > 0.0 ^ y < 0.0)
return (nextafter(z, INFINITY));
else
return (z);
#endif
}
}
if (spread <= DBL_MANT_DIG * 2)
......
......@@ -54,7 +54,9 @@ float fmaf(float x, float y, float z)
* If result is inexact, and exactly halfway between two float values,
* we need to adjust the low-order bit in the direction of the error.
*/
#ifdef FE_TOWARDZERO
fesetround(FE_TOWARDZERO);
#endif
volatile double vxy = xy; /* XXX work around gcc CSE bug */
double adjusted_result = vxy + z;
fesetround(FE_TONEAREST);
......
......@@ -194,27 +194,37 @@ long double fmal(long double x, long double y, long double z)
* modes other than FE_TONEAREST are painful.
*/
if (spread < -LDBL_MANT_DIG) {
#ifdef FE_INEXACT
feraiseexcept(FE_INEXACT);
#endif
#ifdef FE_UNDERFLOW
if (!isnormal(z))
feraiseexcept(FE_UNDERFLOW);
#endif
switch (oround) {
case FE_TONEAREST:
default: /* FE_TONEAREST */
return (z);
#ifdef FE_TOWARDZERO
case FE_TOWARDZERO:
if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
return (z);
else
return (nextafterl(z, 0));
#endif
#ifdef FE_DOWNWARD
case FE_DOWNWARD:
if (x > 0.0 ^ y < 0.0)
return (z);
else
return (nextafterl(z, -INFINITY));
default: /* FE_UPWARD */
#endif
#ifdef FE_UPWARD
case FE_UPWARD:
if (x > 0.0 ^ y < 0.0)
return (nextafterl(z, INFINITY));
else
return (z);
#endif
}
}
if (spread <= LDBL_MANT_DIG * 2)
......
......@@ -49,8 +49,10 @@ dtype fn(type x)
feholdexcept(&env);
d = (dtype)roundit(x);
#if defined(FE_INVALID) && defined(FE_INEXACT)
if (fetestexcept(FE_INVALID))
feclearexcept(FE_INEXACT);
#endif
feupdateenv(&env);
return d;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册