Proposal: fixing the 'pure' floating point problem.

Walter Bright newshound1 at digitalmars.com
Tue Mar 17 03:38:23 PDT 2009


Don wrote:
> 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.

If std.math was floatingpoint, then its functions could not be pure.

> 
>>
>>> 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.

I agree that's a problem.


> (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.

I don't see how your proposal fixes this problem.

> (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.

Maybe a solution is to just have a global compiler flag that says "don't 
cache pure functions." Because this problem applies to every pure 
function, because pure functions can call other pure functions which 
call floating point pure functions.



More information about the Digitalmars-d mailing list