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 > 0tests ifvalueis 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
NaNand signed zeroes. For instance, the variation*(int*)&value >= 0would not be equivalent tovalue >= 0.0f, because-0.0f, represented as0x80000000as an unsigned int and thus as-0x80000000as 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
floatandintare in the same place and both indicate a positive number when unset. But the conditionvalue > 0.0fcould be implemented by re-interpretingvalueas an unsigned integer too.Note: the conversion to
int*of the address ofvaluebreaks 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).