make fma and lrint functions build without full fenv support
authorRich Felker <dalias@aerifal.cx>
Sat, 17 Mar 2012 03:58:49 +0000 (23:58 -0400)
committerRich Felker <dalias@aerifal.cx>
Sat, 17 Mar 2012 03:58:49 +0000 (23:58 -0400)
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.

src/math/fma.c
src/math/fmaf.c
src/math/fmal.c
src/math/lrint.c

index c53f3148bd83733fc2829be18f56c6563e12b851..f44ecda77a689b375ff184266ad199126d816d70 100644 (file)
@@ -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)
index 0dccf108471875e048b210e31408ef9525a23744..cc427fb5ac987b15cad113d02183145f7e3c1c68 100644 (file)
@@ -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);
index 200bd5a55ea06e8b655e06dc9ddc383a94df7348..3944c29298e108c861d1c0f6aee9a7fe6264ebdc 100644 (file)
@@ -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)
index 98d58ad06f9f7d6ec502792cf594c9096a6bc723..9754fa749f7cc5e13a67e2e0f28e2fe2cc6c6e44 100644 (file)
@@ -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;
 }