Module: wine Branch: master Commit: bc5f28888ce57514dc7a7b4eec316d3327bcbb51 URL: https://source.winehq.org/git/wine.git/?a=commit;h=bc5f28888ce57514dc7a7b4ee...
Author: Piotr Caban piotr@codeweavers.com Date: Tue May 18 19:08:28 2021 +0200
msvcrt: Import fmodf implementation from musl.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msvcrt/math.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++----- dlls/msvcrt/unixlib.c | 9 ------- dlls/msvcrt/unixlib.h | 1 - 3 files changed, 64 insertions(+), 16 deletions(-)
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index d71a7108b5d..de0db9cca50 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -620,12 +620,70 @@ float CDECL expf( float x )
/********************************************************************* * fmodf (MSVCRT.@) + * + * Copied from musl: src/math/fmodf.c */ float CDECL fmodf( float x, float y ) { - float ret = unix_funcs->fmodf( x, y ); - if (!isfinite(x) || !isfinite(y)) return math_error(_DOMAIN, "fmodf", x, 0, ret); - return ret; + UINT32 xi = *(UINT32*)&x; + UINT32 yi = *(UINT32*)&y; + int ex = xi>>23 & 0xff; + int ey = yi>>23 & 0xff; + UINT32 sx = xi & 0x80000000; + UINT32 i; + + if (isinf(x)) return math_error(_DOMAIN, "fmodf", x, y, (x * y) / (x * y)); + if (yi << 1 == 0 || isnan(y) || ex == 0xff) + return (x * y) / (x * y); + if (xi << 1 <= yi << 1) { + if (xi << 1 == yi << 1) + return 0 * x; + return x; + } + + /* normalize x and y */ + if (!ex) { + for (i = xi << 9; i >> 31 == 0; ex--, i <<= 1); + xi <<= -ex + 1; + } else { + xi &= -1U >> 9; + xi |= 1U << 23; + } + if (!ey) { + for (i = yi << 9; i >> 31 == 0; ey--, i <<= 1); + yi <<= -ey + 1; + } else { + yi &= -1U >> 9; + yi |= 1U << 23; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = xi - yi; + if (i >> 31 == 0) { + if (i == 0) + return 0 * x; + xi = i; + } + xi <<= 1; + } + i = xi - yi; + if (i >> 31 == 0) { + if (i == 0) + return 0 * x; + xi = i; + } + for (; xi>>23 == 0; xi <<= 1, ex--); + + /* scale result up */ + if (ex > 0) { + xi -= 1U << 23; + xi |= (UINT32)ex << 23; + } else { + xi >>= -ex + 1; + } + xi |= sx; + return *(float*)ξ }
/********************************************************************* @@ -633,9 +691,9 @@ float CDECL fmodf( float x, float y ) */ float CDECL logf( float x ) { - float ret = unix_funcs->logf( x ); - if (x < 0.0) return math_error(_DOMAIN, "logf", x, 0, ret); - if (x == 0.0) return math_error(_SING, "logf", x, 0, ret); + float ret = unix_funcs->logf( x ); + if (x < 0.0) return math_error(_DOMAIN, "logf", x, 0, ret); + if (x == 0.0) return math_error(_SING, "logf", x, 0, ret); return ret; }
diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index 69ce6bb027e..a2bae9c6e5e 100644 --- a/dlls/msvcrt/unixlib.c +++ b/dlls/msvcrt/unixlib.c @@ -297,14 +297,6 @@ static float CDECL unix_fmaf( float x, float y, float z ) #endif }
-/********************************************************************* - * fmodf - */ -static float CDECL unix_fmodf( float x, float y ) -{ - return fmodf( x, y ); -} - /********************************************************************* * frexp */ @@ -665,7 +657,6 @@ static const struct unix_funcs funcs = unix_expm1f, unix_fma, unix_fmaf, - unix_fmodf, unix_frexp, unix_frexpf, unix_hypot, diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index c1cd2c60d29..edb9e99d3e4 100644 --- a/dlls/msvcrt/unixlib.h +++ b/dlls/msvcrt/unixlib.h @@ -45,7 +45,6 @@ struct unix_funcs float (CDECL *expm1f)(float x); double (CDECL *fma)(double x, double y, double z); float (CDECL *fmaf)(float x, float y, float z); - float (CDECL *fmodf)(float x, float y); double (CDECL *frexp)(double x, int *exp); float (CDECL *frexpf)(float x, int *exp); double (CDECL *hypot)(double x, double y);