Piotr Caban : msvcrt: Import fmod implementation from musl.
Alexandre Julliard
julliard at winehq.org
Tue May 18 15:42:38 CDT 2021
Module: wine
Branch: master
Commit: 2e8cfcf5b5e58566615812af0bab602f3bf7c654
URL: https://source.winehq.org/git/wine.git/?a=commit;h=2e8cfcf5b5e58566615812af0bab602f3bf7c654
Author: Piotr Caban <piotr at codeweavers.com>
Date: Tue May 18 19:08:17 2021 +0200
msvcrt: Import fmod implementation from musl.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcrt/math.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++---
dlls/msvcrt/unixlib.c | 9 --------
dlls/msvcrt/unixlib.h | 1 -
3 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index f2caa81712b..d71a7108b5d 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -1266,12 +1266,70 @@ double CDECL exp( double x )
/*********************************************************************
* fmod (MSVCRT.@)
+ *
+ * Copied from musl: src/math/fmod.c
*/
double CDECL fmod( double x, double y )
{
- double ret = unix_funcs->fmod( x, y );
- if (!isfinite(x) || !isfinite(y)) return math_error(_DOMAIN, "fmod", x, y, ret);
- return ret;
+ UINT64 xi = *(UINT64*)&x;
+ UINT64 yi = *(UINT64*)&y;
+ int ex = xi >> 52 & 0x7ff;
+ int ey = yi >> 52 & 0x7ff;
+ int sx = xi >> 63;
+ UINT64 i;
+
+ if (isinf(x)) return math_error(_DOMAIN, "fmod", x, y, (x * y) / (x * y));
+ if (yi << 1 == 0 || isnan(y) || ex == 0x7ff)
+ 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 << 12; i >> 63 == 0; ex--, i <<= 1);
+ xi <<= -ex + 1;
+ } else {
+ xi &= -1ULL >> 12;
+ xi |= 1ULL << 52;
+ }
+ if (!ey) {
+ for (i = yi << 12; i >> 63 == 0; ey--, i <<= 1);
+ yi <<= -ey + 1;
+ } else {
+ yi &= -1ULL >> 12;
+ yi |= 1ULL << 52;
+ }
+
+ /* x mod y */
+ for (; ex > ey; ex--) {
+ i = xi - yi;
+ if (i >> 63 == 0) {
+ if (i == 0)
+ return 0 * x;
+ xi = i;
+ }
+ xi <<= 1;
+ }
+ i = xi - yi;
+ if (i >> 63 == 0) {
+ if (i == 0)
+ return 0 * x;
+ xi = i;
+ }
+ for (; xi >> 52 == 0; xi <<= 1, ex--);
+
+ /* scale result */
+ if (ex > 0) {
+ xi -= 1ULL << 52;
+ xi |= (UINT64)ex << 52;
+ } else {
+ xi >>= -ex + 1;
+ }
+ xi |= (UINT64)sx << 63;
+ return *(double*)ξ
}
/*********************************************************************
diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c
index d7e368d1b37..69ce6bb027e 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
}
-/*********************************************************************
- * fmod
- */
-static double CDECL unix_fmod( double x, double y )
-{
- return fmod( x, y );
-}
-
/*********************************************************************
* fmodf
*/
@@ -673,7 +665,6 @@ static const struct unix_funcs funcs =
unix_expm1f,
unix_fma,
unix_fmaf,
- unix_fmod,
unix_fmodf,
unix_frexp,
unix_frexpf,
diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h
index b8c18b1e2a5..c1cd2c60d29 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);
- double (CDECL *fmod)(double x, double y);
float (CDECL *fmodf)(float x, float y);
double (CDECL *frexp)(double x, int *exp);
float (CDECL *frexpf)(float x, int *exp);
More information about the wine-cvs
mailing list