View mode: basic / threaded / horizontal-split · Log in · Help
September 10, 2009
Floating point rounding modes: we should restrict them slightly
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.
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
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.
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
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'?


-- 
Rainer Deyke - rainerd@eldwood.com
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
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.
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
#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.
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
"#ponce" <aliloko@gmail.com> wrote in message 
news:h8adr2$23p3$1@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.
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
On 2009-09-10 04:24:38 -0400, Don <nospam@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.fortin@michelf.com
http://michelf.com/
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
Michel Fortin wrote:
> On 2009-09-10 04:24:38 -0400, Don <nospam@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.
September 10, 2009
Re: Floating point rounding modes: we should restrict them slightly
#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.
September 11, 2009
Re: Floating point rounding modes: we should restrict them slightly
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.
« First   ‹ Prev
1 2 3 4
Top | Discussion index | About this forum | D home