diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 9aadc6dea1e..5ecbb8bf037 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2527,9 +2527,33 @@ double CDECL sin( double x ) */ double CDECL sinh( double x ) { - double ret = unix_funcs->sinh( x ); - if (isnan(x)) return math_error(_DOMAIN, "sinh", x, 0, ret); - return ret; + UINT64 ux = *(UINT64*)&x; + UINT32 w; + double t, h, absx; + + h = 0.5; + if (ux >> 63) + h = -h; + /* |x| */ + ux &= (UINT64)-1 / 2; + absx = *(double*)&ux; + w = ux >> 32; + + /* |x| < log(DBL_MAX) */ + if (w < 0x40862e42) { + t = __expm1(absx); + if (w < 0x3ff00000) { + if (w < 0x3ff00000 - (26 << 20)) + return x; + return h * (2 * t - t * t / (t + 1)); + } + return h * (t + t / (t + 1)); + } + + /* |x| > log(DBL_MAX) or nan */ + /* note: the result is stored to handle overflow */ + t = __expo2(absx, 2 * h); + return t; } static BOOL sqrt_validate( double *x, BOOL update_sw ) diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index e5e4233d12f..2f447533fb6 100644 --- a/dlls/msvcrt/unixlib.c +++ b/dlls/msvcrt/unixlib.c @@ -268,14 +268,6 @@ static float CDECL unix_powf( float x, float y ) return powf( x, y ); } -/********************************************************************* - * sinh - */ -static double CDECL unix_sinh( double x ) -{ - return sinh( x ); -} - /********************************************************************* * sinhf */ @@ -351,7 +343,6 @@ static const struct unix_funcs funcs = unix_log2f, unix_pow, unix_powf, - unix_sinh, unix_sinhf, unix_tanh, unix_tanhf, diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index 4c30fc220fe..80a150b9031 100644 --- a/dlls/msvcrt/unixlib.h +++ b/dlls/msvcrt/unixlib.h @@ -46,7 +46,6 @@ struct unix_funcs float (CDECL *log2f)(float x); double (CDECL *pow)(double x, double y); float (CDECL *powf)(float x, float y); - double (CDECL *sinh)(double x); float (CDECL *sinhf)(float x); double (CDECL *tanh)(double x); float (CDECL *tanhf)(float x);