Piotr Caban : msvcrt: Import expm1f implementation from musl.

Alexandre Julliard julliard at winehq.org
Mon May 31 15:58:35 CDT 2021


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Sat May 29 19:13:36 2021 +0200

msvcrt: Import expm1f 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    | 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
 




More information about the wine-cvs mailing list