@@ -140,7 +140,7 @@ __ieee754_gammaf_r (float x, int *signgamp)
};
double m = z - 0x1.7p+1;
- double i = roundeven (m);
+ double i = roundeven_finite (m);
double step = copysign (1.0, i);
double d = m - i, d2 = d * d, d4 = d2 * d2, d8 = d4 * d4;
double f = (c[0] + d * c[1]) + d2 * (c[2] + d * c[3])
@@ -57,6 +57,33 @@ static inline int32_t
converttoint (double_t x);
#endif
+#ifndef ROUNDEVEN_INTRINSICS
+/* When set, roundeven_finite will route to the internal roundeven function. */
+# define ROUNDEVEN_INTRINSICS 1
+#endif
+
+/* Round x to nearest integer value in floating-point format, rounding halfway
+ cases to even. If the input is non finite the result is unspecified. */
+static inline double
+roundeven_finite (double x)
+{
+ if (!isfinite (x))
+ __builtin_unreachable ();
+#if ROUNDEVEN_INTRINSICS
+ return roundeven (x);
+#else
+ double y = round (x);
+ if (fabs (x - y) == 0.5)
+ {
+ union { double f; uint64_t i; } u = {y};
+ union { double f; uint64_t i; } v = {y - copysign (1.0, x)};
+ if (__builtin_ctzll (v.i) > __builtin_ctzll (u.i))
+ y = v.f;
+ }
+ return y;
+#endif
+}
+
static inline uint32_t
asuint (float f)
{
@@ -95,7 +95,7 @@ __expm1f (float x)
return __math_oflowf (0);
}
double a = iln2 * z;
- double ia = roundeven (a);
+ double ia = roundeven_finite (a);
double h = a - ia;
double h2 = h * h;
uint64_t u = asuint64 (ia + big);
@@ -59,4 +59,9 @@ __ieee754_sqrtf128 (_Float128 __x)
#define _GL_HAS_BUILTIN_ILOGB 0
#endif
+#ifdef _ARCH_PWR6
+/* ISA 2.03 provides frin/round() and cntlzw/ctznll(). */
+# define ROUNDEVEN_INTRINSICS 0
+#endif
+
#endif /* _PPC_MATH_PRIVATE_H_ */