Piotr Caban : msvcrt: Import log10 implementation from musl.

Alexandre Julliard julliard at winehq.org
Fri Jun 4 14:32:29 CDT 2021


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Jun  4 18:25:35 2021 +0200

msvcrt: Import log10 implementation from musl.

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

---

 dlls/msvcrt/math.c    | 80 ++++++++++++++++++++++++++++++++++++++++++++++++---
 dlls/msvcrt/unixlib.c |  9 ------
 dlls/msvcrt/unixlib.h |  1 -
 3 files changed, 76 insertions(+), 14 deletions(-)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 5702131cec9..4eb759c2dda 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -2964,10 +2964,82 @@ double CDECL log( double x )
  */
 double CDECL log10( double x )
 {
-  double ret = unix_funcs->log10( x );
-  if (x < 0.0) return math_error(_DOMAIN, "log10", x, 0, ret);
-  if (x == 0.0) return math_error(_SING, "log10", x, 0, ret);
-  return ret;
+    static const double ivln10hi = 4.34294481878168880939e-01,
+        ivln10lo = 2.50829467116452752298e-11,
+        log10_2hi = 3.01029995663611771306e-01,
+        log10_2lo = 3.69423907715893078616e-13,
+        Lg1 = 6.666666666666735130e-01,
+        Lg2 = 3.999999999940941908e-01,
+        Lg3 = 2.857142874366239149e-01,
+        Lg4 = 2.222219843214978396e-01,
+        Lg5 = 1.818357216161805012e-01,
+        Lg6 = 1.531383769920937332e-01,
+        Lg7 = 1.479819860511658591e-01;
+
+    union {double f; UINT64 i;} u = {x};
+    double hfsq, f, s, z, R, w, t1, t2, dk, y, hi, lo, val_hi, val_lo;
+    UINT32 hx;
+    int k;
+
+    hx = u.i >> 32;
+    k = 0;
+    if (hx < 0x00100000 || hx >> 31) {
+        if (u.i << 1 == 0)
+            return math_error(_SING, "log10", x, 0, -1 / (x * x));
+        if ((u.i & ~(1ULL << 63)) > 0x7ff0000000000000ULL)
+            return x;
+        if (hx >> 31)
+            return math_error(_DOMAIN, "log10", x, 0, (x - x) / (x - x));
+        /* subnormal number, scale x up */
+        k -= 54;
+        x *= 0x1p54;
+        u.f = x;
+        hx = u.i >> 32;
+    } else if (hx >= 0x7ff00000) {
+        return x;
+    } else if (hx == 0x3ff00000 && u.i<<32 == 0)
+        return 0;
+
+    /* reduce x into [sqrt(2)/2, sqrt(2)] */
+    hx += 0x3ff00000 - 0x3fe6a09e;
+    k += (int)(hx >> 20) - 0x3ff;
+    hx = (hx & 0x000fffff) + 0x3fe6a09e;
+    u.i = (UINT64)hx << 32 | (u.i & 0xffffffff);
+    x = u.f;
+
+    f = x - 1.0;
+    hfsq = 0.5 * f * f;
+    s = f / (2.0 + f);
+    z = s * s;
+    w = z * z;
+    t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
+    t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
+    R = t2 + t1;
+
+    /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */
+    hi = f - hfsq;
+    u.f = hi;
+    u.i &= (UINT64)-1 << 32;
+    hi = u.f;
+    lo = f - hi - hfsq + s * (hfsq + R);
+
+    /* val_hi+val_lo ~ log10(1+f) + k*log10(2) */
+    val_hi = hi * ivln10hi;
+    dk = k;
+    y = dk * log10_2hi;
+    val_lo = dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
+
+    /*
+     * Extra precision in for adding y is not strictly needed
+     * since there is no very large cancellation near x = sqrt(2) or
+     * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs
+     * with some parallelism and it reduces the error for many args.
+     */
+    w = y + val_hi;
+    val_lo += (y - w) + val_hi;
+    val_hi = w;
+
+    return val_lo + val_hi;
 }
 
 /*********************************************************************
diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c
index 3b003a846c8..436accde122 100644
--- a/dlls/msvcrt/unixlib.c
+++ b/dlls/msvcrt/unixlib.c
@@ -120,14 +120,6 @@ static float CDECL unix_lgammaf(float x)
 #endif
 }
 
-/*********************************************************************
- *      log10
- */
-static double CDECL unix_log10( double x )
-{
-    return log10( x );
-}
-
 /*********************************************************************
  *      log10f
  */
@@ -211,7 +203,6 @@ static const struct unix_funcs funcs =
     unix_fmaf,
     unix_lgamma,
     unix_lgammaf,
-    unix_log10,
     unix_log10f,
     unix_log2,
     unix_log2f,
diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h
index 7e976949e04..6ff2a520224 100644
--- a/dlls/msvcrt/unixlib.h
+++ b/dlls/msvcrt/unixlib.h
@@ -30,7 +30,6 @@ struct unix_funcs
     float           (CDECL *fmaf)(float x, float y, float z);
     double          (CDECL *lgamma)(double x);
     float           (CDECL *lgammaf)(float x);
-    double          (CDECL *log10)(double x);
     float           (CDECL *log10f)(float x);
     double          (CDECL *log2)(double x);
     float           (CDECL *log2f)(float x);




More information about the wine-cvs mailing list