Piotr Caban : msvcrt: Import erfcf implementation from musl.

Alexandre Julliard julliard at winehq.org
Wed May 19 14:55:13 CDT 2021


Module: wine
Branch: master
Commit: de11fe6dcd7a816d6a2dd98310345227a7c08141
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=de11fe6dcd7a816d6a2dd98310345227a7c08141

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed May 19 15:26:23 2021 +0200

msvcrt: Import erfcf implementation from musl.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 configure             |   1 -
 configure.ac          |   1 -
 dlls/msvcrt/math.c    | 125 +++++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/msvcrt/unixlib.c |  13 ------
 dlls/msvcrt/unixlib.h |   1 -
 include/config.h.in   |   3 --
 6 files changed, 124 insertions(+), 20 deletions(-)

diff --git a/configure b/configure
index 44077d727fe..00c8378b4c6 100755
--- a/configure
+++ b/configure
@@ -19624,7 +19624,6 @@ for ac_func in \
 	atanhf \
 	erf \
 	erfc \
-	erfcf \
 	erff \
 	exp2 \
 	exp2f \
diff --git a/configure.ac b/configure.ac
index 56a4a75ac08..e8b3d175fc9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2664,7 +2664,6 @@ AC_CHECK_FUNCS(\
 	atanhf \
 	erf \
 	erfc \
-	erfcf \
 	erff \
 	exp2 \
 	exp2f \
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 8ac545ae758..bd4df691e58 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -5223,6 +5223,87 @@ double CDECL erf(double x)
     return unix_funcs->erf( x );
 }
 
+static float erfc1f(float x)
+{
+    static const float erx  =  8.4506291151e-01,
+                 pa0  = -2.3621185683e-03,
+                 pa1  =  4.1485610604e-01,
+                 pa2  = -3.7220788002e-01,
+                 pa3  =  3.1834661961e-01,
+                 pa4  = -1.1089469492e-01,
+                 pa5  =  3.5478305072e-02,
+                 pa6  = -2.1663755178e-03,
+                 qa1  =  1.0642088205e-01,
+                 qa2  =  5.4039794207e-01,
+                 qa3  =  7.1828655899e-02,
+                 qa4  =  1.2617121637e-01,
+                 qa5  =  1.3637083583e-02,
+                 qa6  =  1.1984500103e-02;
+
+    float s, P, Q;
+
+    s = fabsf(x) - 1;
+    P = pa0 + s * (pa1 + s * (pa2 + s * (pa3 + s * (pa4 + s * (pa5 + s * pa6)))));
+    Q = 1 + s * (qa1 + s * (qa2 + s * (qa3 + s * (qa4 + s * (qa5 + s * qa6)))));
+    return 1 - erx - P / Q;
+}
+
+static float erfc2f(UINT32 ix, float x)
+{
+    static const float ra0  = -9.8649440333e-03,
+                 ra1  = -6.9385856390e-01,
+                 ra2  = -1.0558626175e+01,
+                 ra3  = -6.2375331879e+01,
+                 ra4  = -1.6239666748e+02,
+                 ra5  = -1.8460508728e+02,
+                 ra6  = -8.1287437439e+01,
+                 ra7  = -9.8143291473e+00,
+                 sa1  =  1.9651271820e+01,
+                 sa2  =  1.3765776062e+02,
+                 sa3  =  4.3456588745e+02,
+                 sa4  =  6.4538726807e+02,
+                 sa5  =  4.2900814819e+02,
+                 sa6  =  1.0863500214e+02,
+                 sa7  =  6.5702495575e+00,
+                 sa8  = -6.0424413532e-02,
+                 rb0  = -9.8649431020e-03,
+                 rb1  = -7.9928326607e-01,
+                 rb2  = -1.7757955551e+01,
+                 rb3  = -1.6063638306e+02,
+                 rb4  = -6.3756646729e+02,
+                 rb5  = -1.0250950928e+03,
+                 rb6  = -4.8351919556e+02,
+                 sb1  =  3.0338060379e+01,
+                 sb2  =  3.2579251099e+02,
+                 sb3  =  1.5367296143e+03,
+                 sb4  =  3.1998581543e+03,
+                 sb5  =  2.5530502930e+03,
+                 sb6  =  4.7452853394e+02,
+                 sb7  = -2.2440952301e+01;
+
+    float s, R, S, z;
+
+    if (ix < 0x3fa00000) /* |x| < 1.25 */
+        return erfc1f(x);
+
+    x = fabsf(x);
+    s = 1 / (x * x);
+    if (ix < 0x4036db6d) { /* |x| < 1/0.35 */
+        R = ra0 + s * (ra1 + s * (ra2 + s * (ra3 + s * (ra4 + s *
+                            (ra5 + s * (ra6 + s * ra7))))));
+        S = 1.0f + s * (sa1 + s * (sa2 + s * (sa3 + s * (sa4 + s *
+                            (sa5 + s * (sa6 + s * (sa7 + s * sa8)))))));
+    } else { /* |x| >= 1/0.35 */
+        R = rb0 + s * (rb1 + s * (rb2 + s * (rb3 + s * (rb4 + s * (rb5 + s * rb6)))));
+        S = 1.0f + s * (sb1 + s * (sb2 + s * (sb3 + s * (sb4 + s *
+                            (sb5 + s * (sb6 + s * sb7))))));
+    }
+
+    ix = *(UINT32*)&x & 0xffffe000;
+    z = *(float*)&ix;
+    return expf(-z * z - 0.5625f) * expf((z - x) * (z + x) + R / S) / x;
+}
+
 /*********************************************************************
  *      erff (MSVCR120.@)
  */
@@ -5241,10 +5322,52 @@ double CDECL erfc(double x)
 
 /*********************************************************************
  *      erfcf (MSVCR120.@)
+ *
+ * Copied from musl: src/math/erff.c
  */
 float CDECL erfcf(float x)
 {
-    return unix_funcs->erfcf( x );
+    static const float pp0  =  1.2837916613e-01,
+                 pp1  = -3.2504209876e-01,
+                 pp2  = -2.8481749818e-02,
+                 pp3  = -5.7702702470e-03,
+                 pp4  = -2.3763017452e-05,
+                 qq1  =  3.9791721106e-01,
+                 qq2  =  6.5022252500e-02,
+                 qq3  =  5.0813062117e-03,
+                 qq4  =  1.3249473704e-04,
+                 qq5  = -3.9602282413e-06;
+
+    float r, s, z, y;
+    UINT32 ix;
+    int sign;
+
+    ix = *(UINT32*)&x;
+    sign = ix >> 31;
+    ix &= 0x7fffffff;
+    if (ix >= 0x7f800000) {
+        /* erfc(nan)=nan, erfc(+-inf)=0,2 */
+        return 2 * sign + 1 / x;
+    }
+
+    if (ix < 0x3f580000) { /* |x| < 0.84375 */
+        if (ix < 0x23800000) /* |x| < 2**-56 */
+            return 1.0f - x;
+        z = x * x;
+        r = pp0 + z * (pp1 + z * (pp2 + z * (pp3 + z * pp4)));
+        s = 1.0f + z * (qq1 + z * (qq2 + z * (qq3 + z * (qq4 + z * qq5))));
+        y = r / s;
+        if (sign || ix < 0x3e800000) /* x < 1/4 */
+            return 1.0f - (x + x * y);
+        return 0.5f - (x - 0.5f + x * y);
+    }
+    if (ix < 0x41e00000) { /* |x| < 28 */
+        return sign ? 2 - erfc2f(ix, x) : erfc2f(ix, x);
+    }
+    if (sign)
+        return 2 - FLT_MIN;
+    *_errno() = ERANGE;
+    return FLT_MIN * FLT_MIN;
 }
 
 /*********************************************************************
diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c
index da253d9b55c..77de4602918 100644
--- a/dlls/msvcrt/unixlib.c
+++ b/dlls/msvcrt/unixlib.c
@@ -197,18 +197,6 @@ static double CDECL unix_erfc(double x)
 #endif
 }
 
-/*********************************************************************
- *      erfcf
- */
-static float CDECL unix_erfcf(float x)
-{
-#ifdef HAVE_ERFCF
-    return erfcf(x);
-#else
-    return unix_erfc(x);
-#endif
-}
-
 /*********************************************************************
  *      exp
  */
@@ -579,7 +567,6 @@ static const struct unix_funcs funcs =
     unix_coshf,
     unix_erf,
     unix_erfc,
-    unix_erfcf,
     unix_erff,
     unix_exp,
     unix_expf,
diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h
index 84e62fd133a..13912c68c99 100644
--- a/dlls/msvcrt/unixlib.h
+++ b/dlls/msvcrt/unixlib.h
@@ -35,7 +35,6 @@ struct unix_funcs
     float           (CDECL *coshf)(float x);
     double          (CDECL *erf)(double x);
     double          (CDECL *erfc)(double x);
-    float           (CDECL *erfcf)(float x);
     float           (CDECL *erff)(float x);
     double          (CDECL *exp)(double x);
     float           (CDECL *expf)(float x);
diff --git a/include/config.h.in b/include/config.h.in
index 72e981821da..d7738888e27 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -116,9 +116,6 @@
 /* Define to 1 if you have the `erfc' function. */
 #undef HAVE_ERFC
 
-/* Define to 1 if you have the `erfcf' function. */
-#undef HAVE_ERFCF
-
 /* Define to 1 if you have the `erff' function. */
 #undef HAVE_ERFF
 




More information about the wine-cvs mailing list