Date: Wed, 2 Apr 2003 16:21:30 +1000 (EST) From: Bruce Evans <bde@zeta.org.au> To: Peter Jeremy <peterjeremy@optushome.com.au> Cc: cvs-src@FreeBSD.org Subject: Re: cvs commit: src/sys/ia64/include float.h Message-ID: <20030402154250.X25489@gamplex.bde.org> In-Reply-To: <20030401200457.GA30284@cirb503493.alcatel.com.au> References: <200303272038.h2RKcM7L096560@repoman.freebsd.org> <20030330175646.281097ad.Alexander@Leidinger.net> <20030331082023.GE11307@cirb503493.alcatel.com.au> <20030401172440.701aaafd.Alexander@Leidinger.net> <20030401200457.GA30284@cirb503493.alcatel.com.au>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 2 Apr 2003, Peter Jeremy wrote: > On Tue, Apr 01, 2003 at 05:24:40PM +0200, Alexander Leidinger wrote: > >On Mon, 31 Mar 2003 18:20:23 +1000 > >Peter Jeremy <peterjeremy@optushome.com.au> wrote: > > > >> It's not clear exactly what this program is intended to test. > > > >We noticed that icc does use other values for LDBL_MIN than we do, and > >instead of just thinking that Intel does it right I wanted to verify it. This might be caused by icc actually understanding the target's default precision for long doubles (FreeBSD changes the hardware default of 64-bit to 53-bit for technical reasons). > >So I started with tests for float and double. > > The actual digit string forming the constants is not especially > important - as long as the compiler interprets that string as the > correct FP value. There are a number of test programs intended to I think compilers are required to diagnose overflow. gcc -Wmumble reports the overflow for the current i386 LDBL_MAX if you increase the last digit in it by 1 (which corresponds to rounding the infinitely precise value up instead of down). However, since gcc doesn't understand the target's precision, its overflow threshold is wrong, so it permits a value of LDBL_MAX (the one in the i386 float.h) that causes overflow when used: %%% $ cat z.c #include <float.h> #include <stdio.h> long double x, y, zero; static void print_ld(long double *dp) { unsigned char *cp; int i; for (cp = (unsigned char *)(void *)dp, i = 0; i < sizeof(*dp); i++) printf("%02x", cp[i]); printf("\n"); } int main(void) { x = LDBL_MAX; y = LDBL_MAX + zero; /* This overflows. */ print_ld(&x); print_ld(&y); } $ cc -o z z.c $ ./z fffffffffffffffffe7f0000 0000000000000080ff7f0000 %%% The first value printed is the 64-bit-precision LDBL_MAX (with 2 bytes of padding). The second value is +Inf. Overflow can also be seen by checking the overflow bit using gdb or fpgetsticky(). Note that although LDBL_MAX is defined as the maximum representable long double value, and the 64-bit-precision LDBL_MAX is representable, it must be considered as an unsupported magic value since there is no way to produce it without invoking undefined behaviour. Undefined behaviour includes compiler/library bugs like generating the wrong bits for LBDL max and not trimming extra precision given by hardware math functions. Script to compute LDBL_MAX to 19 digits with 64 and 63-bit precisions: %%% #!/bin/sh bc <<EOF scale=19 (2^64-1)*2^(16384-64)/10^4932 (2^53-1)*2^(16384-53)/10^4932 EOF %%% Beware of sloppy rounding. The other values in float.h can be calculated similarly according to the formulas in the comments for FLT*. > verify correct FP behaviour by the CPU and compiler floating around on > the net - look at NETLIB or Prof W. Kahan's web site. (I don't have > the URL's immediately to hand). ucbtest is good but is too old to cover much of C99. I haven't found anything anywhere near as good and up to date. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030402154250.X25489>