Module: wine Branch: master Commit: 7d0d7690eb03330c16894d4e0bf5ca18335619ca URL: https://source.winehq.org/git/wine.git/?a=commit;h=7d0d7690eb03330c16894d4e0...
Author: Piotr Caban piotr@codeweavers.com Date: Sat May 29 19:13:36 2021 +0200
msvcrt: Import expm1f implementation from musl.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
configure | 1 - configure.ac | 1 - dlls/msvcrt/math.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++-- dlls/msvcrt/unixlib.c | 13 -------- dlls/msvcrt/unixlib.h | 1 - include/config.h.in | 3 -- 6 files changed, 84 insertions(+), 22 deletions(-)
diff --git a/configure b/configure index 75ac679a1d5..3f8b89d287d 100755 --- a/configure +++ b/configure @@ -19618,7 +19618,6 @@ fi for ac_func in \ exp2 \ exp2f \ - expm1f \ fma \ fmaf \ lgamma \ diff --git a/configure.ac b/configure.ac index 9d4e8278eed..7ea0d824cee 100644 --- a/configure.ac +++ b/configure.ac @@ -2658,7 +2658,6 @@ fi AC_CHECK_FUNCS(\ exp2 \ exp2f \ - expm1f \ fma \ fmaf \ lgamma \ diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index f9b2dc06d78..06f1dc26838 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -5856,12 +5856,93 @@ double CDECL expm1(double x)
/********************************************************************* * expm1f (MSVCR120.@) + * + * Copied from musl: src/math/expm1f.c */ float CDECL expm1f(float x) { - float ret = unix_funcs->expm1f( x ); - if (isfinite(x) && !isfinite(ret)) *_errno() = ERANGE; - return ret; + static const float ln2_hi = 6.9313812256e-01, + ln2_lo = 9.0580006145e-06, + invln2 = 1.4426950216e+00, + Q1 = -3.3333212137e-2, + Q2 = 1.5807170421e-3; + + float y, hi, lo, c, t, e, hxs, hfx, r1, twopk; + union {float f; UINT32 i;} u = {x}; + UINT32 hx = u.i & 0x7fffffff; + int k, sign = u.i >> 31; + + /* filter out huge and non-finite argument */ + if (hx >= 0x4195b844) { /* if |x|>=27*ln2 */ + if (hx >= 0x7f800000) /* NaN */ + return u.i == 0xff800000 ? -1 : x; + if (sign) + return math_error(_UNDERFLOW, "exp", x, 0, -1); + if (hx > 0x42b17217) /* x > log(FLT_MAX) */ + return math_error(_OVERFLOW, "exp", x, 0, fp_barrierf(x * FLT_MAX)); + } + + /* argument reduction */ + if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ + if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ + if (!sign) { + hi = x - ln2_hi; + lo = ln2_lo; + k = 1; + } else { + hi = x + ln2_hi; + lo = -ln2_lo; + k = -1; + } + } else { + k = invln2 * x + (sign ? -0.5f : 0.5f); + t = k; + hi = x - t * ln2_hi; /* t*ln2_hi is exact here */ + lo = t * ln2_lo; + } + x = hi - lo; + c = (hi - x) - lo; + } else if (hx < 0x33000000) { /* when |x|<2**-25, return x */ + if (hx < 0x00800000) + fp_barrierf(x * x); + return x; + } else + k = 0; + + /* x is now in primary range */ + hfx = 0.5f * x; + hxs = x * hfx; + r1 = 1.0f + hxs * (Q1 + hxs * Q2); + t = 3.0f - r1 * hfx; + e = hxs * ((r1 - t) / (6.0f - x * t)); + if (k == 0) /* c is 0 */ + return x - (x * e - hxs); + e = x * (e - c) - c; + e -= hxs; + /* exp(x) ~ 2^k (x_reduced - e + 1) */ + if (k == -1) + return 0.5f * (x - e) - 0.5f; + if (k == 1) { + if (x < -0.25f) + return -2.0f * (e - (x + 0.5f)); + return 1.0f + 2.0f * (x - e); + } + u.i = (0x7f + k) << 23; /* 2^k */ + twopk = u.f; + if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */ + y = x - e + 1.0f; + if (k == 128) + y = y * 2.0f * 0x1p127f; + else + y = y * twopk; + return y - 1.0f; + } + u.i = (0x7f-k) << 23; /* 2^-k */ + if (k < 23) + y = (x - e + (1 - u.f)) * twopk; + else + y = (x - (e + u.f) + 1) * twopk; + return y; }
/********************************************************************* diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index 3b0dcea9b47..c0c3a2b1636 100644 --- a/dlls/msvcrt/unixlib.c +++ b/dlls/msvcrt/unixlib.c @@ -98,18 +98,6 @@ static float CDECL unix_exp2f( float x ) #endif }
-/********************************************************************* - * expm1f - */ -static float CDECL unix_expm1f(float x) -{ -#ifdef HAVE_EXPM1F - return expm1f(x); -#else - return exp(x) - 1; -#endif -} - /********************************************************************* * fma */ @@ -362,7 +350,6 @@ static const struct unix_funcs funcs = unix_expf, unix_exp2, unix_exp2f, - unix_expm1f, unix_fma, unix_fmaf, unix_frexp, diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index 01907623f6a..6f8347b066a 100644 --- a/dlls/msvcrt/unixlib.h +++ b/dlls/msvcrt/unixlib.h @@ -29,7 +29,6 @@ struct unix_funcs float (CDECL *expf)(float x); double (CDECL *exp2)(double x); float (CDECL *exp2f)(float x); - float (CDECL *expm1f)(float x); double (CDECL *fma)(double x, double y, double z); float (CDECL *fmaf)(float x, float y, float z); double (CDECL *frexp)(double x, int *exp); diff --git a/include/config.h.in b/include/config.h.in index 7ab23e1ab51..42aaa2708a8 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -98,9 +98,6 @@ /* Define to 1 if you have the `exp2f' function. */ #undef HAVE_EXP2F
-/* Define to 1 if you have the `expm1f' function. */ -#undef HAVE_EXPM1F - /* Define to 1 if you have the `F3DAudioInitialize8' function. */ #undef HAVE_F3DAUDIOINITIALIZE8