Piotr Caban : msvcrt: Imporve sqrt accuracy and performance on x86_64.

Alexandre Julliard julliard at winehq.org
Tue Feb 2 15:52:10 CST 2021


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Mon Feb  1 20:47:08 2021 +0100

msvcrt: Imporve sqrt accuracy and performance on x86_64.

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

---

 dlls/msvcrt/math.c | 88 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 62 insertions(+), 26 deletions(-)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 66fd3b5c036..32971f73543 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -1165,6 +1165,43 @@ double CDECL sinh( double x )
   return ret;
 }
 
+static inline double CDECL ret_nan( void )
+{
+    double x = 1.0;
+    return (x - x) / (x - x);
+}
+
+BOOL sqrt_validate( double *x )
+{
+    short c = _dclass(*x);
+
+    if (c == FP_ZERO) return FALSE;
+    if (c == FP_NAN)
+    {
+#ifdef __i386__
+        *x = math_error(_DOMAIN, "sqrt", *x, 0, *x);
+#else
+        /* set signaling bit */
+        *(ULONGLONG*)x |= 0x8000000000000ULL;
+#endif
+        return FALSE;
+    }
+    if (signbit(*x))
+    {
+        *x = math_error(_DOMAIN, "sqrt", *x, 0, ret_nan());
+        return FALSE;
+    }
+    if (c == FP_INFINITE) return FALSE;
+    return TRUE;
+}
+
+#if defined(__x86_64__)
+double CDECL sse2_sqrt(double);
+__ASM_GLOBAL_FUNC( sse2_sqrt,
+        "sqrtsd %xmm0, %xmm0\n\t"
+        "ret" )
+#endif
+
 /*********************************************************************
  *		sqrt (MSVCRT.@)
  *
@@ -1172,6 +1209,12 @@ double CDECL sinh( double x )
  */
 double CDECL sqrt( double x )
 {
+#ifdef __x86_64__
+    if (!sqrt_validate(&x))
+        return x;
+
+    return sse2_sqrt(x);
+#else
     static const double tiny = 1.0e-300;
 
     double z;
@@ -1180,21 +1223,13 @@ double CDECL sqrt( double x )
     unsigned int r,t1,s1,ix1,q1;
     ULONGLONG ix;
 
+    if (!sqrt_validate(&x))
+        return x;
+
     ix = *(ULONGLONG*)&x;
     ix0 = ix >> 32;
     ix1 = ix;
 
-    /* take care of Inf and NaN */
-    if (isnan(x) || (isinf(x) && x > 0))
-        return x;
-
-    /* take care of zero */
-    if (ix0 <= 0) {
-        if (((ix0 & ~sign) | ix1) == 0)
-            return x;  /* sqrt(+-0) = +-0 */
-        if (ix0 < 0)
-            return math_error(_DOMAIN, "sqrt", x, 0, (x - x) / (x - x));
-    }
     /* normalize x */
     m = ix0 >> 20;
     if (m == 0) {  /* subnormal x */
@@ -1278,6 +1313,7 @@ double CDECL sqrt( double x )
     ix <<= 32;
     ix |= ix1;
     return *(double*)&ix;
+#endif
 }
 
 /*********************************************************************
@@ -3424,6 +3460,21 @@ __int64 CDECL llrintf(float x)
     return unix_funcs->llrintf( x );
 }
 
+/*********************************************************************
+ *      _dclass (MSVCR120.@)
+ *
+ * Copied from musl: src/math/__fpclassify.c
+ */
+short CDECL _dclass(double x)
+{
+    union { double f; UINT64 i; } u = { x };
+    int e = u.i >> 52 & 0x7ff;
+
+    if (!e) return u.i << 1 ? FP_SUBNORMAL : FP_ZERO;
+    if (e == 0x7ff) return (u.i << 12) ? FP_NAN : FP_INFINITE;
+    return FP_NORMAL;
+}
+
 #if _MSVCR_VER>=120
 
 /*********************************************************************
@@ -3490,21 +3541,6 @@ float CDECL truncf(float x)
     return unix_funcs->truncf(x);
 }
 
-/*********************************************************************
- *      _dclass (MSVCR120.@)
- *
- * Copied from musl: src/math/__fpclassify.c
- */
-short CDECL _dclass(double x)
-{
-    union { double f; UINT64 i; } u = { x };
-    int e = u.i >> 52 & 0x7ff;
-
-    if (!e) return u.i << 1 ? FP_SUBNORMAL : FP_ZERO;
-    if (e == 0x7ff) return (u.i << 12) ? FP_NAN : FP_INFINITE;
-    return FP_NORMAL;
-}
-
 /*********************************************************************
  *      _fdclass (MSVCR120.@)
  *




More information about the wine-cvs mailing list