From owner-freebsd-standards@FreeBSD.ORG Wed Dec 31 13:10:03 2008 Return-Path: Delivered-To: freebsd-standards@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 50122106564A for ; Wed, 31 Dec 2008 13:10:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 3C5058FC17 for ; Wed, 31 Dec 2008 13:10:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id mBVDA2DW004097 for ; Wed, 31 Dec 2008 13:10:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id mBVDA21N004096; Wed, 31 Dec 2008 13:10:02 GMT (envelope-from gnats) Date: Wed, 31 Dec 2008 13:10:02 GMT Message-Id: <200812311310.mBVDA21N004096@freefall.freebsd.org> To: freebsd-standards@FreeBSD.org From: Bruce Evans Cc: Subject: Re: standards/130067: Wrong numeric limits in system headers? X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Bruce Evans List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 31 Dec 2008 13:10:03 -0000 The following reply was made to PR standards/130067; it has been noted by GNATS. From: Bruce Evans To: Vaclav Haisman Cc: freebsd-gnats-submit@FreeBSD.org, freebsd-standards@FreeBSD.org, imp@FreeBSD.org Subject: Re: standards/130067: Wrong numeric limits in system headers? Date: Wed, 31 Dec 2008 22:26:22 +1100 (EST) On Tue, 30 Dec 2008, Vaclav Haisman wrote: > There seems to be a problem with definition of long double limits on FreeBSD i386/6.x. > > shell::wilx:~/packed_vector> echo | g++ -dD -E - | sort | grep LDBL_MAX > #define __LDBL_MAX_10_EXP__ 4932 > #define __LDBL_MAX_EXP__ 16384 > #define __LDBL_MAX__ 1.1897314953572316e+4932L > > shell::wilx:~/packed_vector> fgrep -rn LDBL_MAX /usr/include > [...] > /usr/include/machine/float.h:75:#define LDBL_MAX_EXP 16384 > /usr/include/machine/float.h:76:#define LDBL_MAX 1.1897314953572317650E+4932L > /usr/include/machine/float.h:77:#define LDBL_MAX_10_EXP 4932 > /usr/include/float.h:75:#define LDBL_MAX_EXP 16384 > /usr/include/float.h:76:#define LDBL_MAX 1.1897314953572317650E+4932L > /usr/include/float.h:77:#define LDBL_MAX_10_EXP 4932 > > Notice the difference in definition of LDBL_MAX, the values in system > headers are tiny bit larger than that defined by GCC itself. > ... > machine/float.h:76:#define LDBL_MAX 1.1897314953572317650E+4932L > float.h:76:#define LDBL_MAX 1.1897314953572317650E+4932L > GCC: __LDBL_MAX__ 1.1897314953572316e+4932L This has never worked. However, since gcc became aware of the limited precision of long doubles under FreeBSD a few years ago, it shouldn't be as broken as it is. Gcc defines __LDBL_MAX__ to have the correct value (1-2^-53)*2^1024 (rounded to 17 digits, which is enough for the actual precision of 53 bits), while FreeBSD defines LDBL_MAX as (1-2^-64)*2^1024 (rounded to 20 digits, which is perhaps not quite enough for the non-actual precision of 64 bits (either this 20 or DECIMAL_DIG's value of 21 is dubious). The wrong value in FreeBSD may have worked accidentally a few years ago, but now hit has no chance of working: - a few years ago: gcc didn't know about FreeBSD's limited precision, so it evaluated the constant in 64-bit precision and got precisely (1-2^-64)*2^1024 (only the decimal constant is imprecise). Static initialization to this value preserved the value. Actual use of the value caused it to be rounded to 53 bits. I think that still made it Infinity in most cases. - now: gcc evaluates it in 53-bit precision and gets Infinity for it consistently. Many other long double constants in FreeBSD's have never worked, and are much further from neing correct, but are fixed in gcc: From gcc4.2 -E -dM: % #define __LDBL_MAX__ 1.1897314953572316e+4932L % #define __LDBL_MAX_EXP__ 16384 % #define __LDBL_HAS_INFINITY__ 1 % #define __LDBL_MIN__ 3.3621031431120935e-4932L % #define __LDBL_HAS_QUIET_NAN__ 1 % #define __LDBL_HAS_DENORM__ 1 % #define __LDBL_EPSILON__ 2.2204460492503131e-16L % #define __LDBL_DIG__ 15 % #define __LDBL_MANT_DIG__ 53 % #define __LDBL_MIN_EXP__ (-16381) % #define __LDBL_MAX_10_EXP__ 4932 % #define __LDBL_DENORM_MIN__ 7.4653686412953080e-4948L % #define __LDBL_MIN_10_EXP__ (-4931) From float.h: % #define LDBL_MANT_DIG 64 Wrong; should be 53. All the other errors are derived from this (see the definitions of FLT_* for the derivations -- p must be 53 but is 64). % #define LDBL_EPSILON 1.0842021724855044340E-19L Wrong: too small by a factor of 2^13. % #define LDBL_DIG 18 Wrong: unnecessarily large (fairly harmless). % #define LDBL_MIN_EXP (-16381) Correct. % #define LDBL_MIN 3.3621031431120935063E-4932L Correct (just has more precision than needed for rounding to 53 bits). % #define LDBL_MIN_10_EXP (-4931) % #define LDBL_MAX_EXP 16384 Correct. % #define LDBL_MAX 1.1897314953572317650E+4932L Wrong: see above. % #define LDBL_MAX_10_EXP 4932 Correct. Bruce