msvcrt: Import nextafter 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-14 16:11:50 +02:00 committed by Alexandre Julliard
parent 854a3cab4c
commit f041eeab26
3 changed files with 38 additions and 17 deletions

View File

@ -87,13 +87,11 @@ static inline float fp_barrierf(float x)
return y;
}
#if _MSVCR_VER>=120
static inline double fp_barrier(double x)
{
volatile double y = x;
return y;
}
#endif
static inline double CDECL ret_nan( BOOL update_sw )
{
@ -3482,13 +3480,46 @@ float CDECL MSVCRT_nexttowardf(float num, double next)
/*********************************************************************
* _nextafter (MSVCRT.@)
*
* Copied from musl: src/math/nextafter.c
*/
double CDECL _nextafter(double num, double next)
double CDECL _nextafter(double x, double y)
{
double retval;
if (!isfinite(num) || !isfinite(next)) *_errno() = EDOM;
retval = unix_funcs->nextafter(num,next);
return retval;
ULONGLONG llx = *(ULONGLONG*)&x;
ULONGLONG lly = *(ULONGLONG*)&y;
ULONGLONG ax, ay;
int e;
if (isnan(x) || isnan(y))
return x + y;
if (llx == lly) {
if (_fpclass(y) & (_FPCLASS_ND | _FPCLASS_PD | _FPCLASS_NZ | _FPCLASS_PZ ))
*_errno() = ERANGE;
return y;
}
ax = llx & -1ULL / 2;
ay = lly & -1ULL / 2;
if (ax == 0) {
if (ay == 0)
return y;
llx = (lly & 1ULL << 63) | 1;
} else if (ax > ay || ((llx ^ lly) & 1ULL << 63))
llx--;
else
llx++;
e = llx >> 52 & 0x7ff;
/* raise overflow if llx is infinite and x is finite */
if (e == 0x7ff) {
fp_barrier(x + x);
*_errno() = ERANGE;
}
/* raise underflow if llx is subnormal or zero */
y = *(double*)&llx;
if (e == 0) {
fp_barrier(x * x + y * y);
*_errno() = ERANGE;
}
return y;
}
/*********************************************************************

View File

@ -547,14 +547,6 @@ static float CDECL unix_modff( float x, float *iptr )
return modff( x, iptr );
}
/*********************************************************************
* nextafter
*/
static double CDECL unix_nextafter(double num, double next)
{
return nextafter(num,next);
}
/*********************************************************************
* nextafterf
*/
@ -822,7 +814,6 @@ static const struct unix_funcs funcs =
unix_logbf,
unix_modf,
unix_modff,
unix_nextafter,
unix_nextafterf,
unix_nexttoward,
unix_nexttowardf,

View File

@ -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);
double (CDECL *nextafter)(double x, double y);
float (CDECL *nextafterf)(float x, float y);
double (CDECL *nexttoward)(double x, double y);
float (CDECL *nexttowardf)(float x, double y);