Bug 43345

Summary: ilogb(INFINITY) returns incorrect value
Product: [Retired] Red Hat Linux Reporter: Trevin Beattie <trevin>
Component: libcAssignee: Jakub Jelinek <jakub>
Status: CLOSED RAWHIDE QA Contact:
Severity: low Docs Contact:
Priority: low    
Version: 7.1   
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2001-06-05 07:56:31 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Trevin Beattie 2001-06-03 14:44:16 UTC
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

Comment 2 Jakub Jelinek 2001-06-07 13:17:34 UTC
Included in glibc-2.2.3-11.