Re: Floating point rounding modes: we should restrict them slightly

2009-09-17 Thread Don

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-16 Thread Rainer Deyke
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 - rain...@eldwood.com


Re: Floating point rounding modes: we should restrict them slightly

2009-09-15 Thread Don

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-15 Thread Don

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-15 Thread Rainer Deyke
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 - rain...@eldwood.com


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Don

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Don

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Rainer Deyke
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 - rain...@eldwood.com


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Walter Bright

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!


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Don

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread bearophile
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


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Don

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Jason House
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.



Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Denis Koroskin
On Mon, 14 Sep 2009 16:44:48 +0400, Jason House  
jason.james.ho...@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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Brad Roberts
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? :)




Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Walter Bright

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.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-14 Thread Rainer Deyke
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 - rain...@eldwood.com


Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread Don

Walter Bright wrote:

Don wrote:

PROPOSAL:
Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it 
must be restored before the function exits. If this rule is violated 
(for example, by the use of inline asm), the rounding mode used for 
subsequent calculations is undefined.


But that doesn't allow for changing the rounding mode at a global level, 
then rerunning one's computation to determine how rounding affects their 
final result.


It doesn't prevent that at all. You just need to change the rounding 
mode before running your computation (at the start of main(), for 
example), and then reset it after performing the computation. What it 
does do is prevent different terms within a single expression from 
interacting which other.


eg
double foo() {
  return x() + y();
}
x() and y() can use whichever rounding modes they like, and if they are 
impure, they can affect one another, but under this proposal, they 
cannot change the meaning of the addition inside foo().


Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread Michel Fortin

On 2009-09-13 06:14:02 -0400, Don nos...@nospam.com said:


double foo() {
   return x() + y();
}
x() and y() can use whichever rounding modes they like, and if they are 
impure, they can affect one another, but under this proposal, they 
cannot change the meaning of the addition inside foo().


Problems still may occur if x and y do memoization however. You call 
x() with one rounding mode, it memoize the results, then call x() with 
another rounding mode and it reuses the previous results while it 
shouldn't.


Basicaly, any memoization of x() should be discarded when you change 
the rounding mode. For instance the compiler should not reuse the value 
of x(), even if x is pure, in the following code:


auto a = x();
setRoundingMode(...);
auto b = x();

Basically, setRoundingMode should act as some sort of barrier for the 
optimizer, but how?


--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread Don

Michel Fortin wrote:

On 2009-09-13 06:14:02 -0400, Don nos...@nospam.com said:


double foo() {
   return x() + y();
}
x() and y() can use whichever rounding modes they like, and if they 
are impure, they can affect one another, but under this proposal, they 
cannot change the meaning of the addition inside foo().


Problems still may occur if x and y do memoization however. 


Yes, but this is an orthogonal issue, which I have discussed previously.

Basicaly, any memoization of x() should be discarded when you change the 
rounding mode.


Basically, setRoundingMode should act as some sort of barrier for the 
optimizer, but how?


It's not a big deal, because rounding mode is changed so rarely, so you 
don't need to exactly catch all the cases where memoisation can safely 
be used; you only need to disallow all of the ones where it is unsafe.


I proposed two options: (1) by analogy to SafeD, allow rounding mode and 
float exception flags to be respected only in specially marked modules 
('module(advancedfloatingpoint)' or similar). Memoisation should be 
disabled in such modules. (As a further optimisation, the compiler can 
re-enable memoisation when such functions are called from 
non-advancedfloatingpoint modules).
(2) provide a runtime call to disable memoisation. You'd be obliged to 
call this every time you changed the rounding mode or exception status 
from the default.


I favour (1) because it provides huge optimisation potential for modules 
with default floating point.


The point of all my proposals on this topic, is that these features 
cause a lot of trouble if they're completely unrestrained in the way 
that C/C++ does it, but the semantics required to completely domesticate 
them are not burdensome, and can be done without loss of useful 
functionality.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread Walter Bright

Walter Bright wrote:

Don wrote:

PROPOSAL:
Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it 
must be restored before the function exits. If this rule is violated 
(for example, by the use of inline asm), the rounding mode used for 
subsequent calculations is undefined.


But that doesn't allow for changing the rounding mode at a global level, 
then rerunning one's computation to determine how rounding affects their 
final result.


Ok, I understand now. This makes sense.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread Walter Bright

Don wrote:

PROPOSAL:
Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it 
must be restored before the function exits. If this rule is violated 
(for example, by the use of inline asm), the rounding mode used for 
subsequent calculations is undefined.



I added it into float.html for D2.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread Stewart Gordon

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


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.  But that said, wrapping every arithmetic operation in a function 
to purify it of dependence on floating point settings wouldn't be ideal.


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.


Stewart.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread bearophile
Walter Bright:

 Don:
  PROPOSAL:
  Change the spec by adding the line to float.html:
  If the floating-point rounding mode is changed within a function, it 
  must be restored before the function exits. If this rule is violated 
  (for example, by the use of inline asm), the rounding mode used for 
  subsequent calculations is undefined.
 
 I added it into float.html for D2.

An important purpose of a not bug-prone language is remove as many undefined 
situations as possible. If you add that to D2 specs, can the compiler catch at 
compile time all cases of violations to that rule?

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?

Bye,
bearophile


Re: Floating point rounding modes: we should restrict them slightly

2009-09-13 Thread Walter Bright

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.




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.



Re: Floating point rounding modes: we should restrict them slightly

2009-09-11 Thread Stewart Gordon

Don wrote:
snip

LISTING ONE:

real x = foo(1) + foo(2) + foo(3);

LISTING TWO:

real x1 = foo(1);
real x2 = foo(2);
real x3 = foo(3);
real x = x1 + x2 + x3;

In C and C++ (and currently in D), they are NOT equivalent!
foo() is allowed to change the floating-point rounding mode, so it could 
change the meaning of '+'.

snip

This is just one aspect of it.  You could also call a pure function, 
change the rounding mode, and then call the pure function again on the 
same arguments.  The value returned would change, thereby violating the 
purity.


There has been some talk about pure functions in relation to locales:

http://d.puremagic.com/issues/show_bug.cgi?id=3057
http://www.digitalmars.com/d/archives/digitalmars/D/std.locale_85081.html

Floating point settings are just another case of the same thing, except 
that currently violations in relation to the former are allowed.


Maybe the right solution is some kind of hidden parameter mechanism

Stewart.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-11 Thread Walter Bright

Don wrote:

PROPOSAL:
Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it 
must be restored before the function exits. If this rule is violated 
(for example, by the use of inline asm), the rounding mode used for 
subsequent calculations is undefined.


But that doesn't allow for changing the rounding mode at a global level, 
then rerunning one's computation to determine how rounding affects their 
final result.


Floating point rounding modes: we should restrict them slightly

2009-09-10 Thread Don

A quiz:
Conside a function
real foo() {}
This is not pure, so that it may side-effects, but even so, are listings 
one and two equivalent?


LISTING ONE:

real x = foo(1) + foo(2) + foo(3);

LISTING TWO:

real x1 = foo(1);
real x2 = foo(2);
real x3 = foo(3);
real x = x1 + x2 + x3;

In C and C++ (and currently in D), they are NOT equivalent!
foo() is allowed to change the floating-point rounding mode, so it could 
change the meaning of '+'.
This is quite ridiculous. This is a 'freedom' that comes with a heavy 
price tag.
Actually doing this would make code nearly impossible to debug, and I 
don't think anyone is stupid enough to actually do this
...but as long as it's theoretically possible, it prevents the compiler 
from doing useful optimisations.
Disallowing this kind of obscure, dangerous nonsense is, I think, part 
of the core mission of D.


PROPOSAL:
Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it 
must be restored before the function exits. If this rule is violated 
(for example, by the use of inline asm), the rounding mode used for 
subsequent calculations is undefined.


This slight tightening of semantics can have a significant benefit for 
all floating-point code.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-10 Thread Don

Rainer Deyke wrote:

Don wrote:

Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it
must be restored before the function exits.


Even if that function is called 'fesetround'?


Obviously not. In fact, I'd hope to even disallow fesetround() since 
it's too easy to abuse, and instead have an RAII struct to restore the 
mode automatically. But that's just syntax sugar.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-10 Thread Don

#ponce wrote:

Why not imposing a rounding mode (ex :  toward minus infinity) ?
And then disallowing to change it in assembly.


You can't impose a rounding mode in a system language: rounding mode is 
a crucial feature in a few rare but very important cases. The trick is 
to allow those cases without polluting everything else. This tiny 
proposal gets rid of most the damage.


However, my previous proposal for fixing the interaction of 'pure' with 
rounding modes and exception handling, would allow the rounding mode to 
be round-to-nearest almost everywhere, and changeable only in impure 
functions inside modules marked module(advancedfloatingpoint). This 
could give performance benefits everywhere outside those modules.




Re: Floating point rounding modes: we should restrict them slightly

2009-09-10 Thread Jimbob

#ponce alil...@gmail.com wrote in message 
news:h8adr2$23p...@digitalmars.com...
 Why not imposing a rounding mode (ex :  toward minus infinity) ?
 And then disallowing to change it in assembly.

 I mean, you can still do :
  round(x) as floor(x + 0.5L)
  ceil(x) as floor(x + 1.0L)

 Iit would cost some precision with large floating-point number, but not 
 much since rounding such large numbers has few meaning.

 It would clear up the rounding-mode mess a bit.

There's more to rounding modes than just converting / rounding to integer. 
Rounding affects all arithmetic operations, and whether an expresion 
evaluates to 0.97999 or .97998 can be important in some cases.








Re: Floating point rounding modes: we should restrict them slightly

2009-09-10 Thread Michel Fortin

On 2009-09-10 04:24:38 -0400, Don nos...@nospam.com said:


PROPOSAL:
Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it 
must be restored before the function exits. If this rule is violated 
(for example, by the use of inline asm), the rounding mode used for 
subsequent calculations is undefined.


This slight tightening of semantics can have a significant benefit for 
all floating-point code.


I perfectly agree. I'm just wondering how to enforce it in the language.

Later in the thread you say:

... have an RAII struct to restore the mode automatically. But that's 
just syntax sugar.


But how do you prevent someone from writing:

auto s = new roundingMode(...);

The only way you can really make sure it's scoped to a specific 
function is to call it from another function:


R performWithRoundingMode(R)(flag roundingMode, lazy R result)
{
flag oldRoundingMode = getRoundingMode();
setRoundingMode(roundingMode);
try
return result;
finally
setRoundingMode(oldRoundingMode);
}

auto i = performWithRoundingMode(TOWARDS_ZERO, 12 * 12);

Here you can't escape the scoping requirements.

--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Re: Floating point rounding modes: we should restrict them slightly

2009-09-10 Thread Don

Michel Fortin wrote:

On 2009-09-10 04:24:38 -0400, Don nos...@nospam.com said:


PROPOSAL:
Change the spec by adding the line to float.html:
If the floating-point rounding mode is changed within a function, it 
must be restored before the function exits. If this rule is violated 
(for example, by the use of inline asm), the rounding mode used for 
subsequent calculations is undefined.


This slight tightening of semantics can have a significant benefit for 
all floating-point code.


I perfectly agree. I'm just wondering how to enforce it in the language.


Yes, it's not so obvious how to enforce it. However, in reality it's a 
rarely-used, system level feature, so relying on convention probably 
isn't too terrible in the short term.




Later in the thread you say:

... have an RAII struct to restore the mode automatically. But that's 
just syntax sugar.


But how do you prevent someone from writing:

auto s = new roundingMode(...);


scope _should_ take care of that. I'm not sure that it does. Still, we 
just need to make it easy to do the right thing, and difficult to do the 
wrong thing.


The only way you can really make sure it's scoped to a specific function 
is to call it from another function:


R performWithRoundingMode(R)(flag roundingMode, lazy R result)
{
flag oldRoundingMode = getRoundingMode();
setRoundingMode(roundingMode);
try
return result;
finally
setRoundingMode(oldRoundingMode);
}

auto i = performWithRoundingMode(TOWARDS_ZERO, 12 * 12);

Here you can't escape the scoping requirements.


Hmmm. Not ideal, but could be worse.
But anyway, the important thing is to codify in the spec that the 
floating point state must not change randomly.
For discussing syntax, I think we really need an interval arithmetic 
module, so that we can ensure it all works well.


Re: Floating point rounding modes: we should restrict them slightly

2009-09-10 Thread Lionello Lunesu
#ponce wrote:
 Why not imposing a rounding mode (ex :  toward minus infinity) ?
 And then disallowing to change it in assembly.
 
 I mean, you can still do :
   round(x) as floor(x + 0.5L)
   ceil(x) as floor(x + 1.0L)
 
 Iit would cost some precision with large floating-point number, but not much 
 since rounding such large numbers has few meaning.
 
 It would clear up the rounding-mode mess a bit.

Shouldn't ceil(1.0) return 1.0, and wouldn't floor(1.0 + 1.0L) return 2.0?

L.