Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 May 2002 03:10:03 -0700 (PDT)
From:      David Schultz <dschultz@uclink.Berkeley.EDU>
To:        standards@FreeBSD.org
Subject:   Re: misc/23103: <math.h> lacks many ISO C99 features (NAN, isfinite,...)
Message-ID:  <200205091010.g49AA3t98744@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR misc/23103; it has been noted by GNATS.

From: David Schultz <dschultz@uclink.Berkeley.EDU>
To: freebsd-gnats-submit@FreeBSD.org, freebsd-standards@FreeBSD.org
Cc: Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
Subject: Re: misc/23103: <math.h> lacks many ISO C99 features (NAN, isfinite,...)
Date: Thu, 9 May 2002 03:09:26 -0700

 Thus spake Gerald Pfeifer:
 > <math.h> AKA /usr/include/math.h lacks a couple of features
 > required by ISO C99. ISO compliant programs will thus fail to
 > compile; one (more or less) prominent one is Wine.
 > 
 > Features missing include macros FP_INFINITE, FP_NAN, FP_NORMAL,
 > FP_SUBNORMAL, FP_ZERO, fpclassify(), and isfinite().
 
 I've made some patches to add most of these features for i386.  The
 remaining ones are mostly trivial extensions to the ones I've already
 added.  I would just like to get some assurance that I'm on the right
 track with these changes before I go ahead and write the rest of the
 C99 stuff for all supported architectures.  Notes:
 
 - Some of the symbolic constants in math.h are architecture-dependant,
   and I don't know if anything special needs to be done about this.
   Architecture-dependent assumptions are:
     o ints are 32 bits					FP_ILOG*
     o doubles are 64-bit IEEE 754's			DECIMAL_DIG
     o `long double' is an appropriate choice for	FLT_EVAL_METHOD
       float_t and double_t
 
 - The necessary support needs to be added to libc in all architectures
   before the math.h changes can be committed.  The i386 code I wrote
   should work fine on any architecture on which floats, doubles, and
   long doubles have 32, 64, and 80 bits of precision, respectively,
   but fpclassify() can be done more efficiently on 64-bit architectures.
 
 Please CC me any responses; I'm not subscribed to -standards.
 
 Here are the patches:
 
 Index: math.h
 ===================================================================
 RCS file: /home/ncvs/src/lib/msun/src/math.h,v
 retrieving revision 1.8.2.2
 diff -u -r1.8.2.2 math.h
 --- math.h	2001/11/23 16:16:18	1.8.2.2
 +++ math.h	2002/05/09 09:35:02
 @@ -21,7 +21,39 @@
   * ANSI/POSIX
   */
  extern char __infinity[];
 +extern char __infinity_f[];
 +extern char __infinity_l[];
 +extern char __nan[];
  #define HUGE_VAL	(*(double *) __infinity)
 +#define HUGE_VALF	(*(float *) __infinity_f)
 +#define HUGE_VALL	(*(long double *) __infinity_l)
 +#define INFINITY	HUGE_VALF
 +#define NAN		(*(float *) __nan)
 +#define FP_ILOGB0	(-0x7fffffff - 1)	/* INT_MIN */
 +#define FP_ILOGBNAN	0x7fffffff		/* INT_MAX */
 +#define DECIMAL_DIG	15
 +
 +#define FLT_EVAL_METHOD	2
 +typedef long double float_t;
 +typedef long double double_t;
 +
 +/* Symbolic constants to classify floating point numbers */
 +#define FP_INFINITE	1
 +#define FP_NAN		2
 +#define FP_NORMAL	3
 +#define FP_SUBNORMAL	4
 +#define FP_ZERO		5
 +#define fpclassify(x) \
 +	((sizeof (x) == sizeof (float)) ? \
 +		__fpclassifyf(x) \
 +	: (sizeof (x) == sizeof (double)) ? \
 +		__fpclassifyd(x) \
 +	:       __fpclassifyl(x))
 +
 +/* XXX missing: C99 7.12.7 FP_FAST_FMA*
 + *     need to add or fix up isfinite(), isinf(), isnan(),
 + *                           isnormal(), signbit()
 + */
  
  /*
   * XOPEN/SVID
 Index: Makefile.inc
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/i386/gen/Makefile.inc,v
 retrieving revision 1.10.2.1
 diff -u -r1.10.2.1 Makefile.inc
 --- Makefile.inc        2001/02/07 00:12:45     1.10.2.1
 +++ Makefile.inc        2002/05/09 09:57:13
 @@ -1,5 +1,5 @@
  #      @(#)Makefile.inc        8.1 (Berkeley) 6/4/93
  # $FreeBSD: src/lib/libc/i386/gen/Makefile.inc,v 1.10.2.1 2001/02/07 00:12:45 peter Exp $
  
 -SRCS+= _setjmp.S alloca.S fabs.S frexp.c infinity.c isinf.c ldexp.c modf.S \
 -       rfork_thread.S setjmp.S sigsetjmp.S
 +SRCS+= _setjmp.S alloca.S fabs.S fpclassify.c frexp.c infinity.c isinf.c \
 +       ldexp.c modf.S rfork_thread.S setjmp.S sigsetjmp.S
 Index: infinity.c
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/i386/gen/infinity.c,v
 retrieving revision 1.5
 diff -u -u -r1.5 infinity.c
 --- infinity.c  1999/08/27 23:59:21     1.5
 +++ infinity.c  2002/05/09 09:44:05
 @@ -7,3 +7,8 @@
  
  /* bytes for +Infinity on a 387 */
  char __infinity[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
 +char __infinity_f[] = { 0, 0, 0x80, 0x7f };
 +char __infinity_l[] = { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7f, 0, 0 };
 +
 +/* bytes for NaN */
 +char __nan[] = { 0, 0, 0xc0, 0x7f };
 
 --- /dev/null	Thu May  9 02:44:57 2002
 +++ fpclassify.c	Wed May  8 06:30:05 2002
 @@ -0,0 +1,81 @@
 +/*
 + * $FreeBSD: $
 + */
 +
 +#include <sys/types.h>
 +#include <math.h>
 +
 +int
 +__fpclassifyf(f)
 +	float f;
 +{
 +	register union flt2d {
 +		float fv;
 +		u_int32_t dv;
 +	} u;
 +
 +	u.fv = f;
 +	u.dv &= 0x7fffffff;
 +	if (u.dv == 0)
 +		return FP_ZERO;
 +	else if (u.dv < 0x00800000)
 +		return FP_SUBNORMAL;
 +	else if (u.dv == 0x7f800000)
 +		return FP_INFINITE;
 +	else if (u.dv > 0x7f800000)
 +		return FP_NAN;
 +	else
 +		return FP_NORMAL;
 +}
 +
 +int
 +__fpclassifyd(d)
 +	double d;
 +{
 +	register struct IEEEdp {
 +		u_int manl : 32;
 +		u_int manh : 20;
 +		u_int  exp : 11;
 +		u_int sign :  1;
 +	} *p = (struct IEEEdp *)&d;
 +
 +	if (p->exp == 0) {
 +		if ((p->manl | p->manh) == 0)
 +			return FP_ZERO;
 +		else
 +			return FP_SUBNORMAL;
 +	} else if (p->exp == 2047) {
 +		if ((p->manl | p->manh) == 0)
 +			return FP_INFINITE;
 +		else
 +			return FP_NAN;
 +	} else
 +		return FP_NORMAL;
 +}
 +
 +int
 +__fpclassifyl(l)
 +	long double l;
 +{
 +	register struct IEEElp {
 +		u_int manl : 32;
 +		u_int manh : 31;
 +		u_int  exp : 16;
 +		u_int sign :  1;
 +		u_int junk : 16;
 +	} *p = (struct IEEElp *)&l;
 +
 +        if (p->exp == 0) {
 +                if ((p->manl | p->manh) == 0)
 +                        return FP_ZERO;
 +                else
 +                        return FP_SUBNORMAL;
 +        } else if (p->exp == 32767) {
 +                if ((p->manl | p->manh) == 0)
 +                        return FP_INFINITE;
 +                else
 +                        return FP_NAN;
 +        } else
 +                return FP_NORMAL;
 +
 +}

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-standards" in the body of the message




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