Piotr Caban : msvcrt: Import nextafter implementation from musl.

Alexandre Julliard julliard at winehq.org
Fri May 14 15:47:05 CDT 2021


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri May 14 16:11:50 2021 +0200

msvcrt: Import nextafter 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    | 45 ++++++++++++++++++++++++++++++++++++++-------
 dlls/msvcrt/unixlib.c |  9 ---------
 dlls/msvcrt/unixlib.h |  1 -
 3 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 2bc51213a07..b682e72ab76 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -87,13 +87,11 @@ static inline float fp_barrierf(float x)
     return y;
 }
 
-#if _MSVCR_VER>=120
 static inline double fp_barrier(double x)
 {
     volatile double y = x;
     return y;
 }
-#endif
 
 static inline double CDECL ret_nan( BOOL update_sw )
 {
@@ -3482,13 +3480,46 @@ float CDECL MSVCRT_nexttowardf(float num, double next)
 
 /*********************************************************************
  *		_nextafter (MSVCRT.@)
+ *
+ * Copied from musl: src/math/nextafter.c
  */
-double CDECL _nextafter(double num, double next)
+double CDECL _nextafter(double x, double y)
 {
-  double retval;
-  if (!isfinite(num) || !isfinite(next)) *_errno() = EDOM;
-  retval = unix_funcs->nextafter(num,next);
-  return retval;
+    ULONGLONG llx = *(ULONGLONG*)&x;
+    ULONGLONG lly = *(ULONGLONG*)&y;
+    ULONGLONG ax, ay;
+    int e;
+
+    if (isnan(x) || isnan(y))
+        return x + y;
+    if (llx == lly) {
+        if (_fpclass(y) & (_FPCLASS_ND | _FPCLASS_PD | _FPCLASS_NZ | _FPCLASS_PZ ))
+            *_errno() = ERANGE;
+        return y;
+    }
+    ax = llx & -1ULL / 2;
+    ay = lly & -1ULL / 2;
+    if (ax == 0) {
+        if (ay == 0)
+            return y;
+        llx = (lly & 1ULL << 63) | 1;
+    } else if (ax > ay || ((llx ^ lly) & 1ULL << 63))
+        llx--;
+    else
+        llx++;
+    e = llx >> 52 & 0x7ff;
+    /* raise overflow if llx is infinite and x is finite */
+    if (e == 0x7ff) {
+        fp_barrier(x + x);
+        *_errno() = ERANGE;
+    }
+    /* raise underflow if llx is subnormal or zero */
+    y = *(double*)&llx;
+    if (e == 0) {
+        fp_barrier(x * x + y * y);
+        *_errno() = ERANGE;
+    }
+    return y;
 }
 
 /*********************************************************************
diff --git a/dlls/msvcrt/unixlib.c b/dlls/msvcrt/unixlib.c
index 376bdb5c1c7..931c8a2412b 100644
--- a/dlls/msvcrt/unixlib.c
+++ b/dlls/msvcrt/unixlib.c
@@ -547,14 +547,6 @@ static float CDECL unix_modff( float x, float *iptr )
     return modff( x, iptr );
 }
 
-/*********************************************************************
- *      nextafter
- */
-static double CDECL unix_nextafter(double num, double next)
-{
-  return nextafter(num,next);
-}
-
 /*********************************************************************
  *      nextafterf
  */
@@ -822,7 +814,6 @@ static const struct unix_funcs funcs =
     unix_logbf,
     unix_modf,
     unix_modff,
-    unix_nextafter,
     unix_nextafterf,
     unix_nexttoward,
     unix_nexttowardf,
diff --git a/dlls/msvcrt/unixlib.h b/dlls/msvcrt/unixlib.h
index ecdbdf0cca1..1c43253f746 100644
--- a/dlls/msvcrt/unixlib.h
+++ b/dlls/msvcrt/unixlib.h
@@ -72,7 +72,6 @@ struct unix_funcs
     float           (CDECL *logbf)(float x);
     double          (CDECL *modf)(double x, double *iptr);
     float           (CDECL *modff)(float x, float *iptr);
-    double          (CDECL *nextafter)(double x, double y);
     float           (CDECL *nextafterf)(float x, float y);
     double          (CDECL *nexttoward)(double x, double y);
     float           (CDECL *nexttowardf)(float x, double y);




More information about the wine-cvs mailing list