From Bugzilla Helper: User-Agent: Mozilla/4.77 [en] (X11; U; Linux 2.4.2-2 i586) Description of problem: The ilogb function in glibc apparently returns FP_ILOGBNAN for both INFINITY and NAN. On the i386 port, this value is equal to INT_MIN, but ilogb(INFINITY) is supposed to return INT_MAX. (On other architectures, FP_ILOGBNAN is equal to INT_MAX, so it doesn't matter.) This affects both the generic C and i386-specific assembly language sources. How reproducible: Always Steps to Reproduce: Compile and run the following code (don't forget -lm): #include <limits.h> #define __USE_ISOC99 1 #include <math.h> #include <stdio.h> main () { if (ilogb (INFINITY) == INT_MAX) { printf ("ilogb(INFINITY) is correct.\n"); return 0; } else { printf ("ilogb(INFINITY) returned %d; should be %d.\n", ilogb (INFINITY), INT_MAX); return 1; } } Actual Results: ilogb(INFINITY) returned -2147483648; should be 2147483647. Expected Results: ilogb(INFINITY) is correct. Additional info: This is a requirement of ISO C99, as found in WG14/N869 (7.12.6.5); it may be a new addition since the C90 standard. The draft standard reads: 2 "The ilogb functions extract the exponent of x as a signed int value. If x is zero they compute the value FP_ILOGB0; if x is infinite they compute the value INT_MAX; if x is a NaN they compute the value FP_ILOGBNAN; otherwise, they are equivalent to calling the corresponding logb function and casting the returned value to type int. A range error may occur if x is 0." Suggested patch: Something like the following should work: diff -c glibc-2.2.3/sysdeps/ieee754/dbl-64/s_ilogb.c.orig glibc-2.2.3/sysdeps/ieee754/dbl-64/s_ilogb.c *** glibc-2.2.3/sysdeps/ieee754/dbl-64/s_ilogb.c.orig Tue Jul 13 16:52:14 1999--- glibc-2.2.3/sysdeps/ieee754/dbl-64/s_ilogb.c Sun Jun 3 07:38:16 2001*************** *** 20,25 **** --- 20,26 ---- * ilogb(inf/NaN) = 0x7fffffff (no signal is raised) */ + #include "limits.h" #include "math.h" #include "math_private.h" *************** *** 47,53 **** return ix; } else if (hx<0x7ff00000) return (hx>>20)-1023; ! else return FP_ILOGBNAN; } weak_alias (__ilogb, ilogb) #ifdef NO_LONG_DOUBLE --- 48,59 ---- return ix; } else if (hx<0x7ff00000) return (hx>>20)-1023; ! else { ! GET_LOW_WORD(lx,x); ! if((hx==0x7ff00000)&&(lx==0)) ! return INT_MAX; ! else return FP_ILOGBNAN; ! } } weak_alias (__ilogb, ilogb) #ifdef NO_LONG_DOUBLE diff -c glibc-2.2.3/sysdeps/i386/fpu/s_ilogb.S.orig glibc-2.2.3/sysdeps/i386/fpu/s_ilogb.S *** glibc-2.2.3/sysdeps/i386/fpu/s_ilogb.S.orig Tue Jul 13 16:34:41 1999 --- glibc-2.2.3/sysdeps/i386/fpu/s_ilogb.S Sun Jun 3 07:45:08 2001 *************** *** 9,15 **** ENTRY(__ilogb) fldl 4(%esp) ! fxtract pushl %eax fstp %st --- 9,24 ---- ENTRY(__ilogb) fldl 4(%esp) ! fxam ! fnstsw ! andb $69, %ah ! cmpb $5, %ah ! jne 1f ! fstp %st(0) ! movl $0x7fffffff, %eax ! ret ! ! 1: fxtract pushl %eax fstp %st
See http://sources.redhat.com/ml/libc-hacker/2001-06/msg00004.html
Included in glibc-2.2.3-11.