diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 723c341c653..73277a6a7b5 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -340,12 +340,73 @@ float CDECL MSVCRT_atanf( float x ) /********************************************************************* * MSVCRT_atan2f (MSVCRT.@) + * + * Copied from musl: src/math/atan2f.c */ -float CDECL MSVCRT_atan2f( float x, float y ) +float CDECL MSVCRT_atan2f( float y, float x ) { - float ret = atan2f(x, y); - if (isnan(x)) return math_error(_DOMAIN, "atan2f", x, y, ret); - return ret; + static const float pi = 3.1415927410e+00, + pi_lo = -8.7422776573e-08; + + float z; + unsigned int m, ix, iy; + + if (MSVCRT__isnanf(x) || MSVCRT__isnanf(y)) + return x + y; + ix = *(unsigned int*)&x; + iy = *(unsigned int*)&y; + if (ix == 0x3f800000) /* x=1.0 */ + return atanf(y); + m = ((iy >> 31) & 1) | ((ix >> 30) & 2); /* 2*sign(x)+sign(y) */ + ix &= 0x7fffffff; + iy &= 0x7fffffff; + + /* when y = 0 */ + if (iy == 0) { + switch (m) { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return pi; /* atan(+0,-anything) = pi */ + case 3: return -pi; /* atan(-0,-anything) =-pi */ + } + } + /* when x = 0 */ + if (ix == 0) + return m & 1 ? -pi / 2 : pi / 2; + /* when x is INF */ + if (ix == 0x7f800000) { + if (iy == 0x7f800000) { + switch (m) { + case 0: return pi / 4; /* atan(+INF,+INF) */ + case 1: return -pi / 4; /* atan(-INF,+INF) */ + case 2: return 3 * pi / 4; /*atan(+INF,-INF)*/ + case 3: return -3 * pi / 4; /*atan(-INF,-INF)*/ + } + } else { + switch (m) { + case 0: return 0.0f; /* atan(+...,+INF) */ + case 1: return -0.0f; /* atan(-...,+INF) */ + case 2: return pi; /* atan(+...,-INF) */ + case 3: return -pi; /* atan(-...,-INF) */ + } + } + } + /* |y/x| > 0x1p26 */ + if (ix + (26 << 23) < iy || iy == 0x7f800000) + return m & 1 ? -pi / 2 : pi / 2; + + /* z = atan(|y/x|) with correct underflow */ + if ((m & 2) && iy + (26 << 23) < ix) /*|y/x| < 0x1p-26, x < 0 */ + z = 0.0; + else + z = atanf(fabsf(y / x)); + switch (m) { + case 0: return z; /* atan(+,+) */ + case 1: return -z; /* atan(-,+) */ + case 2: return pi - (z - pi_lo); /* atan(+,-) */ + default: /* case 3 */ + return (z - pi_lo) - pi; /* atan(-,-) */ + } } /*********************************************************************