This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Correct calculation of subnormal exponent in fmod and ilogb


All the fmod and ilogb implementations rely on undefined behaviour
(arithmethic shift into sign bit) when calculating the exponent of a
denormal number.

Andreas.

	* math/libm-test.inc (ilogb_test): Add tests for denormal numbers.
	* sysdeps/ieee754/dbl-64/e_fmod.c (__ieee754_fmod): Declare hx,
	hy, sx as unsigned.  Use __builtin_clz to calculate exponent of
	subnormal number.
	* sysdeps/ieee754/dbl-64/e_ilogb.c (__ieee754_ilogb): Likewise.
	* sysdeps/ieee754/dbl-64/wordsize-64/e_fmod.c (__ieee754_fmod):
	Likewise.
	* sysdeps/ieee754/flt-32/e_fmodf.c (__ieee754_fmodf): Likewise.
	* sysdeps/ieee754/flt-32/e_ilogbf.c (__ieee754_ilogbf): Likewise.
	* sysdeps/ieee754/ldbl-128/e_fmodl.c (__ieee754_fmodl): Likewise.
	* sysdeps/ieee754/ldbl-128/e_ilogbl.c (__ieee754_ilogbl):
	Likewise.
	* sysdeps/ieee754/ldbl-128ibm/e_fmodl.c (__ieee754_fmodl):
	Likewise.
	* sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c (__ieee754_ilogbl):
	Likewise.
	* sysdeps/ieee754/ldbl-96/e_ilogbl.c (__ieee754_ilogbl): Likewise.
---
 math/libm-test.inc                          |   16 ++++++++++++++++
 sysdeps/ieee754/dbl-64/e_fmod.c             |   22 ++++++++++++----------
 sysdeps/ieee754/dbl-64/e_ilogb.c            |   10 +++++++---
 sysdeps/ieee754/dbl-64/wordsize-64/e_fmod.c |   13 +++++++------
 sysdeps/ieee754/flt-32/e_fmodf.c            |   13 +++++++------
 sysdeps/ieee754/flt-32/e_ilogbf.c           |    5 +++--
 sysdeps/ieee754/ldbl-128/e_fmodl.c          |   20 +++++++++++---------
 sysdeps/ieee754/ldbl-128/e_ilogbl.c         |    9 ++++++---
 sysdeps/ieee754/ldbl-128ibm/e_fmodl.c       |   22 +++++++---------------
 sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c      |    8 ++------
 sysdeps/ieee754/ldbl-96/e_ilogbl.c          |   10 +++++++---
 11 files changed, 85 insertions(+), 63 deletions(-)

diff --git a/math/libm-test.inc b/math/libm-test.inc
index 2b2ca32..c81ecd9 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -4284,6 +4284,22 @@ ilogb_test (void)
   TEST_f_i (ilogb, minus_infty, INT_MAX, INVALID_EXCEPTION);
   check_int ("errno for ilogb(-Inf) unchanged", errno, EDOM, 0, 0, 0);
 
+  TEST_f_i (ilogb, 0x0.1p-127, -131);
+  TEST_f_i (ilogb, 0x0.01p-127, -135);
+  TEST_f_i (ilogb, 0x0.011p-127, -135);
+#ifndef TEST_FLOAT
+  TEST_f_i (ilogb, 0x0.8p-1022, -1023);
+  TEST_f_i (ilogb, 0x0.1p-1022, -1026);
+  TEST_f_i (ilogb, 0x0.00111p-1022, -1034);
+  TEST_f_i (ilogb, 0x0.00001p-1022, -1042);
+  TEST_f_i (ilogb, 0x0.000011p-1022, -1042);
+  TEST_f_i (ilogb, 0x0.0000000000001p-1022, -1074);
+#endif
+#if defined TEST_LDOUBLE && LDBL_MIN_EXP - LDBL_MANT_DIG <= -16400
+  TEST_f_i (ilogb, 0x1p-16400L, -16400);
+  TEST_f_i (ilogb, 0x.00000000001p-16382L, -16426);
+#endif
+
   END (ilogb);
 }
 
diff --git a/sysdeps/ieee754/dbl-64/e_fmod.c b/sysdeps/ieee754/dbl-64/e_fmod.c
index b8548fa..a225085 100644
--- a/sysdeps/ieee754/dbl-64/e_fmod.c
+++ b/sysdeps/ieee754/dbl-64/e_fmod.c
@@ -23,8 +23,8 @@ static const double one = 1.0, Zero[] = {0.0, -0.0,};
 double
 __ieee754_fmod (double x, double y)
 {
-	int32_t n,hx,hy,hz,ix,iy,sx,i;
-	u_int32_t lx,ly,lz;
+	int32_t n,hz,ix,iy;
+	uint32_t hx,hy,lx,ly,lz,sx;
 
 	EXTRACT_WORDS(hx,lx,x);
 	EXTRACT_WORDS(hy,ly,y);
@@ -39,24 +39,26 @@ __ieee754_fmod (double x, double y)
 	if(hx<=hy) {
 	    if((hx<hy)||(lx<ly)) return x;	/* |x|<|y| return x */
 	    if(lx==ly)
-		return Zero[(u_int32_t)sx>>31];	/* |x|=|y| return x*0*/
+		return Zero[sx>>31];	/* |x|=|y| return x*0*/
 	}
 
     /* determine ix = ilogb(x) */
 	if(__builtin_expect(hx<0x00100000, 0)) {	/* subnormal x */
+	    ix = -1022;
 	    if(hx==0) {
-		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+		ix -= __builtin_clz (lx) + 21;
 	    } else {
-		for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+		ix -= __builtin_clz (hx << 11);
 	    }
 	} else ix = (hx>>20)-1023;
 
     /* determine iy = ilogb(y) */
 	if(__builtin_expect(hy<0x00100000, 0)) {	/* subnormal y */
+	    iy = -1022;
 	    if(hy==0) {
-		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+		iy -= __builtin_clz (ly) + 21;
 	    } else {
-		for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+		iy -= __builtin_clz (hy << 11);
 	    }
 	} else iy = (hy>>20)-1023;
 
@@ -93,7 +95,7 @@ __ieee754_fmod (double x, double y)
 	    if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
 	    else {
 		if((hz|lz)==0)		/* return sign(x)*0 */
-		    return Zero[(u_int32_t)sx>>31];
+		    return Zero[sx>>31];
 		hx = hz+hz+(lz>>31); lx = lz+lz;
 	    }
 	}
@@ -102,7 +104,7 @@ __ieee754_fmod (double x, double y)
 
     /* convert back to floating value and restore the sign */
 	if((hx|lx)==0)			/* return sign(x)*0 */
-	    return Zero[(u_int32_t)sx>>31];
+	    return Zero[sx>>31];
 	while(hx<0x00100000) {		/* normalize x */
 	    hx = hx+hx+(lx>>31); lx = lx+lx;
 	    iy -= 1;
@@ -113,7 +115,7 @@ __ieee754_fmod (double x, double y)
 	} else {		/* subnormal output */
 	    n = -1022 - iy;
 	    if(n<=20) {
-		lx = (lx>>n)|((u_int32_t)hx<<(32-n));
+		lx = (lx>>n)|(hx<<(32-n));
 		hx >>= n;
 	    } else if (n<=31) {
 		lx = (hx<<(32-n))|(lx>>n); hx = sx;
diff --git a/sysdeps/ieee754/dbl-64/e_ilogb.c b/sysdeps/ieee754/dbl-64/e_ilogb.c
index 0452a71..a2fa90d 100644
--- a/sysdeps/ieee754/dbl-64/e_ilogb.c
+++ b/sysdeps/ieee754/dbl-64/e_ilogb.c
@@ -27,7 +27,8 @@ static char rcsid[] = "$NetBSD: s_ilogb.c,v 1.9 1995/05/10 20:47:28 jtc Exp $";
 
 int __ieee754_ilogb(double x)
 {
-	int32_t hx,lx,ix;
+	int32_t ix;
+	uint32_t hx,lx;
 
 	GET_HIGH_WORD(hx,x);
 	hx &= 0x7fffffff;
@@ -36,11 +37,14 @@ int __ieee754_ilogb(double x)
 	    if((hx|lx)==0)
 		return FP_ILOGB0;	/* ilogb(0) = FP_ILOGB0 */
 	    else			/* subnormal x */
+	      {
+		ix = -1022;
 		if(hx==0) {
-		    for (ix = -1043; lx>0; lx<<=1) ix -=1;
+		    ix -= __builtin_clz (lx) + 21;
 		} else {
-		    for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1;
+		    ix -= __builtin_clz (hx << 11);
 		}
+	      }
 	    return ix;
 	}
 	else if (hx<0x7ff00000) return (hx>>20)-1023;
diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/e_fmod.c b/sysdeps/ieee754/dbl-64/wordsize-64/e_fmod.c
index a630d10..540cce3 100644
--- a/sysdeps/ieee754/dbl-64/wordsize-64/e_fmod.c
+++ b/sysdeps/ieee754/dbl-64/wordsize-64/e_fmod.c
@@ -25,7 +25,8 @@ double
 __ieee754_fmod (double x, double y)
 {
 	int32_t n,ix,iy;
-	int64_t hx,hy,hz,sx,i;
+	int64_t hz;
+	uint64_t hx,hy,sx;
 
 	EXTRACT_WORDS64(hx,x);
 	EXTRACT_WORDS64(hy,y);
@@ -41,18 +42,18 @@ __ieee754_fmod (double x, double y)
 	    return (x*y)/(x*y);
 	if(__builtin_expect(hx<=hy, 0)) {
 	    if(hx<hy) return x;	/* |x|<|y| return x */
-	    return Zero[(uint64_t)sx>>63];	/* |x|=|y| return x*0*/
+	    return Zero[sx>>63];	/* |x|=|y| return x*0*/
 	}
 
     /* determine ix = ilogb(x) */
 	if(__builtin_expect(hx<UINT64_C(0x0010000000000000), 0)) {
 	  /* subnormal x */
-	  for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+	  ix = -1022 - __builtin_clzll (hx << 11);
 	} else ix = (hx>>52)-1023;
 
     /* determine iy = ilogb(y) */
 	if(__builtin_expect(hy<UINT64_C(0x0010000000000000), 0)) {	/* subnormal y */
-	  for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+	  iy = -1022 - __builtin_clzll (hy << 11);
 	} else iy = (hy>>52)-1023;
 
     /* set up hx, hy and align y to x */
@@ -76,7 +77,7 @@ __ieee754_fmod (double x, double y)
 	    if(hz<0){hx = hx+hx;}
 	    else {
 		if(hz==0)		/* return sign(x)*0 */
-		    return Zero[(uint64_t)sx>>63];
+		    return Zero[sx>>63];
 		hx = hz+hz;
 	    }
 	}
@@ -85,7 +86,7 @@ __ieee754_fmod (double x, double y)
 
     /* convert back to floating value and restore the sign */
 	if(hx==0)			/* return sign(x)*0 */
-	    return Zero[(uint64_t)sx>>63];
+	    return Zero[sx>>63];
 	while(hx<UINT64_C(0x0010000000000000)) {	/* normalize x */
 	    hx = hx+hx;
 	    iy -= 1;
diff --git a/sysdeps/ieee754/flt-32/e_fmodf.c b/sysdeps/ieee754/flt-32/e_fmodf.c
index 8d8fad4..eac6797 100644
--- a/sysdeps/ieee754/flt-32/e_fmodf.c
+++ b/sysdeps/ieee754/flt-32/e_fmodf.c
@@ -27,7 +27,8 @@ static const float one = 1.0, Zero[] = {0.0, -0.0,};
 float
 __ieee754_fmodf (float x, float y)
 {
-	int32_t n,hx,hy,hz,ix,iy,sx,i;
+	int32_t n,hz,ix,iy;
+	uint32_t hx,hy,sx;
 
 	GET_FLOAT_WORD(hx,x);
 	GET_FLOAT_WORD(hy,y);
@@ -41,16 +42,16 @@ __ieee754_fmodf (float x, float y)
 	    return (x*y)/(x*y);
 	if(hx<hy) return x;			/* |x|<|y| return x */
 	if(hx==hy)
-	    return Zero[(u_int32_t)sx>>31];	/* |x|=|y| return x*0*/
+	    return Zero[sx>>31];	/* |x|=|y| return x*0*/
 
     /* determine ix = ilogb(x) */
 	if(hx<0x00800000) {	/* subnormal x */
-	    for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+	    ix = -126 - __builtin_clz (hx << 8);
 	} else ix = (hx>>23)-127;
 
     /* determine iy = ilogb(y) */
 	if(hy<0x00800000) {	/* subnormal y */
-	    for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
+	    iy = -126 - __builtin_clz (hy << 8);
 	} else iy = (hy>>23)-127;
 
     /* set up {hx,lx}, {hy,ly} and align y to x */
@@ -74,7 +75,7 @@ __ieee754_fmodf (float x, float y)
 	    if(hz<0){hx = hx+hx;}
 	    else {
 		if(hz==0)		/* return sign(x)*0 */
-		    return Zero[(u_int32_t)sx>>31];
+		    return Zero[sx>>31];
 		hx = hz+hz;
 	    }
 	}
@@ -83,7 +84,7 @@ __ieee754_fmodf (float x, float y)
 
     /* convert back to floating value and restore the sign */
 	if(hx==0)			/* return sign(x)*0 */
-	    return Zero[(u_int32_t)sx>>31];
+	    return Zero[sx>>31];
 	while(hx<0x00800000) {		/* normalize x */
 	    hx = hx+hx;
 	    iy -= 1;
diff --git a/sysdeps/ieee754/flt-32/e_ilogbf.c b/sysdeps/ieee754/flt-32/e_ilogbf.c
index 1ae344e..95e8b3f 100644
--- a/sysdeps/ieee754/flt-32/e_ilogbf.c
+++ b/sysdeps/ieee754/flt-32/e_ilogbf.c
@@ -23,7 +23,8 @@ static char rcsid[] = "$NetBSD: s_ilogbf.c,v 1.4 1995/05/10 20:47:31 jtc Exp $";
 
 int __ieee754_ilogbf(float x)
 {
-	int32_t hx,ix;
+	int32_t ix;
+	uint32_t hx;
 
 	GET_FLOAT_WORD(hx,x);
 	hx &= 0x7fffffff;
@@ -31,7 +32,7 @@ int __ieee754_ilogbf(float x)
 	    if(hx==0)
 		return FP_ILOGB0;	/* ilogb(0) = FP_ILOGB0 */
 	    else			/* subnormal x */
-	        for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
+		ix = -126 - __builtin_clz (hx << 8);
 	    return ix;
 	}
 	else if (hx<0x7f800000) return (hx>>23)-127;
diff --git a/sysdeps/ieee754/ldbl-128/e_fmodl.c b/sysdeps/ieee754/ldbl-128/e_fmodl.c
index 3328003..48c8c81 100644
--- a/sysdeps/ieee754/ldbl-128/e_fmodl.c
+++ b/sysdeps/ieee754/ldbl-128/e_fmodl.c
@@ -26,8 +26,8 @@ static const long double one = 1.0, Zero[] = {0.0, -0.0,};
 long double
 __ieee754_fmodl (long double x, long double y)
 {
-	int64_t n,hx,hy,hz,ix,iy,sx,i;
-	u_int64_t lx,ly,lz;
+	int64_t n,hz,ix,iy;
+	u_int64_t hx,hy,lx,ly,lz,sx;
 
 	GET_LDOUBLE_WORDS64(hx,lx,x);
 	GET_LDOUBLE_WORDS64(hy,ly,y);
@@ -42,24 +42,26 @@ __ieee754_fmodl (long double x, long double y)
 	if(hx<=hy) {
 	    if((hx<hy)||(lx<ly)) return x;	/* |x|<|y| return x */
 	    if(lx==ly)
-		return Zero[(u_int64_t)sx>>63];	/* |x|=|y| return x*0*/
+		return Zero[sx>>63];	/* |x|=|y| return x*0*/
 	}
 
     /* determine ix = ilogb(x) */
 	if(hx<0x0001000000000000LL) {	/* subnormal x */
+	    ix = -16382;
 	    if(hx==0) {
-		for (ix = -16431, i=lx; i>0; i<<=1) ix -=1;
+		ix -= __builtin_clzll (lx) + 49;
 	    } else {
-		for (ix = -16382, i=hx<<15; i>0; i<<=1) ix -=1;
+		ix -= __builtin_clzll (hx << 15);
 	    }
 	} else ix = (hx>>48)-0x3fff;
 
     /* determine iy = ilogb(y) */
 	if(hy<0x0001000000000000LL) {	/* subnormal y */
+	    iy = -16382;
 	    if(hy==0) {
-		for (iy = -16431, i=ly; i>0; i<<=1) iy -=1;
+		iy -= __builtin_clzll (ly) + 49;
 	    } else {
-		for (iy = -16382, i=hy<<15; i>0; i<<=1) iy -=1;
+		iy -= __builtin_clzll (hy << 15);
 	    }
 	} else iy = (hy>>48)-0x3fff;
 
@@ -96,7 +98,7 @@ __ieee754_fmodl (long double x, long double y)
 	    if(hz<0){hx = hx+hx+(lx>>63); lx = lx+lx;}
 	    else {
 		if((hz|lz)==0)		/* return sign(x)*0 */
-		    return Zero[(u_int64_t)sx>>63];
+		    return Zero[sx>>63];
 		hx = hz+hz+(lz>>63); lx = lz+lz;
 	    }
 	}
@@ -105,7 +107,7 @@ __ieee754_fmodl (long double x, long double y)
 
     /* convert back to floating value and restore the sign */
 	if((hx|lx)==0)			/* return sign(x)*0 */
-	    return Zero[(u_int64_t)sx>>63];
+	    return Zero[sx>>63];
 	while(hx<0x0001000000000000LL) {	/* normalize x */
 	    hx = hx+hx+(lx>>63); lx = lx+lx;
 	    iy -= 1;
diff --git a/sysdeps/ieee754/ldbl-128/e_ilogbl.c b/sysdeps/ieee754/ldbl-128/e_ilogbl.c
index 0a47649..854b2c5 100644
--- a/sysdeps/ieee754/ldbl-128/e_ilogbl.c
+++ b/sysdeps/ieee754/ldbl-128/e_ilogbl.c
@@ -30,7 +30,7 @@ static char rcsid[] = "$NetBSD: $";
 
 int __ieee754_ilogbl (long double x)
 {
-	int64_t hx,lx;
+	uint64_t hx,lx;
 	int ix;
 
 	GET_LDOUBLE_WORDS64(hx,lx,x);
@@ -39,11 +39,14 @@ int __ieee754_ilogbl (long double x)
 	    if((hx|lx)==0)
 		return FP_ILOGB0;	/* ilogbl(0) = FP_ILOGB0 */
 	    else			/* subnormal x */
+	      {
+		ix = -16382;
 		if(hx==0) {
-		    for (ix = -16431; lx>0; lx<<=1) ix -=1;
+		    ix -= __builtin_clzll (lx) + 49;
 		} else {
-		    for (ix = -16382, hx<<=15; hx>0; hx<<=1) ix -=1;
+		    ix -= __builtin_clzll (hx << 15);
 		}
+	      }
 	    return ix;
 	}
 	else if (hx<0x7fff000000000000LL) return (hx>>48)-0x3fff;
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c b/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
index a60963c..5c48e3b 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
@@ -27,8 +27,8 @@ static const long double one = 1.0, Zero[] = {0.0, -0.0,};
 long double
 __ieee754_fmodl (long double x, long double y)
 {
-	int64_t n,hx,hy,hz,ix,iy,sx, i;
-	u_int64_t lx,ly,lz;
+	int64_t n,hz,ix,iy;
+	u_int64_t hx,hy,lx,ly,lz,sx;
 	int temp;
 
 	GET_LDOUBLE_WORDS64(hx,lx,x);
@@ -45,25 +45,17 @@ __ieee754_fmodl (long double x, long double y)
 	if(__builtin_expect(hx<=hy,0)) {
 	    if((hx<hy)||(lx<ly)) return x;	/* |x|<|y| return x */
 	    if(lx==ly)
-		return Zero[(u_int64_t)sx>>63];	/* |x|=|y| return x*0*/
+		return Zero[sx>>63];	/* |x|=|y| return x*0*/
 	}
 
     /* determine ix = ilogb(x) */
 	if(__builtin_expect(hx<0x0010000000000000LL,0)) {	/* subnormal x */
-	    if(hx==0) {
-		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
-	    } else {
-		for (ix = -1022, i=(hx<<11); i>0; i<<=1) ix -=1;
-	    }
+	    ix = -1022 - __builtin_clzll (hx << 11);
 	} else ix = (hx>>52)-0x3ff;
 
     /* determine iy = ilogb(y) */
 	if(__builtin_expect(hy<0x0010000000000000LL,0)) {	/* subnormal y */
-	    if(hy==0) {
-		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
-	    } else {
-		for (iy = -1022, i=(hy<<11); i>0; i<<=1) iy -=1;
-	    }
+	    iy = -1022 - __builtin_clzll (hy << 11);
 	} else iy = (hy>>52)-0x3ff;
 
     /* Make the IBM extended format 105 bit mantissa look like the ieee854 112
@@ -105,7 +97,7 @@ __ieee754_fmodl (long double x, long double y)
 	    if(hz<0){hx = hx+hx+(lx>>63); lx = lx+lx;}
 	    else {
 		if((hz|(lz&0x7fffffffffffffff))==0)		/* return sign(x)*0 */
-		    return Zero[(u_int64_t)sx>>63];
+		    return Zero[sx>>63];
 		hx = hz+hz+(lz>>63); lx = lz+lz;
 	    }
 	}
@@ -114,7 +106,7 @@ __ieee754_fmodl (long double x, long double y)
 
     /* convert back to floating value and restore the sign */
 	if((hx|(lx&0x7fffffffffffffff))==0)			/* return sign(x)*0 */
-	    return Zero[(u_int64_t)sx>>63];
+	    return Zero[sx>>63];
 	while(hx<0x0001000000000000LL) {	/* normalize x */
 	    hx = hx+hx+(lx>>63); lx = lx+lx;
 	    iy -= 1;
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c b/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
index 55f87ed..8d42911 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
@@ -31,7 +31,7 @@ static char rcsid[] = "$NetBSD: $";
 
 int __ieee754_ilogbl(long double x)
 {
-	int64_t hx,lx;
+	uint64_t hx,lx;
 	int ix;
 
 	GET_LDOUBLE_WORDS64(hx,lx,x);
@@ -40,11 +40,7 @@ int __ieee754_ilogbl(long double x)
 	    if((hx|(lx&0x7fffffffffffffffLL))==0)
 		return FP_ILOGB0;	/* ilogbl(0) = FP_ILOGB0 */
 	    else			/* subnormal x */
-		if(hx==0) {
-		    for (ix = -1043; lx>0; lx<<=1) ix -=1;
-		} else {
-		    for (ix = -1022, hx<<=11; hx>0; hx<<=1) ix -=1;
-		}
+		ix = -1022 - __builtin_clzll (hx << 11);
 	    return ix;
 	}
 	else if (hx<0x7ff0000000000000LL) return (hx>>52)-0x3ff;
diff --git a/sysdeps/ieee754/ldbl-96/e_ilogbl.c b/sysdeps/ieee754/ldbl-96/e_ilogbl.c
index 0c7d9d5..41cd8b1 100644
--- a/sysdeps/ieee754/ldbl-96/e_ilogbl.c
+++ b/sysdeps/ieee754/ldbl-96/e_ilogbl.c
@@ -31,7 +31,8 @@ static char rcsid[] = "$NetBSD: $";
 
 int __ieee754_ilogbl (long double x)
 {
-	int32_t es,hx,lx,ix;
+	int32_t es,ix;
+	uint32_t hx,lx;
 
 	GET_LDOUBLE_EXP(es,x);
 	es &= 0x7fff;
@@ -40,11 +41,14 @@ int __ieee754_ilogbl (long double x)
 	    if((hx|lx)==0)
 		return FP_ILOGB0;	/* ilogbl(0) = FP_ILOGB0 */
 	    else			/* subnormal x */
+	      {
+		ix = -16383;
 		if(hx==0) {
-		    for (ix = -16415; lx>0; lx<<=1) ix -=1;
+		    ix -= __builtin_clz (lx) + 32;
 		} else {
-		    for (ix = -16383; hx>0; hx<<=1) ix -=1;
+		    ix -= __builtin_clz (hx);
 		}
+	      }
 	    return ix;
 	}
 	else if (es<0x7fff) return es-0x3fff;
-- 
1.7.10.4


-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]