Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 May 2003 08:54:43 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Sean Chittenden <seanc@freebsd.org>
Cc:        freebsd-standards@freebsd.org
Subject:   Re: float values at the extreme... when did things change?
Message-ID:  <20030508080005.D4073@gamplex.bde.org>
In-Reply-To: <20030507175740.GM49916@perrin.int.nxad.com>
References:  <20030507175740.GM49916@perrin.int.nxad.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 7 May 2003, Sean Chittenden wrote:

> While PostgreSQL runs its regression tests fine on 4.X, in recent 5.X
> the return values of floats have changed and I'm trying to figure out
> the best way to detect this.
>
> Under older versions of FreeBSD, the following was true:
>
>   INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400');
>   ERROR:  Input '10e400' is out of range for float8
>   INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
>   ERROR:  Input '-10e400' is out of range for float8
>   INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
>   INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
>
> Small values were considered zero.  Now, however, small values are out
> of range:
>
>   INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400');
>   ERROR:  Input '-10e400' is out of range for float8
>   INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400');
>   ERROR:  Input '10e-400' is out of range for float8
>   INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400');
>   ERROR:  Input '-10e-400' is out of range for float8
>
> No doubt that things are more correct in their current incarnation,
> however, when did this change (not sure where to look) and was there a
> __FreeBSD_version bump regarding this?  -sc
>
> PS Reason this is on standards is because from what I can tell,
> -CURRENT's float handling is more standards compliant than previously
> and figure someone on this list had a hand in making this the case.

Some LDBL_* constants, especially ones related to small values, were
broken in rev.1.7 of the i386 <float.h>, but this problem seems to be
just a bug in the regression tests combined with a change in the
implementation-defined behaviour of strtod().

strtod("10e-400", NULL) now sets errno to ERANGE.  It apparently now
detects underflow when it didn't before, or decides to report this
by setting errno to ERANGE when it didn't before.  Whether errno is
set to ERANGE on underflow is implementation-defined, so it is a bug
in the regression tests for them to not expect this error.  Whether
it is actually an error depends on whether the application cares
about underflow.

gdtoa has a knob for changing this behaviour (see the README), but
this should never be used since it breaks the standard behaviour
of setting errno to ERANGE on overflow in strtod().

In RELENG_4, strtod() attempts to set errno to ERANGE on underflow.
It has no knob to control this, but its underflow detection is broken
unless the library is compiled with -O0.  This might be a compiler bug
(mishandling of extra precision could easily break underflow checks).

Test program:
%%%
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

int
main(void)
{
	double d;

	errno = 0;
	d = strtod("10e-400", 0);
	if (errno != 0)
		warn("strtod set errno!");
#ifndef TEST_RELENG_4
	/*
	 * Can't use this if we #include strtod.c since the current libc
	 * is too different and dumps core.
	 */
	printf("%.20g\n", d);
#endif
	return (0);
}

#ifdef TEST_RELENG_4
/*
 * Can also link with compat lib to see old behaviour, but that doesn't work
 * so well for the -O0 case.
 */
#include "/somewhere/RELENG_4/src/lib/libc/stdlib/strtod.c"
#endif
%%%

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030508080005.D4073>