View mode: basic / threaded / horizontal-split · Log in · Help
September 14, 2009
Re: Floating point rounding modes: we should restrict them slightly
Brad Roberts wrote:
> Walter Bright wrote:
>> 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? :)

Yes. Memory safety is defined as being free of memory corruption errors. 
Simply reading memory out of bounds does not corrupt memory.

Note that it is ok for a memory safe program to generate a seg fault.

printf() is not memory safe because of the %n format.
September 15, 2009
Re: Floating point rounding modes: we should restrict them slightly
Don wrote:
> Rainer Deyke wrote:
>> 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.

Then I must have misunderstood your proposal.  Either you did a poor job
of explaining it, or I did a poor job of trying to understand it, or
it's not as simple as you make it out to be.

Since I'm not really interested in discussing the details of floating
point rounding modes and memoisation, I'll just leave it at that.

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

It only affects floating point operations.  Other pieces of global state
(e.g. the global locale) affect other operations.  Once you make a
special case for floating point mode, it's easy to argue that the
special case should be extended to other pieces of global data.  A
general solution generally beats special cases.

Or maybe I'm completely overthinking this.

> 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; }

In the presence of structs and class executing arbitrary code in opPlus,
you can't make this pure anyway.  Unless you force opPlus itself to be
pure, which is almost certainly too restrictive for the current
definition of pure.


-- 
Rainer Deyke - rainerd@eldwood.com
September 15, 2009
Re: Floating point rounding modes: we should restrict them slightly
Rainer Deyke wrote:
> Don wrote:
>> Rainer Deyke wrote:
>>> 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.
> 
> Then I must have misunderstood your proposal.  Either you did a poor job
> of explaining it, or I did a poor job of trying to understand it, or
> it's not as simple as you make it out to be.

> Since I'm not really interested in discussing the details of floating
> point rounding modes and memoisation, I'll just leave it at that.

The description I just gave of it was
The thing you missed is that the non-memoisable pure functions can only 
read the global state.

> 
>>> 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.
> 
> It only affects floating point operations.  Other pieces of global state
> (e.g. the global locale) affect other operations. 

But you ALWAYS have a choice about that. You can rewrite functions which 
are independent of locale, or you can pass the locale as a parameter. 
With floating point, you don't have that option.

BTW, global locales suck, big time. The idea that you can specify the 
formatting in the form of a locale is clearly the creation of someone 
who had never worked in an international environment. (And any locale 
which includes 'currency' is clearly the creation of an idiot).

 Once you make a
> special case for floating point mode, it's easy to argue that the
> special case should be extended to other pieces of global data.

No, because this is a hardware special case. All the other cases can be 
dealt with in software.

> Or maybe I'm completely overthinking this.
> 
>> 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; }
> 
> In the presence of structs and class executing arbitrary code in opPlus,
> you can't make this pure anyway.  Unless you force opPlus itself to be
> pure, which is almost certainly too restrictive for the current
> definition of pure.

You're right. Bad example. But seriously, people give sqrt(x) as the 
classic example of a pure function.
September 15, 2009
Re: Floating point rounding modes: we should restrict them slightly
Walter Bright wrote:
> Brad Roberts wrote:
>> Walter Bright wrote:
>>> 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? :)
> 
> Yes. Memory safety is defined as being free of memory corruption errors. 
> Simply reading memory out of bounds does not corrupt memory.

It does result in undefined behaviour, though. I don't see much 
difference. (Corrupting memory is a problem only because you read it 
again afterwards...)

> Note that it is ok for a memory safe program to generate a seg fault.

It'd be OK if it was guaranteed to generate a seg fault. But I don't 
think that's true here.

> 
> printf() is not memory safe because of the %n format.
September 15, 2009
Re: Floating point rounding modes: we should restrict them slightly
Don wrote:
> The thing you missed is that the non-memoisable pure functions can only
> read the global state.

No, I saw that.  But if a (pure) function calls another (pure) function
that depends on global state, then the first (pure) function also
depends on global state.

int global_state;

pure int f() {
 return global_state;
}

pure int g() {
 return f();
}

int h() {
 global_state = 5;
 return g();
}

> But you ALWAYS have a choice about that. You can rewrite functions which
> are independent of locale, or you can pass the locale as a parameter.
> With floating point, you don't have that option.

True.  Unless you add functions/operators that use a fixed rounding mode
to the language.

> BTW, global locales suck, big time. The idea that you can specify the
> formatting in the form of a locale is clearly the creation of someone
> who had never worked in an international environment. (And any locale
> which includes 'currency' is clearly the creation of an idiot).

No argument there.


-- 
Rainer Deyke - rainerd@eldwood.com
September 16, 2009
Re: Floating point rounding modes: we should restrict them slightly
Rainer Deyke wrote:
> Don wrote:
>> The thing you missed is that the non-memoisable pure functions can only
>> read the global state.
> 
> No, I saw that.  But if a (pure) function calls another (pure) function
> that depends on global state, then the first (pure) function also
> depends on global state.
> 
> int global_state;
> 
> pure int f() {
>   return global_state;
> }
> 
> pure int g() {
>   return f();
> }
> 
> int h() {
>   global_state = 5;
>   return g();
> }

Ah. The important thing that makes this work is that the global FP state 
has a clearly defined default. (round-to-nearest, full precision, no 
floating point exceptions enabled). Part of the implicit contract of 
calling a 'memoisable pure' function is that the global FP state is in 
the default state.
No pure function can change the state. So once you're in a memoisable 
pure function, you can safely call any non-memoisable pure function, in 
the knowledge that the default mode is in effect.

> 
>> But you ALWAYS have a choice about that. You can rewrite functions which
>> are independent of locale, or you can pass the locale as a parameter.
>> With floating point, you don't have that option.
> 
> True.  Unless you add functions/operators that use a fixed rounding mode
> to the language.

Yes, there's a few impractical ways it could be made to work (passing 
the rounding mode as an explicit parameter to every function is another 
option).

Actually there's a related issue which I haven't mentioned: the floating 
point exception sticky flags are effectively a global variable, written 
to by every floating point operation which you perform. It can be 
covered in the same way: there's no guarantee that the flags will be 
correct in the presence of memoisation, so you need to be able to 
indicate to the compiler or runtime that the flags returned from this 
function call are important to you.
September 16, 2009
Re: Floating point rounding modes: we should restrict them slightly
Don wrote:
> Ah. The important thing that makes this work is that the global FP state
> has a clearly defined default. (round-to-nearest, full precision, no
> floating point exceptions enabled). Part of the implicit contract of
> calling a 'memoisable pure' function is that the global FP state is in
> the default state.

Then I'm not sure it makes to treat "memoisable" as a property of a
(pure) function.  It seems more like a property of the context from
which the function is called.  *All* pure function are memoisable if you
always call them with the floating point rounding mode set to the
default.  Conversely, all pure functions can be called with an arbitrary
rounding mode if you treat them an unmemoisable.

Some function - those that don't perform any floating point calculation,
directly or indirectly - are independent from floating point state, and
could even memoised even when called with an arbitrary floating point
state.  But there is no good way to automatically detect these functions.


-- 
Rainer Deyke - rainerd@eldwood.com
September 17, 2009
Re: Floating point rounding modes: we should restrict them slightly
Rainer Deyke wrote:
> Don wrote:
>> Ah. The important thing that makes this work is that the global FP state
>> has a clearly defined default. (round-to-nearest, full precision, no
>> floating point exceptions enabled). Part of the implicit contract of
>> calling a 'memoisable pure' function is that the global FP state is in
>> the default state.
> 
> Then I'm not sure it makes to treat "memoisable" as a property of a
> (pure) function.  It seems more like a property of the context from
> which the function is called.  *All* pure function are memoisable if you
> always call them with the floating point rounding mode set to the
> default.  Conversely, all pure functions can be called with an arbitrary
> rounding mode if you treat them an unmemoisable.

That is correct.

> Some function - those that don't perform any floating point calculation,
> directly or indirectly - are independent from floating point state, and
> could even memoised even when called with an arbitrary floating point
> state.  But there is no good way to automatically detect these functions.

It sounds as though you never saw my proposal. My proposal was that, by 
analogy to module(system), specific modules should be marked, for example:
module (advancedfloatingpoint, system) std.math;
or:
module (nondefaultfloat, system) std.math;

All pure functions are memoisable except for pure advancedfloatingpoint 
functions when called from a function (pure or not) which is also in an 
advancedfloatingpoint module.

This is a very tiny hole in the 'purity' rules, and is a tiny addition 
to the language, but it's enough to cover  the practical uses of 
floating-point rounding and exception flags.
Next ›   Last »
1 2 3 4
Top | Discussion index | About this forum | D home