Pixel Invariance

darkblu said:
although your concern is generally correct, the particular example you've given would always result in "OK" since both '0.1' constants get onto the fpu stack as doubes (the x87 does not have 80-bit interface to the world); now, *if* one of those '0.1' came as a result from a non-spilled (fpu-internal) calculation, where fpu prec had been set to 80bit, then undoubtedly the comparison would fail miserably.

x87 definitely can load/store a 80 bits FP (check Intel's manual for FLD and FSTP instructions). However, my example is not good enough since the compiler may store the pre-computed number (0.1) in 64 bits FP mode. A better example is

Code:
double a = 1.0 / 3.0;
if(a == 1.0 / 3.0) printf("OK"); else printf("not OK");

if the compiler does not precompute 1.0 / 3.0 (most compilers do, however), the result will be "not OK."
 
pcchen said:
darkblu said:
although your concern is generally correct, the particular example you've given would always result in "OK" since both '0.1' constants get onto the fpu stack as doubes (the x87 does not have 80-bit interface to the world); now, *if* one of those '0.1' came as a result from a non-spilled (fpu-internal) calculation, where fpu prec had been set to 80bit, then undoubtedly the comparison would fail miserably.

x87 definitely can load/store a 80 bits FP (check Intel's manual for FLD and FSTP instructions). However, my example is not good enough since the compiler may store the pre-computed number (0.1) in 64 bits FP mode. A better example is

Code:
double a = 1.0 / 3.0;
if(a == 1.0 / 3.0) printf("OK"); else printf("not OK");

if the compiler does not precompute 1.0 / 3.0 (most compilers do, however), the result will be "not OK."

weird. i've always had the impression the 80bits float of the x87 is only an internal format. but you're right - it is loadable/storable. maybe i was left misled because the cc i use most (MSVC) actually does not implement long doubles (at least on the platforms i've worked on) -- those get implicitly mapped to doubles. but even w/o that twitch your original example would invariably yeld "OK", as the default type of non-explicitly-typed floating-point constants is taken to be 'double'. your revised exmaple is correct, of course (given the compiler does not precompute). another way to re-write your original example to illustrate your concern even on platforms w/o higher-than-double precision would've been:

Code:
double a = 0.1;
if (a == 0.1f) printf("OK"); else printf("not OK");

above problematic statement may or may not go unnoticed by the programmer depending on the vocality and conformance of the compiler.
 
There is an argument for saying compilers should not allow equality checks against float except for NaN, infinities, etc... this could be maybe widened to include 'exactly representable quantities' such as 0, 1.0, 2.0 etc.

C sits on the fence. It allows equality checks in if, but disallows float as a source for switch.
 
Dio said:
There is an argument for saying compilers should not allow equality checks against float except for NaN, infinities, etc... this could be maybe widened to include 'exactly representable quantities' such as 0, 1.0, 2.0 etc.

or, alternatively, floating-point constants of base any other than 16 sould be disallowed 8)
 
Dio said:
There is an argument for saying compilers should not allow equality checks against float except for NaN, infinities, etc... this could be maybe widened to include 'exactly representable quantities' such as 0, 1.0, 2.0 etc.

Well, this just makes programmers to find some workaround, such as

Code:
double a = 0.3;
if(b == a) ... // in case where if(b == 0.3) is prohibited...

Decimal FPs don't help a lot since people will want to compare to other fractional numbers such as 1.0 / 3.0.

ISO C99 treats FP better, but it seems other languages do not catch up.
 
In my method that would be disallowed. You'd be allowed to ask 'if (a == 0)' or 'if (a == NAN)' - the latter of which isn't trivial to do right now, of course - but not much else.
 
Dio said:
In my method that would be disallowed. You'd be allowed to ask 'if (a == 0)' or 'if (a == NAN)' - the latter of which isn't trivial to do right now, of course - but not much else.

Are you allowed to ask if (a > b) or if (b > a)?
 
I suggest that's OK for all numbers, because then you're not relying on 'exactly comparing' a quantity which is, almost definitively, inexact.

It probably wouldn't be an error, actually. So to phrase this more accurately: "I would generate a warning if the compiler encounters a test of equality or inequality if one of the numbers being compared isn't known to be precise."

>= would be interesting... I would probably tinker the sense of the limitation and issue a warning if the compare is with a constant known to be imprecise (rather than not known to be precise). Or maybe that would be just annoying and I'd let it go :). Minefield ahead, captain.
 
Dio said:
I suggest that's OK for all numbers, because then you're not relying on 'exactly comparing' a quantity which is, almost definitively, inexact.
But by doing both tests you get an equality which was what you were trying to eliminate :D
 
Dio said:
In my method that would be disallowed. You'd be allowed to ask 'if (a == 0)' or 'if (a == NAN)' - the latter of which isn't trivial to do right now, of course - but not much else.
How about:
Code:
double a,b;
...
if ((*(long long *)&a) == (*(long long *)&b))
{}
:D
 
Simon F said:
Dio said:
I suggest that's OK for all numbers, because then you're not relying on 'exactly comparing' a quantity which is, almost definitively, inexact.
But by doing both tests you get an equality which was what you were trying to eliminate :D
I guessed you were trying to trap me.

Hesitant though I am to introduce a cricket analogy after this weekend, maybe we should just enshrine 'the corridor of uncertainty'.

And OpenGL_guy, get a life :)
 
You mean you don't allow general "if(a == b)" statement?

Even so, a simple workaround is "if(a - b == 0)." On an IEEE 754 compliant implementation they are equivalent.
 
OpenGL guy said:
Code:
double a,b;
...
if ((*(long long *)&a) == (*(long long *)&b))
{}
:D
Won't always work as expected. In particular, the number 0.0 has two representations in IEEE-754 formats: one with the sign bit set (-0.0) and another one with the sign bit cleared (+0.0). They are normally considered equal for FP comparisons even though their bit representations are different. Try something like
Code:
double a,b;
....
long long *P1 = (long long *)&a;
long long *P2 = (long long *)&b;
if(*P1 == *P2 || ((*P1 | *P2) & 0x7FFFFFFFFFFFFFFFLL) == 0LL)
{}
 
Dio said:
Myrmecophagavir said:
akira888 said:
Dio said:
even C-written floating point code has this problem. C does not guarantee order of evaluation for arithmetic operands, so if you write D = a+b+c then you could get either (a+b)+c or a+(b+c).
I always had thought that the ANSI standard at the very least enforced a left to right evaluation order for arithmetic operands. At least what every book (including K+R) has told me. Oh well.
Operators have given associativities, left-to-right or right-to-left. It should be that a+b+c always evaluates to (a+b)+c in C?
I've checked this and you're both right (although I think it's a + (b+c) from my reading of K+R, which like so much else, could be wrong...). I was getting confused about the order of evaluation of operands.
It must be the opposite bracketing from the = operator since that has the opposite associativity to +. For a = b = c; to work it couldn't be the same as (a = b) = c; since = doesn't result in an l-value in C (but I think it can in C++?) So it must equal a = (b = c), and therefore the other thing must be (a + b) + c :)
 
Dio said:
I just want to see a compiler that goes 'Warning x2666: Corridor Of Uncertainty Error'.

It's already annoying to see a lot of warnings just because "float a = 0.3;"-like statements. I really don't want to see another warning message for a "if(a == b)" statement... :)
 
pcchen said:
It's already annoying to see a lot of warnings just because "float a = 0.3;"-like statements. I really don't want to see another warning message for a "if(a == b)" statement... :)
I always explicitly use 0.3f when I am using 32-bit float, so I never see this one :)

And most of my projects have at the top of the main header a bunch of '#pragma warning disable' statements... but then again I do use warning level 4.
 
Dio said:
I always explicitly use 0.3f when I am using 32-bit float, so I never see this one :)

That's actually pretty good, until one day when you translate an array of floats into doubles, and wonders why the precision is so bad... ;)

Perhaps we should have a warning class for floating points only, and the user can decide whether to show these warnings. :)
 
Back
Top