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-src mailing list