Proposal: fixing the 'pure' floating point problem.
Denis Koroskin
2korden at gmail.com
Fri Mar 13 04:57:15 PDT 2009
On Fri, 13 Mar 2009 13:52:08 +0300, Don <nospam at nospam.com> wrote:
> 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.
Does it mean that *any* pure function that has floating-point arithmentic involved will have to carry an additional status parameter? If so, why make it explicit?
I've been programming in C++ for years now and have never ever used floating point exception or customized rounding modes. It may be useful in some cases, but I believe it is not a feature of frequent use.
That's why I believe the following would be suitable for most programmers:
- whenever you enter a pure function, all floating point settings get saved to stack and reset to defaults (rounding to nearest, no exceptions etc).
- floating point settings get restored upon leaving the pure function (normally or via exception)
- user may change rounding modes explicitly inside a pure function, but changes won't be visible to outer code (see previous point)
Comments?
More information about the Digitalmars-d
mailing list