From 6b6b4dd0d75b9cd8fd4deebd4046aae2f1fafb10 Mon Sep 17 00:00:00 2001 From: John Marino Date: Sat, 14 Nov 2015 18:12:05 +0100 Subject: [PATCH] Restore buildworld from clang (adjust libm) Functions like "isinff" come from GCC only, causes a missed reference when the world is built with clang. To solve, bring back FreeBSD versions of round(|f|l). An additional benefit is that these functions appear to be improved over the OpenBSD versions (avoids unnecessary conversions). The FreeBSD roundl uses ENTERI/RETURNI macros so I left these off meaning DF will still not able to raise exceptions on roundl. Since isinff and friends are no longer used, clang can continue further with building the world. --- contrib/openbsd_libm/src/s_round.c | 12 +++++++----- contrib/openbsd_libm/src/s_roundf.c | 16 +++++++++------- contrib/openbsd_libm/src/s_roundl.c | 18 +++++++++++------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/contrib/openbsd_libm/src/s_round.c b/contrib/openbsd_libm/src/s_round.c index ce7eb925bd..bd1d73cc13 100644 --- a/contrib/openbsd_libm/src/s_round.c +++ b/contrib/openbsd_libm/src/s_round.c @@ -35,19 +35,21 @@ double round(double x) { double t; + uint32_t hx; - if (isinf(x) || isnan(x)) - return (x); + GET_HIGH_WORD(hx, x); + if ((hx & 0x7fffffff) == 0x7ff00000) + return (x + x); - if (x >= 0.0) { + if (!(hx & 0x80000000)) { t = floor(x); if (t - x <= -0.5) - t += 1.0; + t += 1; return (t); } else { t = floor(-x); if (t + x <= -0.5) - t += 1.0; + t += 1; return (-t); } } diff --git a/contrib/openbsd_libm/src/s_roundf.c b/contrib/openbsd_libm/src/s_roundf.c index f56d218787..d6527ec4a5 100644 --- a/contrib/openbsd_libm/src/s_roundf.c +++ b/contrib/openbsd_libm/src/s_roundf.c @@ -33,19 +33,21 @@ float roundf(float x) { float t; + uint32_t hx; - if (isinff(x) || isnanf(x)) - return (x); + GET_FLOAT_WORD(hx, x); + if ((hx & 0x7fffffff) == 0x7f800000) + return (x + x); - if (x >= 0.0) { + if (!(hx & 0x80000000)) { t = floorf(x); - if (t - x <= -0.5) - t += 1.0; + if (t - x <= -0.5F) + t += 1; return (t); } else { t = floorf(-x); - if (t + x <= -0.5) - t += 1.0; + if (t + x <= -0.5F) + t += 1; return (-t); } } diff --git a/contrib/openbsd_libm/src/s_roundl.c b/contrib/openbsd_libm/src/s_roundl.c index b893f3193c..481a14bd23 100644 --- a/contrib/openbsd_libm/src/s_roundl.c +++ b/contrib/openbsd_libm/src/s_roundl.c @@ -27,24 +27,28 @@ */ #include +#include "math_private.h" long double roundl(long double x) { long double t; + uint16_t hx; - if (!isfinite(x)) - return (x); + GET_LDOUBLE_EXP(hx, x); + if ((hx & 0x7fff) == 0x7fff) + return (x + x); - if (x >= 0.0) { + + if (!(hx & 0x8000)) { t = floorl(x); - if (t - x <= -0.5) - t += 1.0; + if (t - x <= -0.5L) + t += 1; return (t); } else { t = floorl(-x); - if (t + x <= -0.5) - t += 1.0; + if (t + x <= -0.5L) + t += 1; return (-t); } } -- 2.41.0