From 6d85096f49fa955e7e1473b7deb30ce55b6c8be0 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Thu, 15 Aug 2013 14:05:19 +0000 Subject: math: clean up atan2.c * remove volatile hacks * don't care about inexact flag for now (removed all the +-tiny) * fix atanl to raise underflow properly * remove signed int arithmetics * use pi/2 instead of pi_o_2 (gcc generates the same code, which is not correct, but it does not matter: we mainly care about nearest rounding) --- src/math/atan2l.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'src/math/atan2l.c') diff --git a/src/math/atan2l.c b/src/math/atan2l.c index 7cb42c2f..e0167d09 100644 --- a/src/math/atan2l.c +++ b/src/math/atan2l.c @@ -29,26 +29,22 @@ long double atan2l(long double y, long double x) { union IEEEl2bits ux, uy; long double z; - int32_t k,m; - int16_t exptx, expsignx, expty, expsigny; + int m; + uint16_t exptx, expsignx, expty, expsigny; + if (isnan(x) || isnan(y)) + return x+y; + if (x == 1) + return atanl(y); uy.e = y; expsigny = uy.xbits.expsign; expty = expsigny & 0x7fff; ux.e = x; expsignx = ux.xbits.expsign; exptx = expsignx & 0x7fff; - if ((exptx==0x7fff && - ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)!=0) || /* x is NaN */ - (expty==0x7fff && - ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* y is NaN */ - return x+y; - if (expsignx==0x3fff && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) /* x=1.0 */ - return atanl(y); m = ((expsigny>>15)&1) | ((expsignx>>14)&2); /* 2*sign(x)+sign(y) */ - /* when y = 0 */ - if (expty==0 && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)==0) { + if (y == 0) { switch(m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ @@ -56,9 +52,8 @@ long double atan2l(long double y, long double x) case 3: return -2*pio2_hi-0x1p-120f; /* atan(-0,-anything) =-pi */ } } - /* when x = 0 */ - if (exptx==0 && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) - return expsigny < 0 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f; + if (x == 0) + return m&1 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f; /* when x is INF */ if (exptx == 0x7fff) { if (expty == 0x7fff) { @@ -78,17 +73,12 @@ long double atan2l(long double y, long double x) } } /* when y is INF */ - if (expty == 0x7fff) - return expsigny < 0 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f; + if (exptx+120 < expty || expty == 0x7fff) + return m&1 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f; - /* compute y/x */ - k = expty-exptx; - if(k > LDBL_MANT_DIG+2) { /* |y/x| huge */ - z = pio2_hi+0x1p-120f; - m &= 1; - } else if (expsignx < 0 && k < -LDBL_MANT_DIG-2) /* |y/x| tiny, x<0 */ + if ((m&2) && expty+120 < exptx) /* |y/x| tiny, x<0 */ z = 0.0; - else /* safe to do y/x */ + else z = atanl(fabsl(y/x)); switch (m) { case 0: return z; /* atan(+,+) */ -- cgit 1.4.1