Martin Storsjo : msvcrt: Convert double (numerically) to UINT64 via INT64, fixing pow() on arm.

Alexandre Julliard julliard at winehq.org
Wed Jul 28 15:37:42 CDT 2021


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

Author: Martin Storsjo <martin at martin.st>
Date:   Tue Jul 27 01:28:01 2021 +0300

msvcrt: Convert double (numerically) to UINT64 via INT64, fixing pow() on arm.

If converting a negative double to an UINT64, on arm it's clipped
to zero instead of converted to its two's complement form (contrary
to x86).

This fixes cases like pow(2.0, -2.0) on arm/aarch64. Add similar
casts to expf() too which seems to have a similar pattern, even if
it's not known if that case can cause issues or not.

In the original musl source, the converttoint() function returns a
signed int32_t, doing the same double->signed->unsigned conversion,
implicitly.

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

---

 dlls/msvcrt/math.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index 69b807f722c..124cdf80098 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -1204,7 +1204,7 @@ float CDECL expf( float x )
        ideally ties-to-even rule is used, otherwise the magnitude of r
        can be bigger which gives larger approximation error.  */
     kd = __round(z);
-    ki = kd;
+    ki = (INT64)kd;
     r = z - kd;
 
     /* exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
@@ -1508,7 +1508,7 @@ static float powf_exp2(double xd, UINT32 sign_bias)
 
     /* N*x = k + r with r in [-1/2, 1/2] */
     kd = __round(xd); /* k */
-    ki = kd;
+    ki = (INT64)kd;
     r = xd - kd;
 
     /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
@@ -3824,7 +3824,7 @@ static double pow_exp(double argx, double argy, double x, double xtail, UINT32 s
     /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */
     z = invln2N * x;
     kd = __round(z);
-    ki = kd;
+    ki = (INT64)kd;
     r = x + kd * negln2hiN + kd * negln2loN;
     /* The code assumes 2^-200 < |xtail| < 2^-8/N. */
     r += xtail;




More information about the wine-cvs mailing list