Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Oct 2002 18:47:19 -0500 (CDT)
From:      Loren James Rittle <rittle@latour.rsch.comm.mot.com>
To:        current@freebsd.org
Cc:        bde@zeta.org.au
Subject:   Re: Lack of real long double support (was Re: libstdc++ does not contain fabsl symbol)
Message-ID:  <200210242347.g9ONlJqk036023@latour.rsch.comm.mot.com>
In-Reply-To: <20021024205944.R1451-100000@gamplex.bde.org>
References:  <200210240833.g9O8XB1W033884@latour.rsch.comm.mot.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Thanks for the quick answer Bruce.  Based on the statement: ``It
should use whatever is the default format for the host environment''
and the statements that make it clear gcc isn't changing its default
precision setting anytime soon, I think I now know how to make a
correct patch for the FSF gcc mainline.  More details in line below.

Regards,
Loren

>> ...  Anyways, that work exposed some issues.

>> We have this in the system header:

>> #define LDBL_MANT_DIG   DBL_MANT_DIG
>> #define LDBL_MIN_EXP    DBL_MIN_EXP
>> #define LDBL_MAX_EXP    DBL_MAX_EXP
>> [...]

> This seems to be correct.  Long double precision is not really supported
> either at complie time or runtime.  The default precision (on i386's)
> is 53 bits, so (normalized) long doubles have a hard time getting any
> larger than DBL_MAX or any smaller than DBL_MIN (you can create them
> as bits or using a hardware transcendental function, but any arithmetic
> on them will convert them to double precision).

It is easy to generate, with arithmetic, a long double value outside
the *exponent* range above no matter how the precision is set; it is
not truncated to Inf until it is actually cast to a double (as is
currently done just before a long double is printed with stdio).  See
below for a program that demonstrates this behavior.

>> Yet, the FP hardware is actually configured by default to provide
>> `long double' as:

>> #define LDBL_MANT_DIG   53

> I think you mean 64 (the hardware default).

No sir, I did mean as configured in the system startup code, it is
forced to 53-bits (that choice affects long double as well as double).
But there are no IEEE control bits to limit the size of the exponent
field, are there?  Thus, the following describes the exact size of the
HW's exponent field of a long double as configured by default:

>> #define LDBL_MIN_EXP    (-16381)
>> #define LDBL_MAX_EXP    16384

> gcc can't actually support the full range, since it doesn't control
> the runtime environement (it could issue a fninit before main() to
> change the default, but it shouldn't and doesn't).  The exponent
> range is lost long before printf() is reached.  E.g.,

>	long double x= DBL_MAX;
>	long double y = 2 * x;

> gives +Inf for y since the result is doesn't fit in 53-bit precision.

As you know, the selection of maximum precision is orthogonal to the
number of bits used for the exponent.

I do wish you were correct.  Have you looked at the raw memory of y?
It is *not* the bit pattern for +Inf.  If y were +Inf, then based on
the properties of IEEE math, the following would report Inf not
DBL_MAX/2:

#include <float.h>
int main (void)
{
  long double x= LDBL_MAX; // Same as DBL_MAX in current float.h
  long double y = 2e100 * x; // If LDBL_MAX was correct, we should latch Inf.
  long double z = y / 4e100;
  printf ("%Lg\n", z);
}

It does, in fact, report DBL_MAX/2 with the system compiler on FreeBSD
4.  FYI, I reviewed the generated code to ensure it was using run-time
calculations not compile-time calculations.  I'd call that a rather
easy time getting a normalized long double much larger than
LDBL_MAX/DBL_MAX.  This test alone proves in my mind that the
<float.h> system header for i386 is itself wrong.

> The system header correctly reports this default precision.  Any header
> genrated by the gcc build should be no different, since the build should
> run in the target environment.

I agree that the precision setting in the system header is fine.  The
size of the exponent field is buggy.  I held the opinion you have but
while trying to convince RTH (the guy that rewrote gcc FP support), I
did enough research that also leads me to think that it is the header
itself which is buggy.

If you really want, I can tell RTH that FreeBSD/i386 absolutely wants
`long double' to be:

53 mantissa bits
1024 max exponent

And we can let the chips fall where they may but that is lie verses
the hardware setup just to match a buggy system header.  Attempting to
get that patch in was what triggered my research and first post.

>> Anyways, two questions for FreeBSD maintainers.  How should gcc, as
>> provided from the FSF, describe the long double FP format for
>> FreeBSD/i386 4.x?  Shall we assume that no changes for FreeBSD 5.x
>> will occur?

> It should use whatever is the default format for the host environment,
> It still has enquire.c for doing this automatically.  [...]

I fear I didn't explain clearly enough.  enquire.c is completely
*gone* in gcc 3.3.  This is why gcc needs to fully understand the
exact FP default configuration.  As you noted, enquire.c was buggy.

> I think he would be even unhappier with gcc's support for it.  We default
> to 53-bit precision partly because Kahan's (his?) paranioa(1) is unhappy
> with 64-bit precision.

I can't disagree with the first statement.  However, support for FP in
gcc has just been rewritten and the paranioa test was pulled into gcc.
Perhaps it is time to revisit some past assumptions related to FP when
gcc 3.3 is imported as the system compiler.  And of course, I assumed
it was better to give a headups now and fix the FSF-side now while we
have the attention of the person that reworked FP support.

> I think it makes no provably significant difference for naively-written
> code.  I'd rather get the same (perhaps wrong) results on all machines
> from naively-written code.

OK, my main point was to learn exactly what FreeBSD was going to do
with FP so we could capture it over in gcc.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




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