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