From: Piotr Caban piotr@codeweavers.com
--- libs/musl/src/math/rint.c | 63 ++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 20 deletions(-)
diff --git a/libs/musl/src/math/rint.c b/libs/musl/src/math/rint.c index ad35201b266..b9e3cbb0ec2 100644 --- a/libs/musl/src/math/rint.c +++ b/libs/musl/src/math/rint.c @@ -3,27 +3,50 @@ #include <stdint.h> #include "libm.h"
-#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 -#define EPS DBL_EPSILON -#elif FLT_EVAL_METHOD==2 -#define EPS LDBL_EPSILON -#endif -static const double_t toint = 1/EPS; +static const float_t toint = 1 / FLT_EPSILON;
double __cdecl rint(double x) { - union {double f; uint64_t i;} u = {x}; - int e = u.i>>52 & 0x7ff; - int s = u.i>>63; - double_t y; - - if (e >= 0x3ff+52) - return x; - if (s) - y = fp_barrier(x - toint) + toint; - else - y = fp_barrier(x + toint) - toint; - if (y == 0) - return s ? -0.0 : 0; - return y; + union {double f; uint64_t i;} u = {x}; + int e = (u.i >> 52 & 0x7ff) - 0x3ff; + int s = u.i>>63; + double_t y, z; + float_t f; + int even; + + if (e >= 52) + return x; + + even = e <= -1 ? 1 : !((u.i >> (52 - e)) % 2); + + if (s) + { + y = ceil(x); + z = x - y; + if (z < -0.5) f = -0.75; + else if (z == -0.5) f = -0.5; + else if (z != 0.0) f = -0.25; + else f = 0.0; + + f = (even ? -0.0 : -1.0) + f; + f = fp_barrierf(f - toint) + toint; + if (f == (even ? 0.0 : -1.0)) z = y; + else z = floor(x); + } + else + { + y = floor(x); + z = x - y; + if (z > 0.5) f = 0.75; + else if (z == 0.5) f = 0.5; + else if (z != 0.0) f = 0.25; + else f = 0.0; + + f = (even ? 0.0 : 1.0) + f; + f = fp_barrierf(f + toint) - toint; + if (f == (even ? 0.0 : 1.0)) z = y; + else z = ceil(x); + } + + return z; }