From 9bc856dfaf80f9f69eb5b19f1c7f0159de58a630 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Wed, 19 May 2021 15:26:39 +0200 Subject: [PATCH] msvcrt: Import erf implementation from musl. Signed-off-by: Piotr Caban Signed-off-by: Alexandre Julliard --- configure | 1 - configure.ac | 1 - dlls/msvcrt/math.c | 40 +++++++++++++++++++++++++++++++++++++++- dlls/msvcrt/unixlib.c | 21 --------------------- dlls/msvcrt/unixlib.h | 1 - include/config.h.in | 3 --- 6 files changed, 39 insertions(+), 28 deletions(-) diff --git a/configure b/configure index 8e15b71d74e..ecfe7745900 100755 --- a/configure +++ b/configure @@ -19622,7 +19622,6 @@ for ac_func in \ asinhf \ atanh \ atanhf \ - erf \ exp2 \ exp2f \ expm1 \ diff --git a/configure.ac b/configure.ac index 90522c22867..c144fa1bbdd 100644 --- a/configure.ac +++ b/configure.ac @@ -2662,7 +2662,6 @@ AC_CHECK_FUNCS(\ asinhf \ atanh \ atanhf \ - erf \ exp2 \ exp2f \ expm1 \ diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 787bb18ddad..2e2161e91c4 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -5304,7 +5304,45 @@ static double erfc2(uint32_t ix, double x) */ double CDECL erf(double x) { - return unix_funcs->erf( x ); + static const double efx8 = 1.02703333676410069053e+00, + pp0 = 1.28379167095512558561e-01, + pp1 = -3.25042107247001499370e-01, + pp2 = -2.84817495755985104766e-02, + pp3 = -5.77027029648944159157e-03, + pp4 = -2.37630166566501626084e-05, + qq1 = 3.97917223959155352819e-01, + qq2 = 6.50222499887672944485e-02, + qq3 = 5.08130628187576562776e-03, + qq4 = 1.32494738004321644526e-04, + qq5 = -3.96022827877536812320e-06; + + double r, s, z, y; + UINT32 ix; + int sign; + + ix = *(UINT64*)&x >> 32; + sign = ix >> 31; + ix &= 0x7fffffff; + if (ix >= 0x7ff00000) { + /* erf(nan)=nan, erf(+-inf)=+-1 */ + return 1 - 2 * sign + 1 / x; + } + if (ix < 0x3feb0000) { /* |x| < 0.84375 */ + if (ix < 0x3e300000) { /* |x| < 2**-28 */ + /* avoid underflow */ + return 0.125 * (8 * x + efx8 * x); + } + z = x * x; + r = pp0 + z * (pp1 + z * (pp2 + z * (pp3 + z * pp4))); + s = 1.0 + z * (qq1 + z * (qq2 + z * (qq3 + z * (qq4 + z * qq5)))); + y = r / s; + return x + x * y; + } + if (ix < 0x40180000) /* 0.84375 <= |x| < 6 */ + y = 1 - erfc2(ix, x); + else + y = 1 - DBL_MIN; + return sign ? -y : y; } static float erfc1f(float x) diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c index 59f8ce4cee7..fd82c5afb94 100644 --- a/dlls/msvcrt/unixlib.c +++ b/dlls/msvcrt/unixlib.c @@ -153,26 +153,6 @@ static float CDECL unix_coshf( float x ) return coshf( x ); } -/********************************************************************* - * erf - */ -static double CDECL unix_erf(double x) -{ -#ifdef HAVE_ERF - return erf(x); -#else - /* Abramowitz and Stegun approximation, maximum error: 1.5*10^-7 */ - double t, y; - int sign = signbit(x); - - if (sign) x = -x; - t = 1 / (1 + 0.3275911 * x); - y = ((((1.061405429*t - 1.453152027)*t + 1.421413741)*t - 0.284496736)*t + 0.254829592)*t; - y = 1.0 - y*exp(-x*x); - return sign ? -y : y; -#endif -} - /********************************************************************* * exp */ @@ -541,7 +521,6 @@ static const struct unix_funcs funcs = unix_cosf, unix_cosh, unix_coshf, - unix_erf, unix_exp, unix_expf, unix_exp2, diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h index 9793fca93bd..95b4a6488de 100644 --- a/dlls/msvcrt/unixlib.h +++ b/dlls/msvcrt/unixlib.h @@ -33,7 +33,6 @@ struct unix_funcs float (CDECL *cosf)(float x); double (CDECL *cosh)(double x); float (CDECL *coshf)(float x); - double (CDECL *erf)(double x); double (CDECL *exp)(double x); float (CDECL *expf)(float x); double (CDECL *exp2)(double x); diff --git a/include/config.h.in b/include/config.h.in index befb0af9f7e..74d54a942a6 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -110,9 +110,6 @@ /* Define to 1 if you have the `epoll_create' function. */ #undef HAVE_EPOLL_CREATE -/* Define to 1 if you have the `erf' function. */ -#undef HAVE_ERF - /* Define to 1 if you have the `exp2' function. */ #undef HAVE_EXP2