Proposal: fixing the 'pure' floating point problem.

Don nospam at nospam.com
Mon Mar 16 03:46:34 PDT 2009


Walter Bright wrote:
> Don wrote:
>> A has called a function in B. B is not a floatingpoint module, so b() 
>> can only be called when the mode is set back to the default. a() 
>> violates this contract, so a() is incorrect. There's nothing wrong 
>> with b() or c(). If a() wants to call b(), it needs to restore the 
>> mode first; or else change b() into another floatingpoint module.
> 
> Ok, this was the missing piece in my understanding of the proposal.
> 
> But this requires that std.math either be floatingpoint, or two versions 
> of it must exist if you want to do change the rounding modes on it.

I'm proposing that std.math would be floatingpoint. The docs contain 
references to the sticky flags; I just went to a lot of trouble to make 
sure that exp() sets the sticky flags correctly.

> 
>> Something interesting about my proposal is that although it is 
>> motivated by the purity problem, that's simply a rule for the compiler 
>> -- the rules for programmers do not involve purity at all.(See my 
>> other post). Do not call _any_ functions in non-floatingpoint modules 
>> (pure or not) without restoring the rounding modes back to the default.
> 
> They could be done in terms of pure - if you call any pure function, the 
> modes must be set to the default.

(1) If it's totally forbidden to call a pure function with non-default 
rounding modes, you need a separate non-pure function for the 
non-default case. And unfortunately, it's viral -- you'd need 
non-default rounding mode functions for every function. Even though 
these functions are the same for pure and non-pure.

(2) You could do it as, 'pure' is cacheable only if the control mode is 
set to default, otherwise it's not allowed to be cached. That would 
require the complier to check the control mode all the time if it's 
implementing caching. And it has to check it on EVERY function, it can't 
rely on the signature. Something like:

pure int foo(int x)
{
    return (x*0.5 > 6.0)? 1 : 2;
}

depends on the rounding mode! Consider that this might be in a library 
-- I just don't think it's viable.

Additionally, in both cases, you either lose access to the sticky flags, 
or else have to deal with them explicitly.

(3) There is another option which would actually work. That is to 
introduce a secret threadlocal 'must_not_cache_pure_functions' bool 
variable.

At any point where the mode is about to change, 
must_not_cache_pure_functions must be set to true, and set to false when 
the mode is restored.
Likewise, that variable should be set to true whenever you're beginning 
a scope where you care about the sticky flags.

_Every_ attempt to use the cached result of a pure function would have 
to check that bool before doing anything else.



More information about the Digitalmars-d mailing list