소스 검색

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.
Rich Felker 13 년 전
부모
커밋
2e77dc13f8
4개의 변경된 파일28개의 추가작업 그리고 4개의 파일을 삭제
  1. 12 2
      src/math/fma.c
  2. 2 0
      src/math/fmaf.c
  3. 12 2
      src/math/fmal.c
  4. 2 0
      src/math/lrint.c

+ 12 - 2
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)

+ 2 - 0
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);

+ 12 - 2
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)

+ 2 - 0
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;
 }