diff options
| author | Szabolcs Nagy <nsz@port70.net> | 2013-09-02 23:33:20 +0000 | 
|---|---|---|
| committer | Szabolcs Nagy <nsz@port70.net> | 2013-09-05 11:30:07 +0000 | 
| commit | 4cec31fc23b28271a2ed0b290e65699dffac3fee (patch) | |
| tree | 82d7775f198079ec26ecc35eba4aa7e7d32b6c36 | |
| parent | af5f6d9556441487e5c66a7a4cfeddf4ed354aa7 (diff) | |
| download | musl-4cec31fc23b28271a2ed0b290e65699dffac3fee.tar.gz | |
math: ilogb cleanup
* consistent code style
* explicit union instead of typedef for double and float bit access
* turn FENV_ACCESS ON to make 0/0.0f raise invalid flag
* (untested) ld128 version of ilogbl (used by logbl which has ld128 support)
| -rw-r--r-- | src/math/ilogb.c | 14 | ||||
| -rw-r--r-- | src/math/ilogbf.c | 14 | ||||
| -rw-r--r-- | src/math/ilogbl.c | 31 | 
3 files changed, 43 insertions, 16 deletions
| diff --git a/src/math/ilogb.c b/src/math/ilogb.c index 5a1819d8..64d40154 100644 --- a/src/math/ilogb.c +++ b/src/math/ilogb.c @@ -3,22 +3,24 @@  int ilogb(double x)  { -	union dshape u = {x}; -	int e = u.bits>>52 & 0x7ff; +	#pragma STDC FENV_ACCESS ON +	union {double f; uint64_t i;} u = {x}; +	uint64_t i = u.i; +	int e = i>>52 & 0x7ff;  	if (!e) { -		u.bits <<= 12; -		if (u.bits == 0) { +		i <<= 12; +		if (i == 0) {  			FORCE_EVAL(0/0.0f);  			return FP_ILOGB0;  		}  		/* subnormal x */ -		for (e = -0x3ff; u.bits < (uint64_t)1<<63; e--, u.bits<<=1); +		for (e = -0x3ff; i>>63 == 0; e--, i<<=1);  		return e;  	}  	if (e == 0x7ff) {  		FORCE_EVAL(0/0.0f); -		return u.bits<<12 ? FP_ILOGBNAN : INT_MAX; +		return i<<12 ? FP_ILOGBNAN : INT_MAX;  	}  	return e - 0x3ff;  } diff --git a/src/math/ilogbf.c b/src/math/ilogbf.c index 42cd62e2..e23ba209 100644 --- a/src/math/ilogbf.c +++ b/src/math/ilogbf.c @@ -3,22 +3,24 @@  int ilogbf(float x)  { -	union fshape u = {x}; -	int e = u.bits>>23 & 0xff; +	#pragma STDC FENV_ACCESS ON +	union {float f; uint32_t i;} u = {x}; +	uint32_t i = u.i; +	int e = i>>23 & 0xff;  	if (!e) { -		u.bits <<= 9; -		if (u.bits == 0) { +		i <<= 9; +		if (i == 0) {  			FORCE_EVAL(0/0.0f);  			return FP_ILOGB0;  		}  		/* subnormal x */ -		for (e = -0x7f; u.bits < (uint32_t)1<<31; e--, u.bits<<=1); +		for (e = -0x7f; i>>31 == 0; e--, i<<=1);  		return e;  	}  	if (e == 0xff) {  		FORCE_EVAL(0/0.0f); -		return u.bits<<9 ? FP_ILOGBNAN : INT_MAX; +		return i<<9 ? FP_ILOGBNAN : INT_MAX;  	}  	return e - 0x7f;  } diff --git a/src/math/ilogbl.c b/src/math/ilogbl.c index 7df6eb6c..7b1a9cf8 100644 --- a/src/math/ilogbl.c +++ b/src/math/ilogbl.c @@ -9,23 +9,46 @@ int ilogbl(long double x)  #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384  int ilogbl(long double x)  { +	#pragma STDC FENV_ACCESS ON  	union ldshape u = {x};  	uint64_t m = u.i.m;  	int e = u.i.se & 0x7fff;  	if (!e) {  		if (m == 0) { -			FORCE_EVAL(x/x); +			FORCE_EVAL(0/0.0f);  			return FP_ILOGB0;  		}  		/* subnormal x */ -		for (e = -0x3fff+1; m < (uint64_t)1<<63; e--, m<<=1); +		for (e = -0x3fff+1; m>>63 == 0; e--, m<<=1);  		return e;  	}  	if (e == 0x7fff) {  		FORCE_EVAL(0/0.0f); -		/* in ld80 msb is set in inf */ -		return m << 1 ? FP_ILOGBNAN : INT_MAX; +		return m<<1 ? FP_ILOGBNAN : INT_MAX; +	} +	return e - 0x3fff; +} +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 +int ilogbl(long double x) +{ +	#pragma STDC FENV_ACCESS ON +	union ldshape u = {x}; +	int e = u.i.se & 0x7fff; + +	if (!e) { +		if (x == 0) { +			FORCE_EVAL(0/0.0f); +			return FP_ILOGB0; +		} +		/* subnormal x */ +		x *= 0x1p120; +		return ilogbl(x) - 120; +	} +	if (e == 0x7fff) { +		FORCE_EVAL(0/0.0f); +		u.i.se = 0; +		return u.f ? FP_ILOGBNAN : INT_MAX;  	}  	return e - 0x3fff;  } | 
