Re: Lack of real long double support

2002-10-31 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Terry Lambert [EMAIL PROTECTED] writes:
: M. Warner Losh wrote:
:  :  This
:  :  example shows that we don't support it in printf, since the above
:  :  example does ***NOT*** give +Inf, but rather whatever 2*DBL_MAX is.
: 
: [ ... ]
: 
:  Terry you are wrong.  This has to do with the RANGE not the PRECISION
:  of the floating point number.  It is ***NOT*** +Inf.
: 
: I await an explanation of how you can fit 2*DBL_MAX into a double,
: which has a range of DBL_MIN..DBL_MAX.

Look at the code.

 long double a = DBL_MAX;
 long double b = DBL_MAX * 2;

The original posting said that b would be +Inf at this point, which is
not correct.  I think that Bruce was confused there.  The more correct
example to look at was the one that rittle@ posted which was 1 +
LDBL_EPSILON.

:  : The main issue that I think is outstanding is that you can't get
:  : both exception behaviour and non-exception behaviour, and it is
:  : going to have to be the compiler's job to force the issue, because
:  : it can't dictate implementaiton to the host OS.
:  
:  I don't follow.
: 
: I think that a number that's a 64 bit mantissa reaised to an exponent
: N takes a larger N if you have only 53 bits of mantissa, if you want
: to represent the same value.

Nope.  The only difference between 53 bits and 64 bits of precision is
just that: precision.  The number of bits for expoentent is
independent of this.

: The obvious example in the FreeBSD case is the default value of the
: expression (fpgetprec() == FP_PE).  The compiler is not permitted to
: assume, one way or the other; it has to do runtime testing, at the
: time you compile the compiler, to comply with a completely strict
: interpretation of C99 (IMO).

This is true.  Granting, for the moment, that fpgetprec() == FP_PE
isn't a standards conforming expression.

But I think that the rest of this is going off into the weeds.  I'm
just trying to get things working in a sane way for long doubles.  It
looks like gcc 3.2 really wants the fpu to start off in FP_PE.

Before I go forward on this further, I've got a lot of testing to do
with kernels and such to find out what really works and what does (and
doesn't) break paranoia.c.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Bruce Evans
On Wed, 30 Oct 2002, Terry Lambert wrote:

 This is the basis of Bruce's complaint:

 
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1099099+0+archive/2002/freebsd-current/20021027.freebsd-current

 | 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.
 | 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.

Please forget this wrong example :-).  The precision doesn't affect the
exponent range.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Bruce Evans
On Wed, 30 Oct 2002, M. Warner Losh wrote:

 The one issue that I've seen is

 long double a = 1.0L;
 long double b = 1.0L + LDBL_EPSION
 if (a == b) abort();

 which is what I'm trying to fix. (note, 1.0L must be spelled
 oneld() and long double oneld() { return (1.0L);}) to avoid the
 optimizer getting it right.

Example of how fixing this breaks a similar assertion for DBL_ESPILON:

%%%
$ cat z.c
#include float.h
#include floatingpoint.h

long double oneld = 1.0L;
double oned = 1.0;

int
main()
{
test(2);
test(3);
}

int
test(int prec)
{
long double la, lb;
double a, b;

fpsetprec(prec);
la = oneld;
lb = oneld + LDBL_EPSILON;
if (la == lb)
printf(LDBL_EPSILON failed test 1 with prec %d\n, prec);
la = oneld;
lb = oneld + LDBL_EPSILON / 2;
if (la != lb)
printf(LDBL_EPSILON failed test 2 with prec %d\n, prec);

a = oned;
b = oned + DBL_EPSILON;
if (a == b)
printf(DBL_EPSILON failed test 1 with prec %d\n, prec);
a = oned;
b = oned + DBL_EPSILON / 2;
if (a != b)
printf(DBL_EPSILON failed test 2 with prec %d\n, prec);
}
$ cc -o z z.c
$ ./z
LDBL_EPSILON failed test 1 with prec 2
$ cc -O -o z z.c.
$ ./z
LDBL_EPSILON failed test 1 with prec 2
DBL_EPSILON failed test 2 with prec 3
%%%

The full brokenness only shows up with -O.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Bruce Evans
On Wed, 30 Oct 2002, M. Warner Losh wrote:

 In message: [EMAIL PROTECTED]
 Bruce Evans [EMAIL PROTECTED] writes:
 : The reasons are the same as they used to be: incomplete language support
 : and incomplete library support.  Language support is being completed but
 : is far from here yet.  See the paper referenced in Loren's reply for more
 : details than anyone should want to know.

 OK.  I'll have to go back and find that reference.  I'd really like to
 change the __INITIAL_NPXCW__ from 0x127f to 0x137f in npx.h.  I think
 that we can get the library support in place over time, as this
 already is a bullet item in the standards todo list web page.  The gcc
 3.2 compiler does a decent, but not perfect, job of dealing with the
 floating point stuff.

Er, it does the same very imperfect job that it did in when it first
implemented long doubles.

 : C99 encourages having a behaviour that is known at compile time and
 : telling applications about it in FLT_EVAL_METHOD (this can be set to
 : -1 == indeterminable, but that would not be very useful although it
 : is the only correct setting now).  The compiler should implement the
 : system implementor's choice or enforce its own choice.  gcc doesn't
 : really understand this this.  gcc-3.2 thinks that it implementing
 : method 0 (no extension of precision) but the npx hardware is nothing
 : like that.

 I don't understand this completely.  ARe you saying that gcc is doing
 something worng?

Yes.  It doesn't attempt to implement C99 stuff and depends on a fuzzy
reading of C90 to conform to C90.  Example of gcc-3.2's schizophrenia
with precision:

%%%
$ cat z.c
double x = 1.0F / 3.0F;
float y = 1.0F;
float z = 3.0F;
double u;

int
main()
{
u = y / z;
printf(x = %.17g\n, x);
printf(u = %.17g\n, u);
return (x == u ? 0 : 1);
}
$ cc -o z z.c
$ ./z
x = 0.333432674408
u = 0.1
%%%

Evaluation at compile time is different that at runtime because gcc
thinks that float operations are performed in float precision and
performs them at that precision at compile time.  But float operations
at runtime are actually performed in the ambient precision due to
white lies like the following in i386.md:

%%%
(define_expand divsf3
  [(set (match_operand:SF 0 register_operand )
(div:SF (match_operand:SF 1 register_operand )
(match_operand:SF 2 nonimmediate_operand )))]
  TARGET_80387 || TARGET_SSE_MATH
  )
%%%

(This says that the result of dividing a single-precision float by a
single precision float is a single-precision float, but the result is
actually an ambient-precision float.)

The above example is for float precision.  The FreeBSD default basically
insulates users from surprises due to precision when everything is a long
double.

 BTW, NetBSD is kinda schizophrenic about this:

It just supports a lot of cases.

 /*
  * The i387 defaults to Intel extended precision mode and round to nearest,
  * with all exceptions masked.
  */
 #define __INITIAL_NPXCW__   0x037f
 /* NetBSD uses IEEE double precision. */
 #define __NetBSD_NPXCW__0x127f
 /* FreeBSD leaves some exceptions unmasked as well. */
 #define __FreeBSD_NPXCW__   0x1272

This is the FreeBSD[1-3] default.

 /* iBCS2 goes a bit further and leaves the underflow exception unmasked. */
 #define __iBCS2_NPXCW__ 0x0262

FreeBSD and NetBSD are both derived from 386BSD which had this.  I added
the 0x1000 bit in case 386BSD ever got run with a 287.

 /* Linux just uses the default control word. */
 #define __Linux_NPXCW__ 0x037f
 /* SVR4 uses the same control word as iBCS2. */
 #define __SVR4_NPXCW__  0x0262

 So their float.h values are correct only for Linux binaries and
 emulation.  Also, it looks like FreeBSD_NPXCW is incorrect, since we

Linux binaries are just differently incorrect :-).

 have:
 #define   __INITIAL_NPXCW__   0x127F

 And there's a comment:
  * 64-bit precision often gives bad results with high level languages
  * because it makes the results of calculations depend on whether
  * intermediate values are stored in memory or in FPU registers.
 which seems like a compiler issue, not an OS issue to me.

Indeed it is mostly a language issue, so this is not a very good place to
decide the setting.  You would not be wrong to set it in crt0 if you removed
it in the kernel (just set the hardware default in the kernel).  But the
library can still override any unwanted defaults.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread David Schultz
Thus spake Bruce Evans [EMAIL PROTECTED]:
 $ cc -o z z.c
 $ ./z
 LDBL_EPSILON failed test 1 with prec 2
 $ cc -O -o z z.c.
 $ ./z
 LDBL_EPSILON failed test 1 with prec 2
 DBL_EPSILON failed test 2 with prec 3
 %%%
 
 The full brokenness only shows up with -O.

Actually, the _full_ brokenness of floating point in FreeBSD shows
up only with -O2.  :-(  A number of library functions
(e.g. isinf()) use unions for type punning, which violates C's
aliasing rules.  It turns out that there's a bad interaction
between gcc3's -fschedule-insns and -fstrict-aliasing (both
implied by -O2) that can cause problems.  The best fix I know of
is to use unions in the limited way that gcc's optimizer knows how
to handle in a reasonable way.

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Bruce Evans
On Thu, 31 Oct 2002, David Schultz wrote:

 Thus spake Bruce Evans [EMAIL PROTECTED]:
  $ cc -o z z.c
  $ ./z
  LDBL_EPSILON failed test 1 with prec 2
  $ cc -O -o z z.c.
  $ ./z
  LDBL_EPSILON failed test 1 with prec 2
  DBL_EPSILON failed test 2 with prec 3
  %%%
 
  The full brokenness only shows up with -O.

 Actually, the _full_ brokenness of floating point in FreeBSD shows
 up only with -O2.  :-(  A number of library functions
 (e.g. isinf()) use unions for type punning, which violates C's
 aliasing rules.

 It turns out that there's a bad interaction
 between gcc3's -fschedule-insns and -fstrict-aliasing (both
 implied by -O2) that can cause problems.  The best fix I know of
 is to use unions in the limited way that gcc's optimizer knows how
 to handle in a reasonable way.

Eeek.

gcc.info says one version is required to work even with -fstrict-aliasing.
The problems seems to be limited, since msun was fixed before rev.1.1
to use this version.  From msun/src/math_private.h:

%%%
/*
 * The original fdlibm code used statements like:
 *  n0 = ((*(int*)one)29)^1; * index of high word *
 *  ix0 = *(n0+(int*)x);   * high word of x *
 *  ix1 = *((1-n0)+(int*)x);   * low word of x *
 * to dig two 32 bit words out of the 64 bit IEEE floating point
 * value.  That is non-ANSI, and, moreover, the gcc instruction
 * scheduler gets it wrong.  We instead use the following macros.
 * Unlike the original code, we determine the endianness at compile
 * time, not at run time; I don't see much benefit to selecting
 * endianness at run time.
 */
...
#define EXTRACT_WORDS(ix0,ix1,d)\
do {\
  ieee_double_shape_type ew_u;  \
  ew_u.value = (d); \
  (ix0) = ew_u.parts.msw;   \
  (ix1) = ew_u.parts.lsw;   \
} while (0)
...
%%%

This stores the double into the union and doesn't use any pointers to
access the results, so it should work.  isinf.c and even the fixed
version of strtod.c uses a dubious cast to pun the double to a union.
I think the store gets optimized away as far as possible.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Loren James Rittle
In article [EMAIL PROTECTED],
Bruce Evans[EMAIL PROTECTED] writes:

 Example of how fixing this breaks a similar assertion for DBL_ESPILON:

 %%%
 $ cat z.c
[...]
 $ cc -o z z.c
 $ ./z
 LDBL_EPSILON failed test 1 with prec 2
 $ cc -O -o z z.c.
 $ ./z
 LDBL_EPSILON failed test 1 with prec 2
 DBL_EPSILON failed test 2 with prec 3
 %%%

 The full brokenness only shows up with -O.

When I run your program against gcc mainline (for 3.3 release) with
the patch I have staged from RTH to correctly match our FP hardware
default setup, I see:

S rittle@latour; /usr/local/beta-gcc/bin/gcc t.c
S rittle@latour; a.out 
LDBL_EPSILON failed test 2 with prec 3
S rittle@latour; /usr/local/beta-gcc/bin/gcc -O t.c
S rittle@latour; a.out 
LDBL_EPSILON failed test 2 with prec 3
DBL_EPSILON failed test 2 with prec 3
S rittle@latour; /usr/local/beta-gcc/bin/gcc -O2 t.c
S rittle@latour; a.out 
LDBL_EPSILON failed test 2 with prec 3
DBL_EPSILON failed test 2 with prec 3
S rittle@latour; /usr/local/beta-gcc/bin/gcc -O3 t.c
S rittle@latour; a.out 
LDBL_EPSILON failed test 2 with prec 3
DBL_EPSILON failed test 2 with prec 3

I.e. the only time it fails is when the user made a call to change
the default precision.  Is that gcc 3.3 behavior acceptable (at least
until gcc can be further refined to attempt to handle user override of
the FP control word)?

Regards,
Loren

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Terry Lambert
Bruce Evans wrote:
 Please forget this wrong example :-).  The precision doesn't affect the
 exponent range.

Done.

-- Terry



To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Terry Lambert
M. Warner Losh wrote:
 : I await an explanation of how you can fit 2*DBL_MAX into a double,
 : which has a range of DBL_MIN..DBL_MAX.
 
 Look at the code.
 
  long double a = DBL_MAX;
  long double b = DBL_MAX * 2;
 
 The original posting said that b would be +Inf at this point, which is
 not correct.  I think that Bruce was confused there.  The more correct
 example to look at was the one that rittle@ posted which was 1 +
 LDBL_EPSILON.

I guess I must not be understanding.  What will b be, at this point,
then?  How can it have a value larger than DBL_MAX that's not +Inf?

If it's possible to represent a value larger than DBL_MAX in a double,
then the value of DBL_MAX is wrong, right?  Maximum means maximum,
doesn't it?


 : I think that a number that's a 64 bit mantissa reaised to an exponent
 : N takes a larger N if you have only 53 bits of mantissa, if you want
 : to represent the same value.
 
 Nope.  The only difference between 53 bits and 64 bits of precision is
 just that: precision.  The number of bits for expoentent is
 independent of this.

.125 ^ 2 = 0.015625
.25 ^ 3 = 0.015625

So if I go from 3 digits of precision to 2 digits of precision for
my mantissa, in order to represent the same number, I need a larger
exponent.


 This is true.  Granting, for the moment, that fpgetprec() == FP_PE
 isn't a standards conforming expression.
 
 But I think that the rest of this is going off into the weeds.  I'm
 just trying to get things working in a sane way for long doubles.  It
 looks like gcc 3.2 really wants the fpu to start off in FP_PE.

There has to be an agreement between the host OS and the compiler;
that's what makes C99 more complicated than it needed to be.


 Before I go forward on this further, I've got a lot of testing to do
 with kernels and such to find out what really works and what does (and
 doesn't) break paranoia.c.

That's one test.  Another is:

http://www.glenmccl.com/c9suite.htm

Unfortunately, it's $8495 for everything.  8-(.  There's also the
stuff I wrote, which doesn't test range/domain overflows, etc., but
at least complains when things are not defined or prototypes are
out of scope (i.e. it mostly just complains about header file
contents).

-- Terry



To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Steve Kargl
On Thu, Oct 31, 2002 at 03:18:47PM -0700, M. Warner Losh wrote:
 In message: [EMAIL PROTECTED]
 Terry Lambert [EMAIL PROTECTED] writes:
 :  Nope.  The only difference between 53 bits and 64 bits of precision is
 :  just that: precision.  The number of bits for expoentent is
 :  independent of this.
 : 
 : .125 ^ 2 = 0.015625
 : .25 ^ 3 = 0.015625
 : 
 : So if I go from 3 digits of precision to 2 digits of precision for
 : my mantissa, in order to represent the same number, I need a larger
 : exponent.
 
 That's not how it works.  The exponent is more like
 
 .125 * 2^3
 vs
 .124  * 2^3
 
 Both have exponent 3, but the differ by a bit or two in the mantissa.
 

Loren already posted a pointer to What Every Scientist Should
Know About Floating-Point Arithmetic by David Goldberg.  But,
for Terry edification

http://cch.loria.fr/documentation/IEEE754/ACM/goldberg.pdf

This is only 1 of 66100 hits from a google search with
keywords floating point scientist.



-- 
Steve

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Bruce Evans
On Thu, 31 Oct 2002, M. Warner Losh wrote:

 In message: [EMAIL PROTECTED]
 Terry Lambert [EMAIL PROTECTED] writes:
 : M. Warner Losh wrote:
 :  : I await an explanation of how you can fit 2*DBL_MAX into a double,
 :  : which has a range of DBL_MIN..DBL_MAX.
 : 
 :  Look at the code.
 : 
 :   long double a = DBL_MAX;
 :   long double b = DBL_MAX * 2;
 : 
 :  The original posting said that b would be +Inf at this point, which is
 :  not correct.  I think that Bruce was confused there.  The more correct
 :  example to look at was the one that rittle@ posted which was 1 +
 :  LDBL_EPSILON.
 :
 : I guess I must not be understanding.  What will b be, at this point,
 : then?  How can it have a value larger than DBL_MAX that's not +Inf?
 :
 : If it's possible to represent a value larger than DBL_MAX in a double,
 : then the value of DBL_MAX is wrong, right?  Maximum means maximum,
 : doesn't it?

 *LONG*DOUBLE* is not *DOUBLE*.  long double has extended precision and
  a range compared to double.  That's how.

To beat this dead horse some more: look at the code carefully.  It was

long double x= DBL_MAX;
long double y = 2 * x;  /* (1) */

This is quite different from the above, which (after renaming variables
and changing the formatting to be bug for bug compatible) is:

long double x= DBL_MAX;
long double y = DBL_MAX * 2;/* (2) */

In (1), we have DBL_MAX in a long double, so we can expect to double it
if long doubles are longer than doubles (whether they actually are is
machine-dependent).

In (2), we are doubling DBL_MAX as a double.  The result of this is
fuzzy, since the computation may be done in double precision or long
double precision or perhaps something weirder.  There will be no way
to tell until C99 is implemented and perhaps not even then.  gcc things
that it is implementing C99's FLT_EVAL_METHOD of 0, which performs
arithmetic on doubles in double precision, so the result of DBL_MAX *
2 is +Inf if the this is evaluated at compile time.  gcc (gcc-3.2 on
i386's)  doesn't actually implement this, since the result is not +Inf
if DBL_MAX * 2 is evaluated at runtime.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread Bruce Evans
On Thu, 31 Oct 2002, Loren James Rittle wrote:

 In article [EMAIL PROTECTED],
 Bruce Evans[EMAIL PROTECTED] writes:

 When I run your program against gcc mainline (for 3.3 release) with
 the patch I have staged from RTH to correctly match our FP hardware
 default setup, I see:

 S rittle@latour; /usr/local/beta-gcc/bin/gcc t.c
 S rittle@latour; a.out
 LDBL_EPSILON failed test 2 with prec 3
 S rittle@latour; /usr/local/beta-gcc/bin/gcc -O t.c
 S rittle@latour; a.out
 LDBL_EPSILON failed test 2 with prec 3
 DBL_EPSILON failed test 2 with prec 3
 S rittle@latour; /usr/local/beta-gcc/bin/gcc -O2 t.c
 S rittle@latour; a.out
 LDBL_EPSILON failed test 2 with prec 3
 DBL_EPSILON failed test 2 with prec 3
 S rittle@latour; /usr/local/beta-gcc/bin/gcc -O3 t.c
 S rittle@latour; a.out
 LDBL_EPSILON failed test 2 with prec 3
 DBL_EPSILON failed test 2 with prec 3

 I.e. the only time it fails is when the user made a call to change
 the default precision.  Is that gcc 3.3 behavior acceptable (at least
 until gcc can be further refined to attempt to handle user override of
 the FP control word)?

Yes, this is the correct behaviour IMO.  I don't see how any user
override of the control word (except possibly of the rounding mode) can
be expected to work right outside of an FENV_ACCESS section.  Constants
like DBL_EPSILON presumably don't apply in such sections.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-31 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Bruce Evans [EMAIL PROTECTED] writes:
: On Thu, 31 Oct 2002, M. Warner Losh wrote:
: 
:  In message: [EMAIL PROTECTED]
:  Terry Lambert [EMAIL PROTECTED] writes:
:  : M. Warner Losh wrote:
:  :  : I await an explanation of how you can fit 2*DBL_MAX into a double,
:  :  : which has a range of DBL_MIN..DBL_MAX.
:  : 
:  :  Look at the code.
:  : 
:  :   long double a = DBL_MAX;
:  :   long double b = DBL_MAX * 2;
:  : 
:  :  The original posting said that b would be +Inf at this point, which is
:  :  not correct.  I think that Bruce was confused there.  The more correct
:  :  example to look at was the one that rittle@ posted which was 1 +
:  :  LDBL_EPSILON.
:  :
:  : I guess I must not be understanding.  What will b be, at this point,
:  : then?  How can it have a value larger than DBL_MAX that's not +Inf?
:  :
:  : If it's possible to represent a value larger than DBL_MAX in a double,
:  : then the value of DBL_MAX is wrong, right?  Maximum means maximum,
:  : doesn't it?
: 
:  *LONG*DOUBLE* is not *DOUBLE*.  long double has extended precision and
:   a range compared to double.  That's how.
: 
: To beat this dead horse some more: look at the code carefully.  It was
: 
:   long double x= DBL_MAX;
:   long double y = 2 * x;  /* (1) */
:
: This is quite different from the above, which (after renaming variables
: and changing the formatting to be bug for bug compatible) is:
: 
:   long double x= DBL_MAX;
:   long double y = DBL_MAX * 2;/* (2) */
: 
: In (1), we have DBL_MAX in a long double, so we can expect to double it
: if long doubles are longer than doubles (whether they actually are is
: machine-dependent).

Right,  The first example will not be +inf if long doubles have a
greater range than doubles.  On our i386 implemenation, it does.

: In (2), we are doubling DBL_MAX as a double.  The result of this is
: fuzzy, since the computation may be done in double precision or long
: double precision or perhaps something weirder.  There will be no way
: to tell until C99 is implemented and perhaps not even then.  gcc things
: that it is implementing C99's FLT_EVAL_METHOD of 0, which performs
: arithmetic on doubles in double precision, so the result of DBL_MAX *
: 2 is +Inf if the this is evaluated at compile time.  gcc (gcc-3.2 on
: i386's)  doesn't actually implement this, since the result is not +Inf
: if DBL_MAX * 2 is evaluated at runtime.

That's true, but that's also independed problem..  It is no different than

   unsigned long long int a = ~0UL;
   unsigned long long int b = a * 2;

vs

   unsigned long long int a = ~0UL;
   unsigned long long int b = ~0UL * 2;

In the first case, b is twice a.  In the second, b is 1 less than a on
two's compliment machines.

I'd written 2.0L in my test code, and I think that it was originally
that way.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Bruce Evans [EMAIL PROTECTED] writes:
: On Mon, 28 Oct 2002, M. Warner Losh wrote:
: 
:  In message: [EMAIL PROTECTED]
:  Loren James Rittle [EMAIL PROTECTED] writes:
: 
:  This works.  I'm not sure why this isn't the default.  It looks like
:  we have hacks in the local tree to do this, which is why I thought
:  that it worked great by default
: 
: Better change FreeBSD to match the unhacked version :-).

Better to change FreeBSD to do the right thing and give long doubles
their full precision, unless there's some compelling reason not to do
so.

:  : gcc 3.3 will support a framework in which such changes would be easy
:  : to convey at compile-time but, to my knowledge, there is no support
:  : yet to obtain e.g. the precision setting at run-time.  I.e. float.h
: 
: FreeBSD (on i386's) has fpgetprec() to get it and fpsetprec() to set it,
: but these are nonstandard and won't become standard.  They don't exist
: on most or all non-i386's now, unlike fpget/setround() which will become
: the standard feget/setround().

Is there some reason we can't just put them into the machine specific
startup code like I've done with the tree.  What is the issue?  If the
issue is that doubles then start to be computed at 64 bit precision of
intermediate value, then isn't it a compiler issue of scheduling the
precision of the floating point unit?  It then would be the only
entity to know what the proper precision is at any given time.  Of
course, that sounds like a hard problem to me, especially since the
compiler might not know the state of the fp unit on entry to a given
function call.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread Bruce Evans
On Wed, 30 Oct 2002, M. Warner Losh wrote:

 In message: [EMAIL PROTECTED]
 Bruce Evans [EMAIL PROTECTED] writes:
 : On Mon, 28 Oct 2002, M. Warner Losh wrote:
 :
 :  In message: [EMAIL PROTECTED]
 :  Loren James Rittle [EMAIL PROTECTED] writes:
 :
 :  This works.  I'm not sure why this isn't the default.  It looks like
 :  we have hacks in the local tree to do this, which is why I thought
 :  that it worked great by default
 :
 : Better change FreeBSD to match the unhacked version :-).

 Better to change FreeBSD to do the right thing and give long doubles
 their full precision, unless there's some compelling reason not to do
 so.

The reasons are the same as they used to be: incomplete language support
and incomplete library support.  Language support is being completed but
is far from here yet.  See the paper referenced in Loren's reply for more
details than anyone should want to know.

 :  : gcc 3.3 will support a framework in which such changes would be easy
 :  : to convey at compile-time but, to my knowledge, there is no support
 :  : yet to obtain e.g. the precision setting at run-time.  I.e. float.h
 :
 : FreeBSD (on i386's) has fpgetprec() to get it and fpsetprec() to set it,
 : but these are nonstandard and won't become standard.  They don't exist
 : on most or all non-i386's now, unlike fpget/setround() which will become
 : the standard feget/setround().

 Is there some reason we can't just put them into the machine specific
 startup code like I've done with the tree.

Putting them there would just blow away the kernel default.  There are
arguments for putting the in both places, but not at the same time.
Linux seems to have gone the other way and move the initialization
from crt to the kernel.  I'm not sure what happened to moves to set the
Linux default for Linux applications in the kernel.

 What is the issue?  If the
 issue is that doubles then start to be computed at 64 bit precision of
 intermediate value, then isn't it a compiler issue of scheduling the
 precision of the floating point unit?  It then would be the only
 entity to know what the proper precision is at any given time.  Of
 course, that sounds like a hard problem to me, especially since the
 compiler might not know the state of the fp unit on entry to a given
 function call.

C99 encourages having a behaviour that is known at compile time and
telling applications about it in FLT_EVAL_METHOD (this can be set to
-1 == indeterminable, but that would not be very useful although it
is the only correct setting now).  The compiler should implement the
system implementor's choice or enforce its own choice.  gcc doesn't
really understand this this.  gcc-3.2 thinks that it implementing
method 0 (no extension of precision) but the npx hardware is nothing
like that.

The compiler doesn't have any special problems knowing the state of
the precision control on entry to functions.  It just needs the initial
value to be set correctly and the state to not change underneath it
like it already requires for other aspects of the state.  Changing the
state using fpset*() counts as changing the state underneath it here.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Bruce Evans [EMAIL PROTECTED] writes:
: The reasons are the same as they used to be: incomplete language support
: and incomplete library support.  Language support is being completed but
: is far from here yet.  See the paper referenced in Loren's reply for more
: details than anyone should want to know.

OK.  I'll have to go back and find that reference.  I'd really like to
change the __INITIAL_NPXCW__ from 0x127f to 0x137f in npx.h.  I think
that we can get the library support in place over time, as this
already is a bullet item in the standards todo list web page.  The gcc
3.2 compiler does a decent, but not perfect, job of dealing with the
floating point stuff.

I'll have to dive into the archive to find said paper.

:  :  : gcc 3.3 will support a framework in which such changes would be easy
:  :  : to convey at compile-time but, to my knowledge, there is no support
:  :  : yet to obtain e.g. the precision setting at run-time.  I.e. float.h
:  :
:  : FreeBSD (on i386's) has fpgetprec() to get it and fpsetprec() to set it,
:  : but these are nonstandard and won't become standard.  They don't exist
:  : on most or all non-i386's now, unlike fpget/setround() which will become
:  : the standard feget/setround().
: 
:  Is there some reason we can't just put them into the machine specific
:  startup code like I've done with the tree.
: 
: Putting them there would just blow away the kernel default.  There are
: arguments for putting the in both places, but not at the same time.
: Linux seems to have gone the other way and move the initialization
: from crt to the kernel.  I'm not sure what happened to moves to set the
: Linux default for Linux applications in the kernel.

Yea, putting it in crt is bogus.  Forget I suggested it.

: C99 encourages having a behaviour that is known at compile time and
: telling applications about it in FLT_EVAL_METHOD (this can be set to
: -1 == indeterminable, but that would not be very useful although it
: is the only correct setting now).  The compiler should implement the
: system implementor's choice or enforce its own choice.  gcc doesn't
: really understand this this.  gcc-3.2 thinks that it implementing
: method 0 (no extension of precision) but the npx hardware is nothing
: like that.

I don't understand this completely.  ARe you saying that gcc is doing
something worng?

: The compiler doesn't have any special problems knowing the state of
: the precision control on entry to functions.  It just needs the initial
: value to be set correctly and the state to not change underneath it
: like it already requires for other aspects of the state.  Changing the
: state using fpset*() counts as changing the state underneath it here.

I do understand this, which is why changing the defaults seems
reasonable to me.

BTW, NetBSD is kinda schizophrenic about this:
/*
 * The i387 defaults to Intel extended precision mode and round to nearest,
 * with all exceptions masked.
 */
#define __INITIAL_NPXCW__   0x037f
/* NetBSD uses IEEE double precision. */
#define __NetBSD_NPXCW__0x127f
/* FreeBSD leaves some exceptions unmasked as well. */
#define __FreeBSD_NPXCW__   0x1272
/* iBCS2 goes a bit further and leaves the underflow exception unmasked. */
#define __iBCS2_NPXCW__ 0x0262
/* Linux just uses the default control word. */
#define __Linux_NPXCW__ 0x037f
/* SVR4 uses the same control word as iBCS2. */
#define __SVR4_NPXCW__  0x0262

So their float.h values are correct only for Linux binaries and
emulation.  Also, it looks like FreeBSD_NPXCW is incorrect, since we
have:
#define __INITIAL_NPXCW__   0x127F

And there's a comment:
 * 64-bit precision often gives bad results with high level languages
 * because it makes the results of calculations depend on whether
 * intermediate values are stored in memory or in FPU registers.
which seems like a compiler issue, not an OS issue to me.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread Terry Lambert
M. Warner Losh wrote:
 And there's a comment:
  * 64-bit precision often gives bad results with high level languages
  * because it makes the results of calculations depend on whether
  * intermediate values are stored in memory or in FPU registers.
 which seems like a compiler issue, not an OS issue to me.

The compiler must emit instructions to truncate and set flags, as
well as generating pseudo-exceptions (should they be called for)
in the case that the storage is in registers bigger than the memory
backing them.  IT doesn't do this.

This is the basis of Bruce's complaint:

http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1099099+0+archive/2002/freebsd-current/20021027.freebsd-current

| 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.
| 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.

-- Terry

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Terry Lambert [EMAIL PROTECTED] writes:
: M. Warner Losh wrote:
:  And there's a comment:
:   * 64-bit precision often gives bad results with high level languages
:   * because it makes the results of calculations depend on whether
:   * intermediate values are stored in memory or in FPU registers.
:  which seems like a compiler issue, not an OS issue to me.
: 
: The compiler must emit instructions to truncate and set flags, as
: well as generating pseudo-exceptions (should they be called for)
: in the case that the storage is in registers bigger than the memory
: backing them.  IT doesn't do this.

I think I don't understand what you are saying at all.  It doesn't
seem top jive with the rest of the messages in this thread.

: This is the basis of Bruce's complaint:
: 
: 
:http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1099099+0+archive/2002/freebsd-current/20021027.freebsd-current
:
: | 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.
: | 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.

Except that's wrong, and further messages in the thread showed.  This
example shows that we don't support it in printf, since the above
example does ***NOT*** give +Inf, but rather whatever 2*DBL_MAX is.
The exponent range is ***NOT*** lost until printf truncates it, as my
test programs showed.

The one issue that I've seen is

long double a = 1.0L;
long double b = 1.0L + LDBL_EPSION
if (a == b) abort();

which is what I'm trying to fix. (note, 1.0L must be spelled
oneld() and long double oneld() { return (1.0L);}) to avoid the
optimizer getting it right.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread Garrett Wollman
On Wed, 30 Oct 2002 17:01:54 -0700 (MST), M. Warner Losh [EMAIL PROTECTED] said:

 I think I don't understand what you are saying at all.  It doesn't
 seem top jive with the rest of the messages in this thread.

Of course not, it's Terry ``Irrelevant Tangent'' Lambert you're taking about.

-GAWollman


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread Garrett Wollman
On Wed, 30 Oct 2002 20:29:16 -0500 (EST), Garrett Wollman [EMAIL PROTECTED] said:

[rude snipe deleted...]

Sorry, that was un-called-for (and was intended to be a private
message to Warner).

-GAWollman


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread Terry Lambert
M. Warner Losh wrote:
 : The compiler must emit instructions to truncate and set flags, as
 : well as generating pseudo-exceptions (should they be called for)
 : in the case that the storage is in registers bigger than the memory
 : backing them.  IT doesn't do this.
 
 I think I don't understand what you are saying at all.  It doesn't
 seem top jive with the rest of the messages in this thread.

I mean that if there is a difference between doing the math in
registers vs. doing it in memory (or storing it in memory and
pulling it back in the registers, then you have two options:

1)  Don't late-bind the FPU registers in the kernel, and take
a huge performance hit

2)  Have the compiler generate code that will give the same
results as if the store and load had taken place

The gcc people argue that it's the kernel's job (do #1, not #2),
and the kernel argues that it's the compilers job (do #2, not #1).


 Except that's wrong, and further messages in the thread showed.

I didn't see a printf involved; Bruce was talking, as far as I
could tell, about a direct compare, with no printf() involved.
Are you maybe mixing this up with the paranoia tests?

The problem is that the double didn't give +Inf, like it should
have, because the rvalue was incorrectly promoted to long
double, instead of staying double, and overflowing (Bruce?
Correct this if it's wrong, please).

 This
 example shows that we don't support it in printf, since the above
 example does ***NOT*** give +Inf, but rather whatever 2*DBL_MAX is.

That would be +Inf for double values... a 53 bit +Inf.  But
since it's being improperly treated as a 64 bit value, you don't
get +Inf when you *should*.  I think this case is about *not*
getting an error you should get.


 The exponent range is ***NOT*** lost until printf truncates it, as my
 test programs showed.

Exactly!  And it *should* be, because a double *is not* the same
precision as a *long double*.  A validation suite that tested edge
conditions to ensure that there was a precision failure where there
was supposed to be, and didn't get an expected failure, would mean
it's broken.


 The one issue that I've seen is
 
 long double a = 1.0L;
 long double b = 1.0L + LDBL_EPSION
 if (a == b) abort();
 
 which is what I'm trying to fix. (note, 1.0L must be spelled
 oneld() and long double oneld() { return (1.0L);}) to avoid the
 optimizer getting it right.

Heh.  I saw that discussion; I think that's seperate.

The main issue that I think is outstanding is that you can't get
both exception behaviour and non-exception behaviour, and it is
going to have to be the compiler's job to force the issue, because
it can't dictate implementaiton to the host OS.

One problem is the initialization of the hardware (there was already
a flags change for an initialization difference from what the compiler
expects suggested in this thread -- to my mind, it's a workaround for
the gcc generating header files, instead of taking the system's word
for it).

-- Terry

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Terry Lambert [EMAIL PROTECTED] writes:
:  This
:  example shows that we don't support it in printf, since the above
:  example does ***NOT*** give +Inf, but rather whatever 2*DBL_MAX is.
: 
: That would be +Inf for double values... a 53 bit +Inf.  But
: since it's being improperly treated as a 64 bit value, you don't
: get +Inf when you *should*.  I think this case is about *not*
: getting an error you should get.

Terry you are wrong.  This has to do with the RANGE not the PRECISION
of the floating point number.  It is ***NOT*** +Inf.


:  The exponent range is ***NOT*** lost until printf truncates it, as my
:  test programs showed.
: 
: Exactly!  And it *should* be, because a double *is not* the same
: precision as a *long double*.  A validation suite that tested edge
: conditions to ensure that there was a precision failure where there
: was supposed to be, and didn't get an expected failure, would mean
: it's broken.

You are wrong.  You are confusing the precision of the mantissa with
the range of the exponent.

Printf should *NOT* truncate to double before converting to print.
That's a bug too.

:  The one issue that I've seen is
:  
:  long double a = 1.0L;
:  long double b = 1.0L + LDBL_EPSION
:  if (a == b) abort();
:  
:  which is what I'm trying to fix. (note, 1.0L must be spelled
:  oneld() and long double oneld() { return (1.0L);}) to avoid the
:  optimizer getting it right.
: 
: Heh.  I saw that discussion; I think that's seperate.

Yes.

: The main issue that I think is outstanding is that you can't get
: both exception behaviour and non-exception behaviour, and it is
: going to have to be the compiler's job to force the issue, because
: it can't dictate implementaiton to the host OS.

I don't follow.

: One problem is the initialization of the hardware (there was already
: a flags change for an initialization difference from what the compiler
: expects suggested in this thread -- to my mind, it's a workaround for
: the gcc generating header files, instead of taking the system's word
: for it).

I don't follow.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-30 Thread Terry Lambert
M. Warner Losh wrote:
 :  This
 :  example shows that we don't support it in printf, since the above
 :  example does ***NOT*** give +Inf, but rather whatever 2*DBL_MAX is.

[ ... ]

 Terry you are wrong.  This has to do with the RANGE not the PRECISION
 of the floating point number.  It is ***NOT*** +Inf.

I await an explanation of how you can fit 2*DBL_MAX into a double,
which has a range of DBL_MIN..DBL_MAX.


 You are wrong.  You are confusing the precision of the mantissa with
 the range of the exponent.

I'm talking about the range of the double itself.  When you round it,
you don't jsut truncate the bits off the mantissa, you also increase
the exponent.


 Printf should *NOT* truncate to double before converting to print.
 That's a bug too.

I agree with the printf statement, but I don't see where printf is
coing into the discussion.


 Yes.
 
 : The main issue that I think is outstanding is that you can't get
 : both exception behaviour and non-exception behaviour, and it is
 : going to have to be the compiler's job to force the issue, because
 : it can't dictate implementaiton to the host OS.
 
 I don't follow.

I think that a number that's a 64 bit mantissa reaised to an exponent
N takes a larger N if you have only 53 bits of mantissa, if you want
to represent the same value.


 : One problem is the initialization of the hardware (there was already
 : a flags change for an initialization difference from what the compiler
 : expects suggested in this thread -- to my mind, it's a workaround for
 : the gcc generating header files, instead of taking the system's word
 : for it).
 
 I don't follow.

The obvious example in the FreeBSD case is the default value of the
expression (fpgetprec() == FP_PE).  The compiler is not permitted to
assume, one way or the other; it has to do runtime testing, at the
time you compile the compiler, to comply with a completely strict
interpretation of C99 (IMO).

It would have been nice if C99 provided a way to list the host
defaults for use in compiling the compiler, since the host and the
compiler have to cooperate, but there's no way to do this at run
time because the standard failed to assign responsibility totally
to the compiler vendor or totally to host OS.

The closest possible approach will be for the compilation of the
compiler to make some runtime tests to find out about the host
environment.

Really, it comes down to whether the host, or the compiler, owns
math.h and float.h.  According to my reading of C99, ownership is
split between them.  This kind of implies that the compiler gets
to generate them however it wants, but that the host gets to
dictate operation to the compiler, based on runtime tests the
compiler is required to run to get the information.

Since gcc supplies the crt0, it could always call fpsetprec(FP_PE);
before starting to force the hardware into the compiler's preferred
state.  That's one answer, which makes it really hard to have a gcc
and a TenDRA compiler that give the same results, if they happen to
pick different defaults.  The FP-using code would have to take all
this into account, and be prepared to deal with all the possible
allowed values.


One workaround to this really ugly situation would be to define a
host specific header file that's included by a host independent
math.h and float.h to control its behaviour on a per-host basis,
and then expect the host OS vendor to provide it, or the compiler
to dig it out itself.  It's better for the vendor to provide it,
if the vendor wants any say in the matter at all (i.e. if the crt0
is going to call fpsetprec() to force the initial state, then why
would the OS define an initial state that wasn't what the compiler
wanted, so it could skip the set call?, etc.).

-- Terry

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support (was Re: libstdc++ does notcontain fabsl symbol)

2002-10-29 Thread Loren James Rittle
 Claiming 53 bits but supporting 64, and then not raising an exception
 and/or giving a NaN or INF result on overflow to the 54th bit is
 broken.  If you do this, you will fail runtime validation suites.

Huh?  The 53-bit quantity refers to the mantissa not the exponent.
Unless I'm sorely confused, the only IEEE exceptions you could be
speaking about is inexact; Inf and NaN don't come into play.  In any
event:

As I outlined, in this case (where we advertised 53-bit precision but
the user forced 64-bit precision - it was not precise for you to use
the word supporting since that does not characterize the situation I
was speaking about properly), the user will have explicitly made a
call to change the default precision as conveyed in the system header.
At that point, I don't know why the user should be able to expect that
the published values in float.h are still valid.  Do these
validation suites typically run with a call to override the precision
setting in the IEEE FP control word?  Doubtful (or if they do, they
know what they are doing; just as application code that monkeys with
the control register would have to).  I.e. the test suite would be
running against the published limits.h which at the moment should be:

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

(All other published LDBL_ constants are derivable from these.)

since they match the default FP control word setting on FreeBSD/i386.

 I don't think that any amount of hand-waving will turn it into a
 compiler-only issue.

I am not trying to handwave anything.  The currently published
float.h (both before and after recent patch) is what is attempting
to handwave something.  It doesn't match the hardware settings.  That
patch it just received fixed one thing (exponent range) but broke
another (precision/epsilon).  More than anything, I am attempting to
have that file written exactly to match the default hardware setup.
Since there is exactly one default hardware setup for any particular
booted system, it seems possible to do.

If I were doing what is claimed, I would have fixed the issue in gcc
mainline without consulting FreeBSD-side experts.  Perhaps we should
just leave it broken in the FSF tree and let an expert sort it out
when they import gcc 3.3 into FreeBSD.  However, it seemed reasonable
to me to fix the issues exposed by the gcc infrastructure change ASAP...

 I'd like to see Bruce's issues with the 64 bit support taken care
 of with long double (and the implicit cast that occurs in the one
 case that Bruce complained about in his email, where there is *too
 much* precision on the rvalue, which is a computation of dobule
 operands done in long double form, with a double result).

I think I now understand Bruce's point.  There are two issues: (a)
incorrect double-rounding (once to the precision of extended double in
register and another to double when moved to memory allocated for
double); (b) non-exact comparisons where might otherwise be expected
by programmers even if not absolutely guaranteed by IEEE 754.

To anyone that wishes to understand it, start reading page 249 of this
version of _What Every Computer Scientist Should Know About
Floating-Point Arithmetic_ http://www.validlab.com/goldberg/paper.ps

FYI, by default, FreeBSD/i386 uses technique 4 on page 260 to
circumvent these issues. (There is a proof earlier that fully explains
why double-rounding doesn't affect double-float conversions on i386.)

Now, in case anyone cares, gcc 3.3 will expose the C99 FLT_EVAL_METHOD
macro (set to 2 for FreeBSD/i386) and related float_t and double_t
types (which will both map to long double to represent the destination
of intermediate results otherwise beyond the user's control).  Given
the extended range of the exponent of a double or float in an i386 HW
FP register; I believe that is correct.

Regards,
Loren

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-29 Thread Loren James Rittle
In article [EMAIL PROTECTED] imp writes:

 This works.  I'm not sure why this isn't the default.  It looks like
 we have hacks in the local tree to do this, which is why I thought
 that it worked great by default

 This is true too.  See the fpsetprec() call that I had to add to make
 things work above.

Yes, I know about that call.  I conditionally added it to at least one
gcc i386 FP test case that assumed 64-bit precision.  However, the
system header float.h is suppose to reveal the FP hardware as it is
configured not as some user could litter their code to make it so, no?

 Yes.  The standard didn't anticipate the fp hardware that intel made.

C89, perhaps (although given the timing, I'm skeptical).  C99, no way.

 One could do something like:

 #define LDBL_EPSILON (fpgetprec() == FP_PE ? _LDBL_EPSILON :  DBL_EPSILON)

 But as you said, this isn't a compile time constant.  I'm not sure
 that it would matter in any real context.  I don't think that you can
 do floating point in the preprocessor...

This proposal isn't bad IMHO.  It would clearly explain to the gcc
team what type of FP support we'd want even if not in full compliance
with the standard text.  And, to avoid all compliance problems, perhaps:

#if !defined(_ANSI_SOURCE)  !defined(_POSIX_SOURCE)  !defined(__STRICT_ANSI__)
// for i386, match default as expressed in __INITIAL_NPXCW__
#define LDBL_MANT_DIG 53
#define LDBL_EPSILON 2.2204460492503131E-16
[...]
// changing LDBL_MANT_DIG subtly changes every value not just LDBL_EPSILON)
#else
// Assume something would have to be done to avoid including ieeefp.h
#define LDBL_MANT_DIG (fpgetprec() == FP_PE ? _LDBL_MANT_DIG :  DBL_MANT_DIG)
#define LDBL_EPSILON (fpgetprec() == FP_PE ? _LDBL_EPSILON :  DBL_EPSILON)
[...]
#endif

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-29 Thread Bruce Evans
On Mon, 28 Oct 2002, M. Warner Losh wrote:

 In message: [EMAIL PROTECTED]
 Loren James Rittle [EMAIL PROTECTED] writes:

 This works.  I'm not sure why this isn't the default.  It looks like
 we have hacks in the local tree to do this, which is why I thought
 that it worked great by default

Better change FreeBSD to match the unhacked version :-).

 : gcc 3.3 will support a framework in which such changes would be easy
 : to convey at compile-time but, to my knowledge, there is no support
 : yet to obtain e.g. the precision setting at run-time.  I.e. float.h

FreeBSD (on i386's) has fpgetprec() to get it and fpsetprec() to set it,
but these are nonstandard and won't become standard.  They don't exist
on most or all non-i386's now, unlike fpget/setround() which will become
the standard feget/setround().

 : is now completely dynamically created at compile-time based on the
 : exact knowledge within gcc of the FP hardware; but it is static
 : w.r.t. eventual run-time.  It does not know how to effectively export
 : a function ala FreeBSD/alpha's float.h:
 :
 : #define FLT_ROUNDS  __flt_rounds()

I hope an alpha person will explain the details of this.  Where is the
default configured?

 : One issue, the standard says that various macros related to float
 : limits are constant expressions (as may be used to influence the
 : preprocessor?).  The above construct doesn't conform but I understand
 : the intent.

The standard has a special exception for FLT_ROUNDS.

 Yes.  The standard didn't anticipate the fp hardware that intel made.

Actually, it didn't support the hardware.  The hardware was implemented
long before the (C) standard.

 One could do something like:

 #define LDBL_EPSILON (fpgetprec() == FP_PE ? _LDBL_EPSILON :  DBL_EPSILON)

 But as you said, this isn't a compile time constant.  I'm not sure

The standard doesn't have a special exception for anything in float.h
except FLT_ROUNDS :-.

 that it would matter in any real context.  I don't think that you can
 do floating point in the preprocessor...

Not in non-broken preprocessors.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support (was Re: libstdc++ does notcontain fabsl symbol)

2002-10-28 Thread Loren James Rittle
In article [EMAIL PROTECTED],
Bruce Evans[EMAIL PROTECTED] writes:

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

 53 mantissa bits
 1024 max exponent

 No need.  I prefer to keep the 53-bit precision for now, but fix the
 exponents.

OK.  This was the resolution that made sense to us on the gcc side
(RTH, quickly; myself, some time to get up to speed).  FYI, the system
header patch that was actually checked in claims 64-bit precision.  Oh
well, at least the exponents are now correct.  ;-)  FYI, here is the
exact test case which shows the new value for LDBL_EPSILON (derived
directly from LDBL_MANT_DIG) is wrong verses the hardware default:

#include float.h

// Force run-time computation of math (beware, inlining oneld will defeat this).
long double oneld() { return 1.0L; }

main ()
{
  long double a = oneld();
  long double b = oneld() + LDBL_EPSILON;
  if (a == b) abort ();
}

On ref5 against gcc 3.2.X (as installed as system compiler), with the
latest float.h, it crashes.  By specification, this is one FP test
involving exact equality that is guaranteed to work (and report false,
in this case).

 Hopefully the precision won't be hard-coded into gcc in such
 a way as to completely break changing the precision at runtime.  I think
 it should affect (only) constant folding.  The issues are very similar
 to the ones with changing the rounding mode at runtime (C99 compilers
 shouldn't do constant folding in #pragma STDC FENV_ACCESS ON sections
 if the correct result might depend on the FP environment).

This exchange has been quite useful.  I see that issue.
Unfortunately, changing precision of the FP hardware would seem to
change the value of epsilon that is exported, both in classic C
headers and C++ limits (the latter being how I originally took any
interest in this matter since a C++ test case started failing after
the new real.c code was installed).

gcc 3.3 will support a framework in which such changes would be easy
to convey at compile-time but, to my knowledge, there is no support
yet to obtain e.g. the precision setting at run-time.  I.e. float.h
is now completely dynamically created at compile-time based on the
exact knowledge within gcc of the FP hardware; but it is static
w.r.t. eventual run-time.  It does not know how to effectively export
a function ala FreeBSD/alpha's float.h:

#define FLT_ROUNDS  __flt_rounds()

One issue, the standard says that various macros related to float
limits are constant expressions (as may be used to influence the
preprocessor?).  The above construct doesn't conform but I understand
the intent.

I will advise RTH about that type of issue.  Fortunately, in this
case, I think advertising 53-bit precision but really using 64-bit
precision (i.e. application code overrode system default) doesn't
invalidate the advertised epsilon, in terms of how it is used by the
application.

More generally, I will ask if gcc can support these details as gained
from the run-time environment instead of hard-coded defaults.  This
would be useful for all free OSes not just FreeBSD running on hardware
with such flexible FP hardware.

Any more comments, before I start work on the gcc mainline side of
things?

Thanks,
Loren

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support (was Re: libstdc++ does notcontain fabsl symbol)

2002-10-28 Thread Terry Lambert
Loren James Rittle wrote:
 I will advise RTH about that type of issue.  Fortunately, in this
 case, I think advertising 53-bit precision but really using 64-bit
 precision (i.e. application code overrode system default) doesn't
 invalidate the advertised epsilon, in terms of how it is used by the
 application.
 
 More generally, I will ask if gcc can support these details as gained
 from the run-time environment instead of hard-coded defaults.  This
 would be useful for all free OSes not just FreeBSD running on hardware
 with such flexible FP hardware.
 
 Any more comments, before I start work on the gcc mainline side of
 things?

Claiming 53 bits but supporting 64, and then not raising an exception
and/or giving a NaN or INF result on overflow to the 54th bit is
broken.  If you do this, you will fail runtime validation suites.

The C99 standard intentionall gets its information from float.h ...
rather than it's float.h from the information, as you are doing ...
because this is a combination host OS *and* compiler issue.

I don't think that any amount of hand-waving will turn it into a
compiler-only issue.

I'd like to see Bruce's issues with the 64 bit support taken care
of with long double (and the implicit cast that occurs in the one
case that Bruce complained about in his email, where there is *too
much* precision on the rvalue, which is a computation of dobule
operands done in long double form, with a double result).

-- Terry

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-28 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Terry Lambert [EMAIL PROTECTED] writes:
: I'd like to see Bruce's issues with the 64 bit support taken care
: of with long double (and the implicit cast that occurs in the one
: case that Bruce complained about in his email, where there is *too
: much* precision on the rvalue, which is a computation of dobule
: operands done in long double form, with a double result).

I'd like to see these fixed too.  Now that I understand why I was
deluded into thinking that he was mistaken, I'd like to get these
issues resolved.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-26 Thread David Schultz
Thus spake M. Warner Losh [EMAIL PROTECTED]:
 : No.  You should assume that for i386, at least, that long double will
 : have the right LDBL_ constants.  I've had them in my local tree for
 : about 3 months now and just haven't found the time to commit to
 : -current.  I'll find the time right now.
 
 I've committed the fix to the tree.  NetBSD uses these numbers, and
 I've been using these numbers on a large number of systems that we
 maintain at timing solutions (they were added to our local tree prior
 to the 4.5 release, and we've built hundreds of ports since then w/o
 any issues).  I've had them in my own personal p4 tree for 3 months
 with similar results.

I submitted patches for this back in May.  Could you please close
i386/38288?  While you're at it, you should probably patch IA64 as
well.  Other supported platforms should be okay, I think.  TIA.

(Every time this happens, someone comes along a month later and
tells me that _I'm_wrong_ about there ever being a bug.)

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-26 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
David Schultz [EMAIL PROTECTED] writes:
: Thus spake M. Warner Losh [EMAIL PROTECTED]:
:  : No.  You should assume that for i386, at least, that long double will
:  : have the right LDBL_ constants.  I've had them in my local tree for
:  : about 3 months now and just haven't found the time to commit to
:  : -current.  I'll find the time right now.
:  
:  I've committed the fix to the tree.  NetBSD uses these numbers, and
:  I've been using these numbers on a large number of systems that we
:  maintain at timing solutions (they were added to our local tree prior
:  to the 4.5 release, and we've built hundreds of ports since then w/o
:  any issues).  I've had them in my own personal p4 tree for 3 months
:  with similar results.
: 
: I submitted patches for this back in May.  Could you please close
: i386/38288?  While you're at it, you should probably patch IA64 as
: well.  Other supported platforms should be okay, I think.  TIA.
: 
: (Every time this happens, someone comes along a month later and
: tells me that _I'm_wrong_ about there ever being a bug.)

If I hadn't been using long doubles, day in and day our, for the past
two years, I'd likely have agreed with you.  However, I've had to look
into why weird things happen with long doubles a lot, and have found
in general they work pretty good.

I'll ask Peter Wemm about IA64.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-25 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
Loren James Rittle [EMAIL PROTECTED] writes:
: Yet, the FP hardware is actually configured by default to provide
: `long double' as:
: 
: #define LDBL_MANT_DIG   53
: #define LDBL_MIN_EXP(-16381)
: #define LDBL_MAX_EXP16384
: 
: Indeed, FP code using long double generated by gcc 2.95.X, installed
: as the FreeBSD 4 system compiler, uses the full exponent range of
: -16381 to 16384.  However, printf(), etc loses on that exponent range
: and reports Inf.  I suspect this is why the system header misreports
: the FP hardware, thus the header describes the largest printable long
: double value, not the largest that could be held in a calculation.

I have patches to fix these constants, but not to fix printf, and co,
to really support the full precision of long double.  Even NetBSD
doesn't do that.

: 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?

No.  You should assume that for i386, at least, that long double will
have the right LDBL_ constants.  I've had them in my local tree for
about 3 months now and just haven't found the time to commit to
-current.  I'll find the time right now.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-25 Thread M. Warner Losh
In message: [EMAIL PROTECTED]
M. Warner Losh [EMAIL PROTECTED] writes:
: : 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?
: 
: No.  You should assume that for i386, at least, that long double will
: have the right LDBL_ constants.  I've had them in my local tree for
: about 3 months now and just haven't found the time to commit to
: -current.  I'll find the time right now.

I've committed the fix to the tree.  NetBSD uses these numbers, and
I've been using these numbers on a large number of systems that we
maintain at timing solutions (they were added to our local tree prior
to the 4.5 release, and we've built hundreds of ports since then w/o
any issues).  I've had them in my own personal p4 tree for 3 months
with similar results.

Warner

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support (was Re: libstdc++ does notcontain fabsl symbol)

2002-10-25 Thread Bruce Evans
On Thu, 24 Oct 2002, Loren James Rittle wrote:

  ...  Anyways, that work exposed some issues.
 ...
 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_EXP16384

  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:

Oops.  I did look at the bits, but I looked more closely at gdb's display
of the value which is broken (it says +inf).  Apparently gdb uses the
host's FP too much.

 #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.

Yes, this example is as convincing as examining the (right :) bits.

  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

No need.  I prefer to keep the 53-bit precision for now, but fix the
exponents.  Hopefully the precision won't be hard-coded into gcc in such
a way as to completely break changing the precision at runtime.  I think
it should affect (only) constant folding.  The issues are very similar
to the ones with changing the rounding mode at runtime (C99 compilers
shouldn't do constant folding in #pragma STDC FENV_ACCESS ON sections
if the correct result might depend on the FP environment).

  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.

Ah.  I was a little surprised to find it still in 3.2.  It is not so
much buggy as dysfunctional in a cross compiler.  It has to run on the
target somehow to work.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support

2002-10-25 Thread Bruce Evans
On Fri, 25 Oct 2002, M. Warner Losh wrote:

 In message: [EMAIL PROTECTED]
 Bruce Evans [EMAIL PROTECTED] writes:
 : On Thu, 24 Oct 2002, Loren James Rittle wrote:
 :
 :  ...  Anyways, that work exposed some issues.
 : 
 :  We have this in the system header:
 : 
 :  #define LDBL_MANT_DIG   DBL_MANT_DIG
 :  #define LDBL_MIN_EXPDBL_MIN_EXP
 :  #define LDBL_MAX_EXPDBL_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).

 That is incorrect.  long double are supported at runtime.  We use them
 all the time and do get numbers outside the range of normal doubles.
 There are some minor rounding issues with them, but those issues
 result in a 1-2 bit rounding error in most of the cases I've looked at
 in extreme detail.  Such rounding errors do limit the effective range
 to about 62 bits, but that's still a lot better than 53 bits you get
 with doubles.

Um, you get the FreeBSD default of 53 bits on i386's unless you change
the FP environment using fesetprec(3) or equivalent.  This thread
highlighted the point that you get a larger exponent range even with
53-bit precision.

 : 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.
 : 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.

 that's not true.  y is not +Inf, but prints as +Inf because printf and
 friends do not support outside the range of a double.

Oops (see another reply).

 : Not really.  Assembly is still required to get full control over precision.
 : I'm still waiting for (C) language support to catch up.  Been waiting for
 : about 14 years so far.  C99 clarified the semantics of floating point
 : precision but is not supported by gcc (yet?).

 This is not true.

No oops.   gcc has no support for the C99 FENV_ACCESS stuff and still
doesn't clip excess precision on assignment.  These are easy to implement
... provided efficiency is not required.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Lack of real long double support (was Re: libstdc++ does not contain fabsl symbol)

2002-10-24 Thread Loren James Rittle
 Note that while you're adding the C99 math stuff, you
 might want to fix up float.h, which is just wrong about long
 doubles (see PR i386/38288).

 Right, I should have said no one has started committing C99 math
 functions.

(Reading this exchange reminded me that I promised fellow gcc
developers to check on this issue with FreeBSD developers.)

The gcc mainline (what will become 3.3) recently got a new
implementation of ``software floating point emulation'' (contained in
gcc/real.[hc] which is used to format all compile-time FP constants,
etc).  Along with that change, the compiler wants to provide a copy of
float.h generated from its own knowledge of FP hardware instead of
sucking information from /usr/include/float.h, as it had done in past
gcc releases.  I know that when we install gcc as the FreeBSD system
compiler, we don't bother with such header files provided from gcc
(but, for the moment please consider that people might build
cross-compilers to FreeBSD and please consider that we test future
releases of gcc as might be used as the FreeBSD system compiler from
FSF sources).  Anyways, that work exposed some issues.

We have this in the system header:

#define LDBL_MANT_DIG   DBL_MANT_DIG
#define LDBL_MIN_EXPDBL_MIN_EXP
#define LDBL_MAX_EXPDBL_MAX_EXP
[...]

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

#define LDBL_MANT_DIG   53
#define LDBL_MIN_EXP(-16381)
#define LDBL_MAX_EXP16384

Indeed, FP code using long double generated by gcc 2.95.X, installed
as the FreeBSD 4 system compiler, uses the full exponent range of
-16381 to 16384.  However, printf(), etc loses on that exponent range
and reports Inf.  I suspect this is why the system header misreports
the FP hardware, thus the header describes the largest printable long
double value, not the largest that could be held in a calculation.

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?

Unless someone strongly prefers otherwise, the I lean towards wanting
to describe the default FP hardware setup exactly and assume that libc
changes to properly support long double stdio, etc will follow at some
point.

However, that also brings to mind: Are we happy with the current
default FP hardware setup especially if support for long double is to
be improved?  At the moment we support long double in name only.
There is no extra dynamic range over a double; as might be implied
(and allowed by the hardware).

Also, as an aside, having just learned everything there is to know
about IEEE FP from a witty 80-slide presentation on the WWW by one of
the original designers of the spec@Berkeley, I'd say that he would be
sad that we default to use 53-bit precision mode.  I'd say that it is
dumb to claim we even support long double unless we change that to
64-bit precision mode...

Regarding the comment in sys/i386/include/npx.h:

 * 64-bit precision often gives bad results with high level languages
 * because it makes the results of calculations depend on whether
 * intermediate values are stored in memory or in FPU registers.

This is pure bunk when considered in broad context.  Using 53-bit
precision mode with high level languages while making actual
calculations yields more outright undetectable precision-related
errors due to algorithm design by non-numerical analysts.  I know
which error I'd rather *not* find in my naively-written and compiled
FP code.

People that write their FP code to correctly use epsilon (the one
appropriate for the type of the float they are using) should never see
this problem, no?  I don't see why FreeBSD should cater to people that
don't know how to write FP code properly (i.e. anyone that expected
exact results across compilation switches, etc) at the expense of
being able to write code that fully utilizes the best mode available
from the CPU.

People that absolutely want to avoid the problem of spilling from
register to memory truncation changing with optimization level may
feel free to allocate long doubles instead of doubles.  Problem solved.

Anyways, that is my quick speech in favor of change.  I will help
commit bits to the FSF gcc tree that supports whatever people want to
do.  It is easy to support one FP model for FreeBSD 4 and another for
FreeBSD 5.

Regards,
Loren

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Lack of real long double support (was Re: libstdc++ does notcontain fabsl symbol)

2002-10-24 Thread Bruce Evans
On Thu, 24 Oct 2002, Loren James Rittle wrote:

 ...  Anyways, that work exposed some issues.

 We have this in the system header:

 #define LDBL_MANT_DIG   DBL_MANT_DIG
 #define LDBL_MIN_EXPDBL_MIN_EXP
 #define LDBL_MAX_EXPDBL_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).

 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).

 #define LDBL_MIN_EXP(-16381)
 #define LDBL_MAX_EXP16384

 Indeed, FP code using long double generated by gcc 2.95.X, installed
 as the FreeBSD 4 system compiler, uses the full exponent range of
 -16381 to 16384.  However, printf(), etc loses on that exponent range
 and reports Inf.  I suspect this is why the system header misreports
 the FP hardware, thus the header describes the largest printable long
 double value, not the largest that could be held in a calculation.

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.
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.

 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 don't know
when enquire.c actually gets used.  The FreeBSD build just ignores it
and uses src/sys/${MACHINE_ARCH}/float.h.  My first encounter with this
bug suite was near enquire.c 12-14 years ago.  enquire gave different
results for -msoft-float and hardware FP because my soft-float libraries
only had 53-bit precision but hardware FP used 64-bit precision.

 ...
 However, that also brings to mind: Are we happy with the current
 default FP hardware setup especially if support for long double is to
 be improved?  At the moment we support long double in name only.
 There is no extra dynamic range over a double; as might be implied
 (and allowed by the hardware).

Not really.  Assembly is still required to get full control over precision.
I'm still waiting for (C) language support to catch up.  Been waiting for
about 14 years so far.  C99 clarified the semantics of floating point
precision but is not supported by gcc (yet?).

 Also, as an aside, having just learned everything there is to know
 about IEEE FP from a witty 80-slide presentation on the WWW by one of
 the original designers of the spec@Berkeley, I'd say that he would be
 sad that we default to use 53-bit precision mode.  I'd say that it is
 dumb to claim we even support long double unless we change that to
 64-bit precision mode...

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.

 Regarding the comment in sys/i386/include/npx.h:

  * 64-bit precision often gives bad results with high level languages
  * because it makes the results of calculations depend on whether
  * intermediate values are stored in memory or in FPU registers.

 This is pure bunk when considered in broad context.  Using 53-bit
 precision mode with high level languages while making actual
 calculations yields more outright undetectable precision-related
 errors due to algorithm design by non-numerical analysts.  I know
 which error I'd rather *not* find in my naively-written and compiled
 FP code.

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.

 People that write their FP code to correctly use epsilon (the one
 appropriate for the type of the float they are using) should never see
 this problem, no?

No.  They would see strange behaviour cause by compiler bugs.

 I don't see why FreeBSD should cater to people that
 don't know how to write FP code properly (i.e. anyone that expected
 exact results across compilation switches, etc) at the expense of
 being able to write code that fully utilizes the best mode available
 from the CPU.

IEEE754 provides many guarantees about 

Re: Lack of real long double support (was Re: libstdc++ does notcontain fabsl symbol)

2002-10-24 Thread Loren James Rittle
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_EXPDBL_MIN_EXP
 #define LDBL_MAX_EXPDBL_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_EXP16384

 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