Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 May 2004 21:47:51 +0200
From:      Stefan Farfeleder <stefanf@FreeBSD.org>
To:        freebsd-standards@FreeBSD.org
Subject:   Fixing ilogb()
Message-ID:  <20040508194748.GN29712@wombat.fafoe.narf.at>

next in thread | raw e-mail | index | archive | help

--y96v7rNg6HAoELs5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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

--y96v7rNg6HAoELs5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="c99-ilogb.txt"

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.

--y96v7rNg6HAoELs5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ilogb.diff"

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

--y96v7rNg6HAoELs5--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040508194748.GN29712>