Module: wine Branch: master Commit: 3171dccbef835f85852c50e3dc3f37337e76932c URL: https://source.winehq.org/git/wine.git/?a=commit;h=3171dccbef835f85852c50e3d...
Author: Piotr Caban piotr@codeweavers.com Date: Sat May 29 19:13:52 2021 +0200
msvcrt: Import tanh implementation from musl.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msvcrt/math.c | 44 +++++++++++++++++++++++++++++++++++++++++--- dlls/msvcrt/unixlib.c | 9 --------- dlls/msvcrt/unixlib.h | 1 - 3 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 05571a7fe20..6d60a6fa086 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -2834,9 +2834,47 @@ double CDECL tan( double x ) */ double CDECL tanh( double x ) { - double ret = unix_funcs->tanh(x); - if (isnan(x)) return math_error(_DOMAIN, "tanh", x, 0, ret); - return ret; + UINT64 ui = *(UINT64*)&x; + UINT32 w; + int sign; + double t; + + /* x = |x| */ + sign = ui >> 63; + ui &= (UINT64)-1 / 2; + x = *(double*)&ui; + w = ui >> 32; + + if (w > 0x3fe193ea) { + /* |x| > log(3)/2 ~= 0.5493 or nan */ + if (w > 0x40340000) { +#if _MSVCR_VER < 140 + if (isnan(x)) + return math_error(_DOMAIN, "tanh", x, 0, x); +#endif + /* |x| > 20 or nan */ + /* note: this branch avoids raising overflow */ + fp_barrier(x + 0x1p120f); + t = 1 - 0 / x; + } else { + t = __expm1(2 * x); + t = 1 - 2 / (t + 2); + } + } else if (w > 0x3fd058ae) { + /* |x| > log(5/3)/2 ~= 0.2554 */ + t = __expm1(2 * x); + t = t / (t + 2); + } else if (w >= 0x00100000) { + /* |x| >= 0x1p-1022, up to 2ulp error in [0.1,0.2554] */ + t = __expm1(-2 * x); + t = -t / (t + 2); + } else { + /* |x| is subnormal */ + /* note: the branch above would not raise underflow in [0x1p-1023,0x1p-1022) */ + fp_barrier((float)x); + t = x; + } + return sign ? -t : t; }
diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index 918c7e6ed71..ce4a3eed094 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 ); }
-/********************************************************************* - * tanh - */ -static double CDECL unix_tanh( double x ) -{ - return tanh( x ); -} - /********************************************************************* * tanhf */ @@ -335,7 +327,6 @@ static const struct unix_funcs funcs = unix_log2f, unix_pow, unix_powf, - unix_tanh, unix_tanhf, unix_tgamma, unix_tgammaf, diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index 0e3074be0c5..a95aae74dea 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 *tanh)(double x); float (CDECL *tanhf)(float x); double (CDECL *tgamma)(double x); float (CDECL *tgammaf)(float x);