standards/130067: Wrong numeric limits in system headers?

Bruce Evans brde at optusnet.com.au
Wed Dec 31 13:10:03 UTC 2008


The following reply was made to PR standards/130067; it has been noted by GNATS.

From: Bruce Evans <brde at optusnet.com.au>
To: Vaclav Haisman <v.haisman at sh.cvut.cz>
Cc: freebsd-gnats-submit at FreeBSD.org, freebsd-standards at FreeBSD.org,
        imp at 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 <float.h> 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


More information about the freebsd-standards mailing list