There is an issue about floating point code in Go that I don't recall
that we've ever really settled. That is: how should Go programs
behave with regard to precisely predictable FP behaviour?
There are two basic historical approaches. In C/C++, there are no
promises about FP behaviour at all. Different processors are expected
to produce different results. This is the approach that leads many
programmers to believe statements like "you must never compare
floating point values for equality" (this statement is false).
Java's philosophy, on the other hand, is write once, run anywhere.
That means that a Java program is supposed to produce identical
results whereever it run. Java specifies IEEE-754 floating point
values, and says "The Java programming language requires that
floating-point arithmetic behave as if every floating-point operator
rounded its floating-point result to the result precision."
This means that a Java program has precisely predictable floating
point behaviour, and people who understand how floating point works
can with confidence compare floating point values for equality.
However, Java's approach notoriously led to a strong criticism by
Kahan: How Java's Floating-Point Hurts Everyone Everywhere, at
http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf .
I won't get into the details of Kahan's criticisms, but one that I
think we need to discuss for Go is whether Go expects the same results
for floating point evaluation on all processors. The case that arises
most often in practice is whether the generated code is permitted to
use a floating point fused multiply-and-add instruction. Such an
instruction is faster and is numerically more precise. However, it's
not hard to construct calculations in which it produces a different
result compared to rounding the multiply and add operations
separately.
There are several issues we need to pin down for Go's floating point
format, but let's start with that one: is a Go compiler permitted to
generate a fused multiply-and-add instruction that does not round the
intermediate operation?
The immediate context is
http://golang.org/issue/9066 (which is
unfortunately a confusing mix of several different issues) and a
proposed patch to the ken/cplx2.go test to make it pass on S/390
processors
(
https://groups.google.com/d/msg/gofrontend-dev/5erZWm2lNI0/ajFz0c7tO5cJ).
My first reaction was that FP behaviour should be predictable, but on
reflection I now think that we should permit fused multiply-and-add.
This then leads to a further question: should we require floating
point values to be rounded when assigned to a variable? For example,
that would mean that this could produce different results on some
processors:
var f1, f2, f3 float64
...
a := f1 * f2 + f3
or
a := f1 * f2
a += f3
To put all this another way, we have already said that floating point
operations must obey parentheses for associative operators. What we
have so far failed to specify is when and whether rounding must occur.
(Subsequent issues will be whether we should expose IEEE-754 floating
point flags and traps in any predictable way.)
Ian