From owner-freebsd-standards@FreeBSD.ORG Wed Dec 31 13:09:01 2008 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5CF76106564A; Wed, 31 Dec 2008 13:09:01 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from fallbackmx10.syd.optusnet.com.au (fallbackmx10.syd.optusnet.com.au [211.29.132.251]) by mx1.freebsd.org (Postfix) with ESMTP id 202A48FC21; Wed, 31 Dec 2008 13:08:54 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail02.syd.optusnet.com.au (mail02.syd.optusnet.com.au [211.29.132.183]) by fallbackmx10.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id mBVBQVN9016490; Wed, 31 Dec 2008 22:26:31 +1100 Received: from c211-30-173-239.carlnfd1.nsw.optusnet.com.au (c211-30-173-239.carlnfd1.nsw.optusnet.com.au [211.30.173.239]) by mail02.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id mBVBQMgX014574 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 31 Dec 2008 22:26:26 +1100 Date: Wed, 31 Dec 2008 22:26:22 +1100 (EST) From: Bruce Evans X-X-Sender: bde@delplex.bde.org To: Vaclav Haisman In-Reply-To: <200812302231.mBUMVUtf092910@www.freebsd.org> Message-ID: <20081231215445.S3923@delplex.bde.org> References: <200812302231.mBUMVUtf092910@www.freebsd.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed Cc: imp@FreeBSD.org, freebsd-gnats-submit@FreeBSD.org, freebsd-standards@FreeBSD.org Subject: Re: standards/130067: Wrong numeric limits in system headers? X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 31 Dec 2008 13:09:01 -0000 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