about summary refs log tree commit diff
path: root/src/math/expf.c
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2013-09-04 07:51:11 +0000
committerSzabolcs Nagy <nsz@port70.net>2013-09-05 11:30:08 +0000
commit39c910fb061114e6aa5c3bf2c94b1d7262d62221 (patch)
tree5ca9b82746e8ac224f93dcda1b8d19f95b68eda2 /src/math/expf.c
parentea9bb95a5b36c0a3d2ed8fb03808745b406c2633 (diff)
downloadmusl-39c910fb061114e6aa5c3bf2c94b1d7262d62221.tar.gz
musl-39c910fb061114e6aa5c3bf2c94b1d7262d62221.tar.xz
musl-39c910fb061114e6aa5c3bf2c94b1d7262d62221.zip
math: fix underflow in exp*.c and long double handling in exp2l
* don't care about inexact flag
* use double_t and float_t (faster, smaller, more precise on x86)
* exp: underflow when result is zero or subnormal and not -inf
* exp2: underflow when result is zero or subnormal and not exact
* expm1: underflow when result is zero or subnormal
* expl: don't underflow on -inf
* exp2: fix incorrect comment
* expm1: simplify special case handling and overflow properly
* expm1: cleanup final scaling and fix negative left shift ub (twopk)
Diffstat (limited to 'src/math/expf.c')
-rw-r--r--src/math/expf.c25
1 files changed, 11 insertions, 14 deletions
diff --git a/src/math/expf.c b/src/math/expf.c
index 8aefc917..5572bbf6 100644
--- a/src/math/expf.c
+++ b/src/math/expf.c
@@ -29,7 +29,7 @@ P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */
 
 float expf(float x)
 {
-	float hi, lo, c, xx;
+	float_t hi, lo, c, xx, y;
 	int k, sign;
 	uint32_t hx;
 
@@ -38,20 +38,17 @@ float expf(float x)
 	hx &= 0x7fffffff;  /* high word of |x| */
 
 	/* special cases */
-	if (hx >= 0x42b17218) {  /* if |x| >= 88.722839f or NaN */
-		if (hx > 0x7f800000)  /* NaN */
-			return x;
-		if (!sign) {
-			/* overflow if x!=inf */
+	if (hx >= 0x42aeac50) {  /* if |x| >= -87.33655f or NaN */
+		if (hx >= 0x42b17218 && !sign) {  /* x >= 88.722839f */
+			/* overflow */
 			STRICT_ASSIGN(float, x, x * 0x1p127f);
 			return x;
 		}
-		if (hx == 0x7f800000)  /* -inf */
-			return 0;
-		if (hx >= 0x42cff1b5) { /* x <= -103.972084f */
+		if (sign) {
 			/* underflow */
-			STRICT_ASSIGN(float, x, 0x1p-100f*0x1p-100f);
-			return x;
+			FORCE_EVAL(-0x1p-149f/x);
+			if (hx >= 0x42cff1b5)  /* x <= -103.972084f */
+				return 0;
 		}
 	}
 
@@ -77,8 +74,8 @@ float expf(float x)
 	/* x is now in primary range */
 	xx = x*x;
 	c = x - xx*(P1+xx*P2);
-	x = 1 + (x*c/(2-c) - lo + hi);
+	y = 1 + (x*c/(2-c) - lo + hi);
 	if (k == 0)
-		return x;
-	return scalbnf(x, k);
+		return y;
+	return scalbnf(y, k);
 }