about summary refs log tree commit diff
path: root/src/math/atan.c
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2012-12-11 23:56:59 +0100
committerSzabolcs Nagy <nsz@port70.net>2012-12-11 23:56:59 +0100
commitb12a73d5bf595b7fbb73db30c6bb144078e86ef5 (patch)
tree547edc4ee13453230bb1c154015150b9fc88c766 /src/math/atan.c
parent482ccd2f7497a79ca83e998f54e823e7cedaaa6e (diff)
downloadmusl-b12a73d5bf595b7fbb73db30c6bb144078e86ef5.tar.gz
musl-b12a73d5bf595b7fbb73db30c6bb144078e86ef5.tar.xz
musl-b12a73d5bf595b7fbb73db30c6bb144078e86ef5.zip
math: clean up inverse trigonometric functions
modifications:
* avoid unsigned->signed conversions
* removed various volatile hacks
* use FORCE_EVAL when evaluating only for side-effects
* factor out R() rational approximation instead of manual inline
* __invtrigl.h now only provides __invtrigl_R, __pio2_hi and __pio2_lo
* use 2*pio2_hi, 2*pio2_lo instead of pi_hi, pi_lo

otherwise the logic is not changed, long double versions will
need a revisit when a genaral long double cleanup happens
Diffstat (limited to 'src/math/atan.c')
-rw-r--r--src/math/atan.c32
1 files changed, 13 insertions, 19 deletions
diff --git a/src/math/atan.c b/src/math/atan.c
index f34551c7..7fd8a3b8 100644
--- a/src/math/atan.c
+++ b/src/math/atan.c
@@ -60,32 +60,26 @@ static const double aT[] = {
   1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
 };
 
-static const double huge = 1.0e300;
-
 double atan(double x)
 {
 	double w,s1,s2,z;
-	int32_t ix,hx,id;
+	uint32_t ix,sign;
+	int id;
 
-	GET_HIGH_WORD(hx, x);
-	ix = hx & 0x7fffffff;
+	GET_HIGH_WORD(ix, x);
+	sign = ix >> 31;
+	ix &= 0x7fffffff;
 	if (ix >= 0x44100000) {   /* if |x| >= 2^66 */
-		uint32_t low;
-
-		GET_LOW_WORD(low, x);
-		if (ix > 0x7ff00000 ||
-		    (ix == 0x7ff00000 && low != 0))  /* NaN */
-			return x+x;
-		if (hx > 0)
-			return  atanhi[3] + *(volatile double *)&atanlo[3];
-		else
-			return -atanhi[3] - *(volatile double *)&atanlo[3];
+		if (isnan(x))
+			return x;
+		z = atanhi[3] + 0x1p-1000;
+		return sign ? -z : z;
 	}
 	if (ix < 0x3fdc0000) {    /* |x| < 0.4375 */
 		if (ix < 0x3e400000) {  /* |x| < 2^-27 */
-			/* raise inexact */
-			if (huge+x > 1.0)
-				return x;
+			/* raise inexact if x!=0 */
+			FORCE_EVAL(x + 0x1p1000);
+			return x;
 		}
 		id = -1;
 	} else {
@@ -117,5 +111,5 @@ double atan(double x)
 	if (id < 0)
 		return x - x*(s1+s2);
 	z = atanhi[id] - (x*(s1+s2) - atanlo[id] - x);
-	return hx < 0 ? -z : z;
+	return sign ? -z : z;
 }