msvcrt: Import fmodf implementation from musl.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2021-05-18 19:08:28 +02:00 committed by Alexandre Julliard
parent 2e8cfcf5b5
commit bc5f28888c
3 changed files with 64 additions and 16 deletions

View File

@ -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*)&xi;
}
/*********************************************************************
@ -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;
}

View File

@ -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,

View File

@ -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);