diff options
| author | Szabolcs Nagy <nsz@port70.net> | 2013-08-15 15:13:24 +0000 | 
|---|---|---|
| committer | Szabolcs Nagy <nsz@port70.net> | 2013-08-15 15:13:24 +0000 | 
| commit | c221af951693d526d3ae946f7e708af8e7a9bf85 (patch) | |
| tree | 0d18e9fdd8cf637d98c9726ff5947d6d8b41f851 | |
| parent | 411efb3bc61298b81456d0fdab39518d983a9681 (diff) | |
| download | musl-c221af951693d526d3ae946f7e708af8e7a9bf85.tar.gz | |
math: fix pow(x,-1) to raise underflow properly
if FLT_EVAL_METHOD!=0 check if (double)(1/x) is subnormal and not a
power of 2 (if 1/x is power of 2 then either it is exact or the
long double to double rounding already raised inexact and underflow)
| -rw-r--r-- | src/math/pow.c | 16 | 
1 files changed, 14 insertions, 2 deletions
| diff --git a/src/math/pow.c b/src/math/pow.c index ac3abc0f..82f684bd 100644 --- a/src/math/pow.c +++ b/src/math/pow.c @@ -146,8 +146,20 @@ double pow(double x, double y)  			else if ((ix|lx) != 0)     /* (|x|<1)**+-inf = 0,inf if x!=0 */  				return hy >= 0 ? 0.0 : -y;  		} -		if (iy == 0x3ff00000)    /* y is +-1 */ -			return hy >= 0 ? x : 1.0/x; +		if (iy == 0x3ff00000) {    /* y is +-1 */ +			if (hy >= 0) +				return x; +			y = 1/x; +#if FLT_EVAL_METHOD!=0 +			{ +				union {double f; uint64_t i;} u = {y}; +				uint64_t i = u.i & -1ULL/2; +				if (i>>52 == 0 && (i&(i-1))) +					FORCE_EVAL((float)y); +			} +#endif +			return y; +		}  		if (hy == 0x40000000)    /* y is 2 */  			return x*x;  		if (hy == 0x3fe00000) {  /* y is 0.5 */ | 
