cvs commit: src/sys/ia64/include float.h
Bruce Evans
bde at zeta.org.au
Tue Apr 1 22:21:51 PST 2003
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 at 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
More information about the cvs-all
mailing list