[PATCH] 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(a)martin.st> --- 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 96cd073b3d0..2f0ee6f0918 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -1203,7 +1203,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) */ @@ -1507,7 +1507,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) */ @@ -3822,7 +3822,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; -- 2.25.1
participants (2)
-
Martin Storsjo -
Piotr Caban