about summary refs log tree commit diff
path: root/src/math/atan2l.c
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2013-08-15 14:05:19 +0000
committerSzabolcs Nagy <nsz@port70.net>2013-08-15 14:05:19 +0000
commit6d85096f49fa955e7e1473b7deb30ce55b6c8be0 (patch)
treea4254fb4660ce953cdbc2b956a0e6d8fd54d312e /src/math/atan2l.c
parent31c5fb80b9eae86f801be4f46025bc6532a554c5 (diff)
downloadmusl-6d85096f49fa955e7e1473b7deb30ce55b6c8be0.tar.gz
musl-6d85096f49fa955e7e1473b7deb30ce55b6c8be0.tar.xz
musl-6d85096f49fa955e7e1473b7deb30ce55b6c8be0.zip
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)
Diffstat (limited to 'src/math/atan2l.c')
-rw-r--r--src/math/atan2l.c36
1 files changed, 13 insertions, 23 deletions
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(+,+) */