# Fixing ilogb()

Stefan Farfeleder stefanf at FreeBSD.org
Sat May 8 12:48:04 PDT 2004

```Hi,

I found two problems with our current ilogb() implemenation(s).

- Both the man page and FP_ILOGB0 claim that ilogb(0) returns INT_MIN
while the implementation in s_ilogb.c returns -INT_MAX.  We really
have to decide on one value (both are conforming to C99, I've attached
the text).  The attached patch assumes that -INT_MAX is kept.

On a related note, is there a reason why <math.h> doesn't use
<machine/_limit.h>'s __INT_M{AX,IN} for the FP_ILOGB* macros?

- On i386 the assembler file s_ilogb.S is used instead.  It uses the
instruction fxtract which returns INT_MIN for 0, infinity and NaN.
Except for infinity this conforms too, but doesn't play well with our
MI definitions for FP_ILOGB*.  In the attached patch I've aligned
s_ilogb.S's behaviour with s_ilogb.c, the alternative would be just
fixing infinity and making FP_ILOGB* MD.

Opinions?

Cheers,
Stefan
-------------- next part --------------
7.12 Mathematics <math.h>

8 The macros
FP_ILOGB0
FP_ILOGBNAN
expand to integer constant expressions whose values are returned by ilogb(x) if x is
zero or NaN, respectively. The value of FP_ILOGB0 shall be either INT_MIN or
-INT_MAX. The value of FP_ILOGBNAN shall be either INT_MAX or INT_MIN.

7.12.6.5 The ilogb functions
Synopsis
1        #include <math.h>
int ilogb(double x);
int ilogbf(float x);
int ilogbl(long double x);
Description
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.
-------------- next part --------------
Index: src/lib/msun/i387/s_ilogb.S
===================================================================
RCS file: /usr/home/ncvs/src/lib/msun/i387/s_ilogb.S,v
retrieving revision 1.8
diff -u -r1.8 s_ilogb.S
--- src/lib/msun/i387/s_ilogb.S	6 Jun 2000 12:12:36 -0000	1.8
+++ src/lib/msun/i387/s_ilogb.S	8 May 2004 18:57:27 -0000
@@ -43,11 +43,27 @@
subl	\$4,%esp

fldl	8(%ebp)
+	fxam
+	fnstsw	%ax
+	sahf
+	jc .L2
+	jnp .L3
+
fxtract
fstp	%st

fistpl	-4(%ebp)
movl	-4(%ebp),%eax
-
+.L1:
leave
ret
+
+.L2:
+	/* Depending on ilogb(NAN) == ilogb(INFINITY) */
+	movl	\$0x7fffffff,%eax	/* FP_ILOGBNAN, INT_MAX */
+	fstp	%st
+	jmp .L1
+.L3:
+	movl	\$0x80000001,%eax	/* FP_ILOGB0 */
+	fstp	%st
+	jmp .L1
Index: src/lib/msun/man/ieee.3
===================================================================
RCS file: /usr/home/ncvs/src/lib/msun/man/ieee.3,v
retrieving revision 1.13
diff -u -r1.13 ieee.3
--- src/lib/msun/man/ieee.3	7 May 2004 18:56:31 -0000	1.13
+++ src/lib/msun/man/ieee.3	8 May 2004 18:48:29 -0000
@@ -116,11 +116,14 @@
in integer format.
.Fn ilogb \*(Pm\*(If
returns
-.Dv INT_MAX
+.Dv INT_MAX ,
+.Fn ilogb \*(Pm\*(Na
+returns
+.Dv FP_ILOGBNAN
and
.Fn ilogb 0
returns
-.Dv INT_MIN .
+.Dv FP_ILOGB0 .
.Pp
.Fn nextafter
and
Index: src/lib/msun/src/math.h
===================================================================
RCS file: /usr/home/ncvs/src/lib/msun/src/math.h,v
retrieving revision 1.32
diff -u -r1.32 math.h
--- src/lib/msun/src/math.h	7 May 2004 18:56:31 -0000	1.32
+++ src/lib/msun/src/math.h	8 May 2004 18:45:25 -0000
@@ -35,7 +35,7 @@
#define	HUGE_VAL	(__infinity.__ud)

#if __ISO_C_VISIBLE >= 1999
-#define	FP_ILOGB0	(-0x7fffffff - 1)	/* INT_MIN */
+#define	FP_ILOGB0	(-0x7fffffff)		/* -INT_MAX */
#define	FP_ILOGBNAN	0x7fffffff		/* INT_MAX */
#define	HUGE_VALF	(float)HUGE_VAL
#define	HUGE_VALL	(long double)HUGE_VAL
```