I am working on a platform that has terrible stalls when comparing floats to zero. As an optimization I have seen the following code used:
inline bool GreaterThanZero( float value )
{
const int value_as_int = *(int*)&value;
return ( value_as_int > 0 );
}
Looking at the generated assembly the stalls are gone and the function is more performant.
Does this work? I'm confused because all of the optimizations for IEEE tricks use SIGNMASKS and lots of AND/OR operations (https://www.lomont.org/papers/2005/CompareFloat.pdf for example). Does the cast to a signed int help? Testing in a simple harness detects no problems.
Any insight would be good.
The expression
*(int*)&value > 0
tests ifvalue
is any positive float, from the smallest positive denormal (which has the same representation as0x00000001
) to the largest finite float (with representation0x7f7fffff
) and+inf
(which has the same representation as0x7f800000
). The trick detects as positive a number of, but not all, NaN representations (the NaN representations above0x7f800001
). It is fine if you don't care about some values of NaN making the test true.This all works because of the representation of IEEE 754 formats.
The bit manipulation functions that you saw in the literature for the purpose of emulating IEEE 754 operations were probably aiming for perfect emulation, taking into account the particular behaviors of
NaN
and signed zeroes. For instance, the variation*(int*)&value >= 0
would not be equivalent tovalue >= 0.0f
, because-0.0f
, represented as0x80000000
as an unsigned int and thus as-0x80000000
as a signed one, makes the latter condition true and the former one false. This can make such functions quite complicated.Well, yes, because the sign bits of
float
andint
are in the same place and both indicate a positive number when unset. But the conditionvalue > 0.0f
could be implemented by re-interpretingvalue
as an unsigned integer too.Note: the conversion to
int*
of the address ofvalue
breaks strict aliasing rules, but this may be acceptable if your compiler guarantees that it gives meaning to these programs (perhaps with a command-line option).