From owner-freebsd-standards@FreeBSD.ORG Wed May 7 15:54:53 2003 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2888337B401; Wed, 7 May 2003 15:54:53 -0700 (PDT) Received: from mailman.zeta.org.au (mailman.zeta.org.au [203.26.10.16]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4CAFB43FBD; Wed, 7 May 2003 15:54:49 -0700 (PDT) (envelope-from bde@zeta.org.au) Received: from katana.zip.com.au (katana.zip.com.au [61.8.7.246]) by mailman.zeta.org.au (8.9.3p2/8.8.7) with ESMTP id IAA27366; Thu, 8 May 2003 08:54:45 +1000 Date: Thu, 8 May 2003 08:54:43 +1000 (EST) From: Bruce Evans X-X-Sender: bde@gamplex.bde.org To: Sean Chittenden In-Reply-To: <20030507175740.GM49916@perrin.int.nxad.com> Message-ID: <20030508080005.D4073@gamplex.bde.org> References: <20030507175740.GM49916@perrin.int.nxad.com> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: das@freebsd.org cc: freebsd-standards@freebsd.org Subject: Re: float values at the extreme... when did things change? X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 May 2003 22:54:53 -0000 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 , 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 #include #include #include 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