September 14, 2009
Stewart Gordon wrote:
> Don wrote:
> <snip>
>>> Floating point settings are just another case of the same thing, except that currently violations in relation to the former are allowed.
>>
>> There's a fundamental difference between them: the floating point settings are a hardware feature and it is IMPOSSIBLE to avoid them.
> 
> Actually, you _can_ avoid changing the floating point settings in the course of an average program.  But still....

The hardware dependency is still there, in every function which uses floating point. And the compiler must assume that dependency.

> 
>> You can choose not to use locale settings. Or, you can pass them as a parameter, which doesn't work for floating point settings.
> 
> As long as it's the built-in arithmetic operators you're concerned about.  

Of course. There's nothing else to floating point, other than the built-in operators. And this is the problem with unconstrained rounding modes: they influence EVERYTHING.

>But that said, wrapping every arithmetic operation in a function 
> to purify it of dependence on floating point settings wouldn't be ideal.

It's worse than that. Every function which might call a function which might use floating point would have to pass the parameter. It doesn't work.

>> Please do not get sidetracked on pure functions, it is orthogonal to this issue.
> 
> I'm not sure about this.  ISTM arithmetic operators are essentially pure functions, and so the compiler may treat them as such.

No, they always depend on the FP settings, and assuming they are pure functions is not permitted in C, C++, or D. C allows the rounding mode to change at any time.

This proposal:
Rounding mode changes must only affect callees, not callers.

The pure function memoisation issue:
Certain functions may be marked as 'pure', even though they use floating point (and are therefore dependent on the FP state). The compiler must be able to prevent memoisation of those functions in cases where the rounding mode may have changed. (Or, equivalently, the memoisation must include the FP state).

I've provided very simple solutions for both of these. I'm getting pretty irritated that people are acting as though these are difficult problems and trying to come up with convoluted solutions. Impose minimal semantics and it becomes trivial.
September 14, 2009
Walter Bright wrote:
> bearophile wrote:
>> An important purpose of a not bug-prone language is remove as many
>> undefined situations as possible.
> 
> That's right.
> 
>> If you add that to D2 specs, can
>> the compiler catch at compile time all cases of violations to that
>> rule?
> 
> Unlikely. But that has to be weighed against the former behavior being defined in a useless way.

We could get close, I think. We could catch all violations in SafeD. Disallow calling core.stdc.fenv functions from inside SafeD modules, and provide an RAII object in std.math for changing the rounding mode.

Actually there's probably a few other C functions we want to prohibit in SafeD -- the infamous string functions, for example.

I think the goal should be try to remove undefined behaviour from SafeD.
Long term goal: "If a program uses no system modules other than those provided in the standard library, it should not be exposed to undefined behaviour." ?

>> D has something for the actions that must be done before the function
>> exits, the scope(exit). Can something like that be used to
>> automatically avoid undefined rounding situations?
> 
> Using an RAII object to do it might be better.

I agree. I'd like to do something similar with the floating point exception state, too. Haven't worked out the details yet.
September 14, 2009
Don wrote:
> The pure function memoisation issue:
> Certain functions may be marked as 'pure', even though they use floating
> point (and are therefore dependent on the FP state). The compiler must
> be able to prevent memoisation of those functions in cases where the
> rounding mode may have changed. (Or, equivalently, the memoisation must
> include the FP state).

Don't forget that "uses floating point" is a transitive property.  Any pure function that calls a pure-but-unmemoisable function is itself pure-but-unmemoisable.  The "pure" annotation is now used for two related but different categories of functions with different properties, and the compiler needs some way to keep track of which is which across module boundaries.  If the compiler can do that, then it can use the same mechanism to differentiate between pure and non-pure functions, and the "pure" annotation becomes redundant.

Is there any real need to treat floating point state differently from other global state in regard to "pure"?


-- 
Rainer Deyke - rainerd@eldwood.com
September 14, 2009
Don wrote:
> Walter Bright wrote:
>> bearophile wrote:
>>> An important purpose of a not bug-prone language is remove as many
>>> undefined situations as possible.
>>
>> That's right.
>>
>>> If you add that to D2 specs, can
>>> the compiler catch at compile time all cases of violations to that
>>> rule?
>>
>> Unlikely. But that has to be weighed against the former behavior being defined in a useless way.
> 
> We could get close, I think. We could catch all violations in SafeD. Disallow calling core.stdc.fenv functions from inside SafeD modules, and provide an RAII object in std.math for changing the rounding mode.
> 
> Actually there's probably a few other C functions we want to prohibit in SafeD -- the infamous string functions, for example.

Yes, all the C functions will have to be gone through and separated. strlen() is safe, while strcpy() and printf() are not.


> I think the goal should be try to remove undefined behaviour from SafeD.
> Long term goal: "If a program uses no system modules other than those provided in the standard library, it should not be exposed to undefined behaviour." ?

Right!
September 14, 2009
Rainer Deyke wrote:
> Don wrote:
>> The pure function memoisation issue:
>> Certain functions may be marked as 'pure', even though they use floating
>> point (and are therefore dependent on the FP state). The compiler must
>> be able to prevent memoisation of those functions in cases where the
>> rounding mode may have changed. (Or, equivalently, the memoisation must
>> include the FP state).
> 
> Don't forget that "uses floating point" is a transitive property.  Any
> pure function that calls a pure-but-unmemoisable function is itself
> pure-but-unmemoisable.

This is incorrect. You've got it backwards. It's not "uses floating point" that's the issue, it's "may use non-default floating point". A memoisable floating point function can only use default floating point. So, if it calls a non-memoisable pure function, it'll be using it in the default state (even though that function can accept non-default state).

The transitivity propagates in the reverse direction: memoisability is transitive, non-memoisability is not. Non-memoisable functions cannot call memoisable ones without first ensuring that everything is back into the default state.

  The "pure" annotation is now used for two
> related but different categories of functions with different properties,
> and the compiler needs some way to keep track of which is which across
> module boundaries.  If the compiler can do that, then it can use the
> same mechanism to differentiate between pure and non-pure functions, and
> the "pure" annotation becomes redundant.

It's true that you could provide a similar loophole for any specific global variable. But you'd need a *very* good reason.

> Is there any real need to treat floating point state differently from
> other global state in regard to "pure"?

Yes. Because it's all-pervasive. Unless you treat it specially, you cannot use floating point in any pure function. That creates a restriction which is so severe that 'pure' becomes useless. Something like the following template function could not be pure:

T add(T a, T b) { return a + b; }

I do not believe that any other global state has an influence which is in the same league.
September 14, 2009
Walter Bright:
> Yes, all the C functions will have to be gone through and separated. strlen() is safe, while strcpy() and printf() are not.

For some of the removed functions better C-like ones can be provided: http://www.ddj.com/cpp/214502214

Bye,
bearophile
September 14, 2009
bearophile wrote:
> Walter Bright:
>> Yes, all the C functions will have to be gone through and separated. strlen() is safe, while strcpy() and printf() are not.
> 
> For some of the removed functions better C-like ones can be provided:
> http://www.ddj.com/cpp/214502214
> 
> Bye,
> bearophile

Just use D instead.
September 14, 2009
Don Wrote:
> 
> I've provided very simple solutions for both of these. I'm getting pretty irritated that people are acting as though these are difficult problems and trying to come up with convoluted solutions. Impose minimal semantics and it becomes trivial.

FWIW, I've liked your proposals, but I don't feel qualified to comment. I never adjust rounding modes. I do like how I can be ignorant and get code that is better optimized. You've shown deep knowledge of floating point operation in the past, and I'm inclined to accept reasonable-sounding proposals from those that know way more than me.

September 14, 2009
On Mon, 14 Sep 2009 16:44:48 +0400, Jason House <jason.james.house@gmail.com> wrote:

> Don Wrote:
>>
>> I've provided very simple solutions for both of these. I'm getting
>> pretty irritated that people are acting as though these are difficult
>> problems and trying to come up with convoluted solutions. Impose minimal
>> semantics and it becomes trivial.
>
> FWIW, I've liked your proposals, but I don't feel qualified to comment. I never adjust rounding modes. I do like how I can be ignorant and get code that is better optimized. You've shown deep knowledge of floating point operation in the past, and I'm inclined to accept reasonable-sounding proposals from those that know way more than me.
>

I second that. Nothing to add.
September 14, 2009
Walter Bright wrote:
> Don wrote:
>> We could get close, I think. We could catch all violations in SafeD. Disallow calling core.stdc.fenv functions from inside SafeD modules, and provide an RAII object in std.math for changing the rounding mode.
>>
>> Actually there's probably a few other C functions we want to prohibit in SafeD -- the infamous string functions, for example.
> 
> Yes, all the C functions will have to be gone through and separated.
> strlen() is safe, while strcpy() and printf() are not.

You sure?  Does running beyond the bounds of the array if there's no null termination count as safe some how? :)