procmail
[Top] [All Lists]

Re: Weighted expressions and small values

1999-03-28 22:31:41
At 12:19 PM 3/27/99 -0600, Philip Guenther wrote:
"John D. Hardin" <jhardin(_at_)wolfenet(_dot_)com> writes:

[snip]

Why the seemingly random jumps to zero (or a fraction that is being
rounded down to zero for display purposes)? Is this some artifact of
the representation of double-precision floating point values in C?

Changing the minus signs to plus signs yields the same results with
positive numbers.

What am I not seeing?

I've stared at the code and after trying some stuff, I can say that
it's either a bug in gcc, gas, or the iX86 FPU itself.

No bug this... it's a feature of the C language!  Been there before  :-)
You're seeing the effect of a sentence in the Standard: "The values of
floating operands and of the results of floating expressions may be
represented in greater precision and range than that required by the
type; the types are not changed thereby."

To be specific, but working from memory so this could be a buggy
description :-), the X86 uses 80-bit floating point registers to do
calculations, which for "double" get stored into 64-bit memory locations.
Thus, truncation occurs whenever storing occurs; when results persist in
a register, the 80 bit value there may well be different than if stored
into a 64-bit number and then reloaded.

The assembly
language looks good to me, so I don't _think_ it's a bug in gcc, but I
could be wrong -- it's been too long since I handcoded for an i387 and
I don't know what tricks gas is playing (it's _got_ be sticking in
fwait instructions, so I know _some_ magic is being invoked...).  I've
sent in a bug report to the GAS people so they can look at it.

Anyway, the workaround is to change lines 914 and 915 of src/misc.c from:

                             ;{ double nweight;
                                if((nweight=weight*weight)<oweight&&oweight<1)

Uh huh... this sort of liberty works OK with integers, but the 64-bit
number stored into nweight may not be the 80-bit number compared with oweight.

to:
                             ;{ double nweight=weight*weight;
                                if(nweight<oweight&&oweight<1)

I would seriously consider declaring nweight to be "volatile double" here
as well, to prevent an optimizer from repeating what happened with the
previous code.

then recompile.  I've checked this change in so it'll appear in the
next snapshot.


Philip Guenther


Cheers,
Stan Ryckman

<Prev in Thread] Current Thread [Next in Thread>