From: Rich Felker Date: Sat, 17 Mar 2012 03:58:49 +0000 (-0400) Subject: make fma and lrint functions build without full fenv support X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=commitdiff_plain;h=2e77dc13f8bc2053642fcb136996f5f36c88c775;hp=8c071f872b2844ca297275176047f8d23eec96a7 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. --- diff --git a/src/math/fma.c b/src/math/fma.c index c53f3148..f44ecda7 100644 --- a/src/math/fma.c +++ b/src/math/fma.c @@ -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) diff --git a/src/math/fmaf.c b/src/math/fmaf.c index 0dccf108..cc427fb5 100644 --- a/src/math/fmaf.c +++ b/src/math/fmaf.c @@ -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); diff --git a/src/math/fmal.c b/src/math/fmal.c index 200bd5a5..3944c292 100644 --- a/src/math/fmal.c +++ b/src/math/fmal.c @@ -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) diff --git a/src/math/lrint.c b/src/math/lrint.c index 98d58ad0..9754fa74 100644 --- a/src/math/lrint.c +++ b/src/math/lrint.c @@ -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; }