diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index b682e72ab76..77018e27cf5 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -234,11 +234,45 @@ float CDECL _copysignf( float x, float y ) /********************************************************************* * _nextafterf (MSVCRT.@) + * + * Copied from musl: src/math/nextafterf.c */ -float CDECL _nextafterf( float num, float next ) +float CDECL _nextafterf( float x, float y ) { - if (!isfinite(num) || !isfinite(next)) *_errno() = EDOM; - return unix_funcs->nextafterf( num, next ); + unsigned int ix = *(unsigned int*)&x; + unsigned int iy = *(unsigned int*)&y; + unsigned int ax, ay, e; + + if (isnan(x) || isnan(y)) + return x + y; + if (x == y) { + if (_fpclassf(y) & (_FPCLASS_ND | _FPCLASS_PD | _FPCLASS_NZ | _FPCLASS_PZ )) + *_errno() = ERANGE; + return y; + } + ax = ix & 0x7fffffff; + ay = iy & 0x7fffffff; + if (ax == 0) { + if (ay == 0) + return y; + ix = (iy & 0x80000000) | 1; + } else if (ax > ay || ((ix ^ iy) & 0x80000000)) + ix--; + else + ix++; + e = ix & 0x7f800000; + /* raise overflow if ix is infinite and x is finite */ + if (e == 0x7f800000) { + fp_barrierf(x + x); + *_errno() = ERANGE; + } + /* raise underflow if ix is subnormal or zero */ + y = *(float*)&ix; + if (e == 0) { + fp_barrierf(x * x + y * y); + *_errno() = ERANGE; + } + return y; } /********************************************************************* diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index 931c8a2412b..c36d5a2caad 100644 --- a/dlls/msvcrt/unixlib.c +++ b/dlls/msvcrt/unixlib.c @@ -547,14 +547,6 @@ static float CDECL unix_modff( float x, float *iptr ) return modff( x, iptr ); } -/********************************************************************* - * nextafterf - */ -static float CDECL unix_nextafterf(float num, float next) -{ - return nextafterf(num,next); -} - /********************************************************************* * nexttoward */ @@ -814,7 +806,6 @@ static const struct unix_funcs funcs = unix_logbf, unix_modf, unix_modff, - unix_nextafterf, unix_nexttoward, unix_nexttowardf, unix_pow, diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index 1c43253f746..1a8807b8495 100644 --- a/dlls/msvcrt/unixlib.h +++ b/dlls/msvcrt/unixlib.h @@ -72,7 +72,6 @@ struct unix_funcs float (CDECL *logbf)(float x); double (CDECL *modf)(double x, double *iptr); float (CDECL *modff)(float x, float *iptr); - float (CDECL *nextafterf)(float x, float y); double (CDECL *nexttoward)(double x, double y); float (CDECL *nexttowardf)(float x, double y); double (CDECL *pow)(double x, double y);