Hmmm, I've never thought that two simple additions would lead to such
a riot... :-)
First of all: Even after re-reading the report I can't see that IEEE
arithmetic is *required* by it. The representation of floating point
values is explicitly stated as "implementation-defined", only the range
and precision "should" at least cover IEEE floats/doubles. I can't find
paragraphs, e.g. stating what `NaN < 3.1415' should yield, if there is
a mathematically wonderful thing like a negative zero, what the rounding
behaviour is, etc. (As an aside: I *hate* standards which are not freely
available, I've never seen a real IEEE-754 document. A $4000 annual
subscription price for a single person is ridiculous, and I would probably
have slight problems persuade my company to buy the $40.000 enterprise
subscription...)
Nevertheless, there seems to be some consensus that optimization should
not change the outcome of a computation. Note that GCC's -O flag *does*
change it, at least if -ffloat-store is not given in addition. The newly
introduced GHC option -fstrictfp is intended to give back that guarantee,
but after this discussion I feel that it should be the default behaviour.
A short description of GHC's internal handling of floating point values
and the accompanying problems:
* GHC uses IEEE arithmetic for Float and Double.
* Floating point values are internally represented as Rationals, which
is completely OK for literals given by the programmer. It is flexible
enough to make cross-compilation possible (which GHC currently can't
do for other reasons), a possibility which would be lost if Float/Double
were used for this, so this approach would be a step in the wrong
direction.
* Floating point constant folding is done only for simple operations
like +, -, <, some coercions, etc. To handle precision/range problems,
the Rationals are converted to Float/Double and back to Rational
before and after those operations. The operations themselves are the
usual ones on Rationals. This is wrong in a cross-compilation scenario,
but this issue is isolated in a single function, which could easily be
changed if the simplifier was parameterized by the target architecture.
Without -fstrictfp, this squashing is not done, so you can get more
exact results.
* The above approach via "squashing" is probably not completely IEEE
conforming, so the right thing would probably be IEEE arithmetic on
Rationals (or a similar type, this doesn't matter). Does somebody
already have such a thing? Even the basic arithmetic operations would
help, and performance is not critical, only correctness.
Cheers,
Sven