Module: wine Branch: master Commit: 7fdb78e80bf3a8ea6d165d320c0db76192325069 URL: https://source.winehq.org/git/wine.git/?a=commit;h=7fdb78e80bf3a8ea6d165d320...
Author: Piotr Caban piotr@codeweavers.com Date: Tue Jun 8 21:19:39 2021 +0200
msvcrt: Import fmaf implementation from musl.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
configure | 3 +-- configure.ac | 3 +-- dlls/msvcrt/math.c | 39 ++++++++++++++++++++++++++++++++++----- dlls/msvcrt/unixlib.c | 13 ------------- dlls/msvcrt/unixlib.h | 1 - include/config.h.in | 3 --- 6 files changed, 36 insertions(+), 26 deletions(-)
diff --git a/configure b/configure index 6a250f3728e..06f18a9efe0 100755 --- a/configure +++ b/configure @@ -19621,8 +19621,7 @@ fi
for ac_func in \ exp2 \ - exp2f \ - fmaf + exp2f
do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` diff --git a/configure.ac b/configure.ac index d4c1896fa96..98404b666d5 100644 --- a/configure.ac +++ b/configure.ac @@ -2660,8 +2660,7 @@ fi
AC_CHECK_FUNCS(\ exp2 \ - exp2f \ - fmaf + exp2f ) LIBS="$ac_save_LIBS"
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index a054f561a63..4d7cc6ab727 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -4127,14 +4127,43 @@ double CDECL fma( double x, double y, double z )
/********************************************************************* * fmaf (MSVCRT.@) + * + * Copied from musl: src/math/fmaf.c */ float CDECL fmaf( float x, float y, float z ) { - float w = unix_funcs->fmaf(x, y, z); - if ((isinf(x) && y == 0) || (x == 0 && isinf(y))) *_errno() = EDOM; - else if (isinf(x) && isinf(z) && x != z) *_errno() = EDOM; - else if (isinf(y) && isinf(z) && y != z) *_errno() = EDOM; - return w; + union { double f; UINT64 i; } u; + double xy, adjust; + int e; + + xy = (double)x * y; + u.f = xy + z; + e = u.i>>52 & 0x7ff; + /* Common case: The double precision result is fine. */ + if ((u.i & 0x1fffffff) != 0x10000000 || /* not a halfway case */ + e == 0x7ff || /* NaN */ + (u.f - xy == z && u.f - z == xy) || /* exact */ + (_controlfp(0, 0) & _MCW_RC) != _RC_NEAR) /* not round-to-nearest */ + { + if (!isnan(x) && !isnan(y) && !isnan(z) && isnan(u.f)) *_errno() = EDOM; + + /* underflow may not be raised correctly, example: + fmaf(0x1p-120f, 0x1p-120f, 0x1p-149f) */ + if (e < 0x3ff-126 && e >= 0x3ff-149 && _statusfp() & _SW_INEXACT) + fp_barrierf((float)u.f * (float)u.f); + return u.f; + } + + /* + * 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. + */ + _controlfp(_RC_CHOP, _MCW_RC); + adjust = fp_barrier(xy + z); + _controlfp(_RC_NEAR, _MCW_RC); + if (u.f == adjust) + u.i++; + return u.f; }
/********************************************************************* diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index a01b227e428..91c6bc4c2f0 100644 --- a/dlls/msvcrt/unixlib.c +++ b/dlls/msvcrt/unixlib.c @@ -82,18 +82,6 @@ static float CDECL unix_exp2f( float x ) #endif }
-/********************************************************************* - * fmaf - */ -static float CDECL unix_fmaf( float x, float y, float z ) -{ -#ifdef HAVE_FMAF - return fmaf(x, y, z); -#else - return x * y + z; -#endif -} - /********************************************************************* * pow */ @@ -116,7 +104,6 @@ static const struct unix_funcs funcs = unix_expf, unix_exp2, unix_exp2f, - unix_fmaf, unix_pow, unix_powf, }; diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index b39f56c31cc..b7afa6cdf8b 100644 --- a/dlls/msvcrt/unixlib.h +++ b/dlls/msvcrt/unixlib.h @@ -27,7 +27,6 @@ struct unix_funcs float (CDECL *expf)(float x); double (CDECL *exp2)(double x); float (CDECL *exp2f)(float x); - float (CDECL *fmaf)(float x, float y, float z); double (CDECL *pow)(double x, double y); float (CDECL *powf)(float x, float y); }; diff --git a/include/config.h.in b/include/config.h.in index be6dfb35ab3..09bcdd70983 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -120,9 +120,6 @@ /* Define to 1 if you have the <float.h> header file. */ #undef HAVE_FLOAT_H
-/* Define to 1 if you have the `fmaf' function. */ -#undef HAVE_FMAF - /* Define to 1 if you have the `fnmatch' function. */ #undef HAVE_FNMATCH