There are numerous reference on the subject (here or here). However I still fails to understand why the following is not considered UB and properly reported by my favorite compiler (insert clang and/or gcc) with a neat warning:
// f1, f2 and epsilon are defined as double
if ( f1 / f2 <= epsilon )
As per C99:TC3, 5.2.4.2.2 §8: we have:
Except for assignment and cast (which remove all extra range and precision), the values of operations with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type. [...]
Using typical compilation f1 / f2
would be read directly from the FPU. I've tried here using gcc -m32
, with gcc 5.2. So f1 / f2
is (over-here) on an 80 bits (just a guess dont have the exact spec here) floating point register. There is not type promotion here (per standard).
I've also tested clang 3.5
, this compiler seems to cast the result of f1 / f2
back to a normal 64 bits floating point representation (this is an implementation defined behavior but for my question I prefer the default gcc behavior).
As per my understanding the comparison will be done in between a type for which we don't know the size (ie. format whose range and precision may be greater
) and epsilon
which size is exactly 64 bits.
What I really find hard to understand is equality comparison with a well known C types (eg. 64bits double
) and something whose range and precision may be greater
. I would have assumed that somewhere in the standard some kind of promotion would be required (eg. standard would mandates that epsilon
would be promoted to a wider floating point type).
So the only legitimate syntaxes should instead be:
if ( (double)(f1 / f2) <= epsilon )
or
double res = f1 / f2;
if ( res <= epsilon )
As a side note, I would have expected the litterature to document only the operator <
, in my case:
if ( f1 / f2 < epsilon )
Since it is always possible to compare floating point with different size using operator <
.
So in which cases the first expression would make sense ? In other word, how could the standard defines some kind of equality operator in between two floating point representation with different size ?
EDIT: The whole confusion here, was that I assumed it was possible to compare two float of different size. Which cannot possibly happen. (thanks @DevSolar!).