Proposal: fixing the 'pure' floating point problem.
Don
nospam at nospam.com
Fri Mar 13 03:52:08 PDT 2009
Consider this code:
double add(double x, double y) {
return x + y;
}
Is this code pure? Is it nothrow?
Technically, it isn't. If you change the floating-point rounding mode on
the processor, you get a different result for exactly the same inputs.
If you change the floating-point traps, it could throw a floating-point
overflow exception.
One Draconian solution would be to say that this code is NOT pure. This
would mean that floating-point could not be used _at all_ in pure code.
Therefore, a template function like this could probably not be pure:
T add(T)(T x, T y) { return x + y; }
And everything unravels from there.
Another solution would be to simply ignore the floating point flags, and
mark the relevant functions as pure anyway. That would be a shame --
DMD goes to a lot of trouble to ensure that they remain valid (which is
one of the reasons why DMD's floating point code is so slow). We'd be
well behind C99 and C++ in support for IEEE floating-point. I don't like
that much.
--- A solution ---
Extend the parametrized module declaration to include something like
module(system, floatingpoint)
as well as
module(system).
This would indicate that the module is floating-point aware. Every
function in that module has two implicit inout parameters: the floating
point status and control registers. This matters ONLY if the compiler
chooses to cache the result of any function in that module which is
marked as 'pure', it must also check the floating-point status and
control, if the function is called from inside any floatingpoint module.
(Most likely, the compiler would simply not bother caching purity of
floating-point modules). This ensures purity is preserved, _and_ the
advanced floating point features remain available.
Functions inside a floating-point aware module would behave exactly as
they do in normal D.
And now comes the big win. The compiler knows that if a module is not
"floatingpoint", the status flags and rounding DO NOT MATTER. It can
assume the floating-point default situation (round-to-nearest, no
floating point exceptions activated). This allows the compiler to
optimize more aggressively. Of course, it is not required to do so.
Note: The compiler can actually cache calls to pure functions defined in
"floatingpoint" modules in the normal way, since even though the
functions care about advanced features, the code calling those functions
isn't interested. But I doubt the compiler would bother.
This proposal is a little similar to the "Borneo" programming language
proposal for Java,
http://sonic.net/~jddarcy/Borneo/
which was made by one of William Kahan's students. He proposed
annotating every function, specifying which floating point exceptions it
may read or write. In my opinion, that's massive overkill -- it's only
in a few situations that anyone cares about this stuff, most of the
time, you don't. And even when you do care about it, it will only be in
small number of modules.
Since DMD doesn't cache pure functions, it doesn't require any changes
to support this (other than the module statement).
BTW, module(floatingpoint) is just a suggestion. I'm sure someone could
come up with a better term. It could even be really verbose, it's hardly
ever going to be used.
Don.
More information about the Digitalmars-d
mailing list