Skip site navigation (1)Skip section navigation (2)
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>