Walter Bright wrote:
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.

It can certainly be floatingpoint. That's the whole point of the proposal! Fundamental to the proposal is to relax the definition of pure from, "the result depends only on the input parameters, and has no side-effects" to (in x86 terminology) "the result depends only on the inputs _and on the floating-point control register_, and has no side-effects _other than on the floating-point status register_".

Because without this relaxed definition, either
(1) any function with any floating-point operation cannot be pure; or
(2) access to the control and status registers is forbidden (the Java solution).

With this changed definition of pure, pure is not the same as "trivially cacheable". I think this is the key point which you haven't understood.

Every function in std.math fulfills the relaxed requirement for purity, though they are not "trivially cacheable", and don't satisfy the rigid purity rule.

Relaxed purity isn't much use for the caching optimization (though it helps for the other benefits of 'pure'). So, I then introduce module(floatingpoint) as a trick to make almost all pure functions "trivially cacheable".

All pure functions are trivially cacheable, unless they are defined in a floatingpoint module, AND are called from another floatingpoint module.

That tiny relaxation of the purity rules is enough to allow things like interval arithmetic to be implemented. In every other circumstance, the rigid purity rule can be applied.

So we get three desired outcomes:
(1) floating point can be used in pure functions;
(2) we have access to the control and status registers;
  2a. (but only in very limited circumstances);
(3) pure functions can be trivially cached;
  3a. (except in very limited circumstances).

Reply via email to