msvcrt: Fix round implementation when 24-bit precision is used.

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-03 14:01:57 +02:00 committed by Alexandre Julliard
parent e19ad98564
commit df9c11ffa8

View file

@ -87,14 +87,6 @@ static inline float fp_barrierf(float x)
return y; 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 ) static inline double CDECL ret_nan( BOOL update_sw )
{ {
double x = 1.0; double x = 1.0;
@ -4330,32 +4322,26 @@ short CDECL _dclass(double x)
/********************************************************************* /*********************************************************************
* round (MSVCR120.@) * round (MSVCR120.@)
* *
* Copied from musl: src/math/round.c * Based on musl implementation: src/math/round.c
*/ */
double CDECL round(double x) double CDECL round(double x)
{ {
static const double toint = 1 / DBL_EPSILON; ULONGLONG llx = *(ULONGLONG*)&x, tmp;
int e = (llx >> 52 & 0x7ff) - 0x3ff;
ULONGLONG llx = *(ULONGLONG*)&x; if (e >= 52)
int e = llx >> 52 & 0x7ff;
double y;
if (e >= 0x3ff + 52)
return x; return x;
if (llx >> 63) if (e < -1)
x = -x; return 0 * x;
if (e < 0x3ff - 1) else if (e == -1)
return 0 * *(double*)&llx; return signbit(x) ? -1 : 1;
y = fp_barrier(x + toint) - toint - x;
if (y > 0.5) tmp = 0x000fffffffffffffULL >> e;
y = y + x - 1; if (!(llx & tmp))
else if (y <= -0.5) return x;
y = y + x + 1; llx += 0x0008000000000000ULL >> e;
else llx &= ~tmp;
y = y + x; return *(double*)&llx;
if (llx >> 63)
y = -y;
return y;
} }
/********************************************************************* /*********************************************************************