C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Compiler allowed to do this?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
David W
Guest





PostPosted: Thu Sep 21, 2006 9:10 am    Post subject: Compiler allowed to do this? Reply with quote



float nanometers(long pm)
{
return pm / 1000.0f;
}
void f()
{
if(nanometers(309311L) == nanometers(309311L))
{
// do something
}
}

The 'if' expression resolves to false, probably because one float value is stored and reloaded but
the other remains in the FPU in extended precision (I examined the assembler). I know you have to be
careful when comparing floats, but I'd expect the same values undergoing the same operations to end
up the _same_, and I'd like to know if the compiler is conforming to the standard.

The compiler is VS .NET 2003 in debug mode (no optimization) and with the /Op switch turned on
(improve float consistency).

DW
Back to top
Kai-Uwe Bux
Guest





PostPosted: Thu Sep 21, 2006 9:10 am    Post subject: Re: Compiler allowed to do this? Reply with quote



David W wrote:

Quote:
float nanometers(long pm)
{
return pm / 1000.0f;
}
void f()
{
if(nanometers(309311L) == nanometers(309311L))
{
// do something
}
}

The 'if' expression resolves to false, probably because one float value is
stored and reloaded but the other remains in the FPU in extended precision
(I examined the assembler). I know you have to be careful when comparing
floats, but I'd expect the same values undergoing the same operations to
end up the _same_, and I'd like to know if the compiler is conforming to
the standard.
[snip]


I think the compiler is within its rights. At least that is how I would
interpret the intention of [5/10]:

The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than that
required by the type; the types are not changed thereby


Best

Kai-Uwe Bux
Back to top
David W
Guest





PostPosted: Fri Sep 22, 2006 8:48 am    Post subject: Re: [OT] Compiler allowed to do this? Reply with quote



"red floyd" <no.spam (AT) here (DOT) dude> wrote in message
news:VsHQg.7098$Ij.4199 (AT) newssvr14 (DOT) news.prodigy.com...
Quote:
David W wrote:

Yes, the compiler should certainly offer this, but I suspect that it
doesn't. It seems wrong to me that I'm not getting what I asked for. The
function return type is specified is float, not double, but I'm getting a
float for one call and a double for the other. If the compiler did what I
asked and produced a float in both cases, at least when an equality is used,
there wouldn't be a problem. This is the worst kind of inconsistency and is
taking the latitude the standard allows too far.


OT, since it's compiler specific, but look at the /fp option.

Thanks, but there isn't a /fp option with VS .NET 2003 (i.e., MS C++ ver. 13). There's a /Fp, but
that's to do with pre-compiled headers.

DW
Back to top
Old Wolf
Guest





PostPosted: Fri Sep 22, 2006 9:00 am    Post subject: Re: Compiler allowed to do this? Reply with quote

David W wrote:
Quote:
"Howard" <alicebt (AT) hotmail (DOT) com> wrote:

How about just assigning the results to variables, and later comparing
those variables? Then the values should be equal. (Right?)

Right, but that doesn't solve my problem of how to determine where else this
bug is occurring in a large project that used to not have it.

Grep for "=="
Back to top
David W
Guest





PostPosted: Fri Sep 22, 2006 9:10 am    Post subject: Re: Compiler allowed to do this? Reply with quote

"Old Wolf" <oldwolf (AT) inspire (DOT) net.nz> wrote in message
news:1158897643.112678.190080 (AT) i3g2000cwc (DOT) googlegroups.com...
Quote:
David W wrote:
Right, but that doesn't solve my problem of how to determine where else this
bug is occurring in a large project that used to not have it.

Grep for "=="

I did. There are 2,568 of them in 344 files.

DW
Back to top
Greg
Guest





PostPosted: Fri Sep 22, 2006 9:10 am    Post subject: Re: Compiler allowed to do this? Reply with quote

David W wrote:
Quote:
"Kai-Uwe Bux" <jkherciueh (AT) gmx (DOT) net> wrote in message
news:eetb8v$470$1 (AT) murdoch (DOT) acc.Virginia.EDU...
David W wrote:

float nanometers(long pm)
{
return pm / 1000.0f;
}
void f()
{
if(nanometers(309311L) == nanometers(309311L))
{
// do something
}
}

The 'if' expression resolves to false, probably because one float value
is
stored and reloaded but the other remains in the FPU in extended
precision
(I examined the assembler). I know you have to be careful when comparing
floats, but I'd expect the same values undergoing the same operations to
end up the _same_, and I'd like to know if the compiler is conforming to
the standard.
[snip]

I think the compiler is within its rights. At least that is how I would
interpret the intention of [5/10]:

The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than that
required by the type; the types are not changed thereby

Well, that's just asking for bugs, IMO. Intuitively, most programmers would
expect the 'if' expression to be true, even those who are aware of round-off
issues with floats. The original code from which I created the example
worked on an earlier compiler, but now it doesn't and I can't even force the
compiler to make it work.

What abourt VC's /Op switch to "improve float consistency"? The
description begins:

"This option improves the consistency of floating-point tests for
equality and inequality by disabling optimizations that could change
the precision of floating-point calculations."

In general, about the only benefit of using a float over a double is to
save a few bytes - possibly. But otherwise, most FPUs perform all
calculations with doubles anyway, making a double at least as fast (or
faster) than a float, and much more precise as well.

Greg
Back to top
David W
Guest





PostPosted: Fri Sep 22, 2006 9:10 am    Post subject: Re: Compiler allowed to do this? Reply with quote

"Stephan Kuhagen" <nospam (AT) domain (DOT) tld> wrote in message
news:eevsi7$l3b$1 (AT) kohl (DOT) informatik.uni-bremen.de...
Quote:
David W wrote:

"Howard" <alicebt (AT) hotmail (DOT) com> wrote in message
news:i2CQg.85790$QM6.53529@bgtnsc05-news.ops.worldnet.att.net...

"David W" <no (AT) email (DOT) provided> wrote in message
news:4512dbba (AT) news (DOT) eftel.com...
"Howard" <alicebt (AT) hotmail (DOT) com> wrote in message
news:0cyQg.84450$QM6.79042@bgtnsc05-news.ops.worldnet.att.net...

How about just assigning the results to variables, and later comparing
those
variables? Then the values should be equal. (Right?)

No, sorry. Just a little while ago I had to solve a colleague's problem with
that, who didn't know about the "volatile-trick". He assigned the values to
two variables and then compared them, but although they had the same value,
the comparison failed. The only way he found to solve it, was to put a
printf between the assignments and the comparison... ouch. And he is _not_
a newbie! It seems, that printf kills all your register contents on that
specific compiler, so the comparison worked...

Yes, the compiler probably just optimizes out the store/load. I think /Op in my compiler is the
printf-eliminating switch for this problem Smile (i.e., store/load of floats really means that).

Quote:
Yes, but it's an understandable problem. I don't imagine there are many
programmers who would instinctively think it's a risky thing to do. In how
many programming languages would this not work?

It is understandable, see above anecdote. I think, many compiler languages
close to hardware would not work in the expected way. But this is how
languages close hardware and complex often work: unexpected to the
programmer who did not know the pitfalls.

The problem are not the languages, I think, but the miserable design of IEEE
floating point numbers and FPUs working with them. For example Intel FPUs
internally work with a larger resolution as when storing the numbers back
into memory (which is the reason, why the comparison fails). The problem
is, that comparing IEEE FPN is not save (there are papers about that...). C
and C++ deal with real IEEE number, so they have the same problem. Other
"higher level" languages do not use them, only in their own (mostly) C
code, but not at the level, where the programmer deals with number. For
example Python or Tcl are written in C themselves so the problem exists on
the C-level. But when the programmer uses numbers in Python, he does not
deal with IEEE FPN, but instead with the higher level abstraction of those
in Python. The benefit is that he has no such annoying problems, but the
drawback is the loss in performance. You would not write a number crunching
program in Tcl, would you...?

I guess not.

Quote:
you. You'll just have to look at your own code, large or not. I don't
know of any way around it, sorry.

I wasn't asking for help on that. I was only pointing out the trouble that
this unreasonable compiler behaviour has caused.

Well, but it _is_ reasonable,

I don't agree. I specifically asked for a comparison of two floats and it gave me a comparison of a
float and a double, and what's worse is that two calls of the same function produced that
inconsistency.

Quote:
because the program uses IEEE FPN. If it uses
a math library like gmp, you have an implementation of FPN which is
designed for speed AND safety. It's not the language or the compiler which
is bad (I never thought, I would say this about a MS Compiler... Wink, the
things, the program uses are.

But it seems odd to me that you're comparing the results of two identical
function calls in the first place. I'm guessing this was just a made-up
test to try to replicate a real-life situation you have?

Of course.

And a good one. A programmer who doesn't know the trick, must think this was
a joke ;-)

If you got those values from the exact same code (as in your example),
then you already know they're equal, and shouldn't need to compare.

I don't know they are equal in the real program, where the longs are
variables, not compile-time constants.

On gcc there is this option:

`-ffloat-store'
Do not store floating point variables in registers, and inhibit
other options that might change whether a floating point value is
taken from a register or memory.

This option prevents undesirable excess precision on machines such
as the 68000 where the floating registers (of the 68881) keep more
precision than a `double' is supposed to have. Similarly for the
x86 architecture. For most programs, the excess precision does
only good, but a few programs rely on the precise definition of
IEEE floating point. Use `-ffloat-store' for such programs, after
modifying them to store all pertinent intermediate computations
into variables.

I'm sure, your compiler has a similar option, which solves the problem
globally, so you do not need to find all places, where the problem might
occur. But it makes the executable a little bit slower...

Well, I haven't found it. If it had one I'd retract all my complaints.

DW
Back to top
Stephan Kuhagen
Guest





PostPosted: Fri Sep 22, 2006 9:10 am    Post subject: Re: Compiler allowed to do this? Reply with quote

David W wrote:

Quote:
"Old Wolf" <oldwolf (AT) inspire (DOT) net.nz> wrote in message
news:1158897643.112678.190080 (AT) i3g2000cwc (DOT) googlegroups.com...
David W wrote:
Right, but that doesn't solve my problem of how to determine where else
this bug is occurring in a large project that used to not have it.

Grep for "=="

I did. There are 2,568 of them in 344 files.

Peanuts... a good sed replace expression should do the work... ;-)

Regards
Stephan
Back to top
Stephan Kuhagen
Guest





PostPosted: Fri Sep 22, 2006 9:10 am    Post subject: Re: Compiler allowed to do this? Reply with quote

David W wrote:

Quote:
"Howard" <alicebt (AT) hotmail (DOT) com> wrote in message
news:i2CQg.85790$QM6.53529@bgtnsc05-news.ops.worldnet.att.net...

"David W" <no (AT) email (DOT) provided> wrote in message
news:4512dbba (AT) news (DOT) eftel.com...
"Howard" <alicebt (AT) hotmail (DOT) com> wrote in message
news:0cyQg.84450$QM6.79042@bgtnsc05-news.ops.worldnet.att.net...

How about just assigning the results to variables, and later comparing
those
variables? Then the values should be equal. (Right?)

No, sorry. Just a little while ago I had to solve a colleague's problem with
that, who didn't know about the "volatile-trick". He assigned the values to
two variables and then compared them, but although they had the same value,
the comparison failed. The only way he found to solve it, was to put a
printf between the assignments and the comparison... ouch. And he is _not_
a newbie! It seems, that printf kills all your register contents on that
specific compiler, so the comparison worked...

Quote:
Yes, but it's an understandable problem. I don't imagine there are many
programmers who would instinctively think it's a risky thing to do. In how
many programming languages would this not work?

It is understandable, see above anecdote. I think, many compiler languages
close to hardware would not work in the expected way. But this is how
languages close hardware and complex often work: unexpected to the
programmer who did not know the pitfalls.

The problem are not the languages, I think, but the miserable design of IEEE
floating point numbers and FPUs working with them. For example Intel FPUs
internally work with a larger resolution as when storing the numbers back
into memory (which is the reason, why the comparison fails). The problem
is, that comparing IEEE FPN is not save (there are papers about that...). C
and C++ deal with real IEEE number, so they have the same problem. Other
"higher level" languages do not use them, only in their own (mostly) C
code, but not at the level, where the programmer deals with number. For
example Python or Tcl are written in C themselves so the problem exists on
the C-level. But when the programmer uses numbers in Python, he does not
deal with IEEE FPN, but instead with the higher level abstraction of those
in Python. The benefit is that he has no such annoying problems, but the
drawback is the loss in performance. You would not write a number crunching
program in Tcl, would you...?

Quote:
you. You'll just have to look at your own code, large or not. I don't
know of any way around it, sorry.

I wasn't asking for help on that. I was only pointing out the trouble that
this unreasonable compiler behaviour has caused.

Well, but it _is_ reasonable, because the program uses IEEE FPN. If it uses
a math library like gmp, you have an implementation of FPN which is
designed for speed AND safety. It's not the language or the compiler which
is bad (I never thought, I would say this about a MS Compiler... Wink, the
things, the program uses are.

Quote:
But it seems odd to me that you're comparing the results of two identical
function calls in the first place. I'm guessing this was just a made-up
test to try to replicate a real-life situation you have?

Of course.

And a good one. A programmer who doesn't know the trick, must think this was
a joke ;-)

Quote:
If you got those values from the exact same code (as in your example),
then you already know they're equal, and shouldn't need to compare.

I don't know they are equal in the real program, where the longs are
variables, not compile-time constants.

On gcc there is this option:

`-ffloat-store'
Do not store floating point variables in registers, and inhibit
other options that might change whether a floating point value is
taken from a register or memory.

This option prevents undesirable excess precision on machines such
as the 68000 where the floating registers (of the 68881) keep more
precision than a `double' is supposed to have. Similarly for the
x86 architecture. For most programs, the excess precision does
only good, but a few programs rely on the precise definition of
IEEE floating point. Use `-ffloat-store' for such programs, after
modifying them to store all pertinent intermediate computations
into variables.

I'm sure, your compiler has a similar option, which solves the problem
globally, so you do not need to find all places, where the problem might
occur. But it makes the executable a little bit slower...

Regards
Stephan
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.