Module: wine Branch: master Commit: f12bcfd2ab1ee985134144cc4163247562b4054c URL: https://source.winehq.org/git/wine.git/?a=commit;h=f12bcfd2ab1ee985134144cc4...
Author: Piotr Caban piotr@codeweavers.com Date: Mon Jan 31 21:36:16 2022 +0100
msvcrt: Fix fmaf not to depend on rounding mode.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msvcrt/math.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 9bb3e26570f..d03b4def801 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -5058,8 +5058,8 @@ double CDECL fma( double x, double y, double z ) float CDECL fmaf( float x, float y, float z ) { union { double f; UINT64 i; } u; - double xy, adjust; - int e; + double xy, err; + int e, neg;
xy = (double)x * y; u.f = xy + z; @@ -5083,11 +5083,15 @@ float CDECL fmaf( float x, float y, float z ) * If result is inexact, and exactly halfway between two float values, * we need to adjust the low-order bit in the direction of the error. */ - _controlfp(_RC_CHOP, _MCW_RC); - adjust = fp_barrier(xy + z); - _controlfp(_RC_NEAR, _MCW_RC); - if (u.f == adjust) + neg = u.i >> 63; + if (neg == (z > xy)) + err = xy - u.f + z; + else + err = z - u.f + xy; + if (neg == (err < 0)) u.i++; + else + u.i--; return u.f; }