<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(). Fix: Implement the following (and probably further macros); the descriptions are copied from a draft of ISO C99. 7.12 Mathematics <math.h> [#6] The macros FP_INFINITE FP_NAN FP_NORMAL FP_SUBNORMAL FP_ZERO are for number classification. They represent the mutually exclusive kinds of floating-point values. They expand to integer constant expressions with distinct values. 7.12.3.1 The fpclassify macro Synopsis [#1] #include <math.h> int fpclassify(real-floating x); Description [#2] The fpclassify macro classifies its argument value as NaN, infinite, normal, subnormal, or zero. First, an argument represented in a format wider than its semantic type is converted to its semantic type. Then classification is based on the type of the argument.184) Returns [#3] The fpclassify macro returns the value of the number classification macro appropriate to the value of its argument. [#4] EXAMPLE The fpclassify macro might be implemented in terms of ordinary functions as #define fpclassify(x) \ ((sizeof (x) == sizeof (float)) ? \ __fpclassifyf(x) \ : (sizeof (x) == sizeof (double)) ? \ __fpclassifyd(x) \ : __fpclassifyl(x)) 7.12.3.2 The isfinite macro Synopsis [#1] #include <math.h> int isfinite(real-floating x); Description [#2] The isfinite macro determines whether its argument has a finite value (zero, subnormal, or normal, and not infinite or NaN). First, an argument represented in a format wider than its semantic type is converted to its semantic type. Then determination is based on the type of the argument. Returns [#3] The isfinite macro returns a nonzero value if and only if its argument has a finite value.
<<On Sun, 26 Nov 2000 03:12:55 +0100 (CET), pfeifer@dbai.tuwien.ac.at (Gerald Pfeifer) said: >> Synopsis: <math.h> lacks many ISO C99 features (NAN, isfinite,...) That's because we don't have a C99 compiler. Some of these will need to be implemented in the library, sure, but I don't see any rush. -GAWollman
On Sat, 25 Nov 2000, Garrett Wollman wrote: > That's because we don't have a C99 compiler. Some of these will need > to be implemented in the library, sure, but I don't see any rush. First of all, you don't exactly need a C99 compiler to have a (mostly) C99 library. Second, GCC 3.0 will be a (nearly fully compliant) C99 compiler, so FreeBSD 5.0 will need this at the very latest, I guess. Current snapshots of GCC are (nearly fully compliant) already, so -CURRENT users do have a (nearly fully compliant) C99 compiler as do 4.x users compiling GCC on their own. And finally, but probably most important: GLIBC 2.1 and especially GLIBC 2.2 are already closely compliant, so many developers will now use C99 library features -- as evidenced by Wine (where I just had to hack around FreeBSD being limited) and surely other programs as well. So, in my opinion, this is a critical issue if we want to avoid the -- all too common impression among users -- that FreeBSD is playing catch up. :-( Gerald -- Gerald "Jerry" pfeifer@dbai.tuwien.ac.at http://www.dbai.tuwien.ac.at/~pfeifer/
Responsible Changed From-To: freebsd-bugs->standards Assign this to -standards, until someone volunteers to implement these C99 additions to <math.h>.
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; + +}
On Thu, 9 May 2002, David Schultz wrote: >> 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. Cool. Unfortunately, I'm not enough of an expert to be really able to review your improvements in detail, but have only been bitten by missing features while maintaining our emulators/wine port. But apart from isfinite(), everything originally require by Wine seems to be there with your patch, thanks! (Hopefully someone with more in-depth knowledge than me will review your patch soon!) Gerald -- Gerald "Jerry" pfeifer@dbai.tuwien.ac.at http://www.dbai.tuwien.ac.at/~pfeifer/
Thus spake Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>: > But apart from isfinite(), everything originally require by Wine seems > to be there with your patch, thanks! isfinite() is a really easy addition, since it's just a special case of fpclassify(). I just want to verify that someone is willing to support the work before I finish hacking up math.h and research any changes necessary for architectures other than i386.
I no longer have the time and interest to implement the rest of C99 math, and nobody else seems to care either. Upon request, I can provide some old patches that are more extensive than the ones I posted to this PR and address a bug.
Why not have an "is()" function that can do all of this? Here is the x86 source code for is(): PROC IS PUSH BP MOV BP,SP FLD [BP+4] FTST ;Get the status register from the FPU into AX AND AX,[BP+10] FCOMP POP BP RET ENDP IS And here is the addition to math.h: int is(double x, int bitmask); Lucas Thode
Responsible Changed From-To: standards->fenner Over to Bill Fenner.
I made an error in my original posting. The ftst opcode should be changed to fxam. Lucas
Hi there, I think that PR misc/23103 can be closed, most if not all of that stuff is in -CURRENT. regards, le --=20 Lukas Ertl eMail: l.ertl@univie.ac.at UNIX-Systemadministrator Tel.: (+43 1) 4277-14073 Zentraler Informatikdienst (ZID) Fax.: (+43 1) 4277-9140 der Universit=E4t Wien http://mailbox.univie.ac.at/~le/
State Changed From-To: open->closed Fixed about a year ago.