Re: Fast binary IEEE to float
Pawe? Sikora wrote:
kanze wrote:
Actually, I think I'd write it using references :
float QuickBinaryToFloat( uint32_t in )
{
return reinterpret_cast< float& >( in ) ;
}
gcc-4.1.1-svn:
bin2float.cpp: In function 'float quickBinaryToFloat(unsigned int)':
bin2float.cpp:3: warning: dereferencing type-punned pointer will
break strict-aliasing rules
00000000 <quickBinaryToFloat(unsigned int)>:
0: d9 44 24 04 flds 0x4(%esp)
4: c3 ret
Interesting. The generated code seems correct, however.
The real issue, of course, is will it be in the actual code.
There is a real problem concerning performance, so presumably,
any such function would be inline, and full optimization will be
turned on. These are exactly the sort of conditions where funny
aliasing can confuse the compiler.
but...
float quickBinaryToFloat( unsigned& in )
{
return reinterpret_cast< float& >( in ) ;
}
00000000 <quickBinaryToFloat(unsigned int&)>:
0: 8b 44 24 04 mov 0x4(%esp),%eax
4: d9 00 flds (%eax)
6: c3 ret
And yet... Logically, this is the same as the above. At least
once the function has been inlined and optimized.
My own impression is that the presence of reinterpret_cast
should tell the compiler that strict aliasing rules won't work,
and cause it to modify its optimization strategy accordingly.
But of course, there's no guarantee one way or the other, as far
as the standard is concerned.
2) Method two: The "union trick":
float QuickBinaryToFloat(LONG in)
{
union {
LONG i;
float o;
} u;
u.i = in;
return u.o;
}
Formally, that's undefined behavior.
could you explain this?
The standard says that only one element of a union is valid at a
time, and that accessing any element except the last one written
is undefined behavior.
From a pratical point of view, what this means is that the
compiler's optimizer can more or less consider that each element
is independant -- if it sees, say, the constant 42 assigned to
u.i, it can later replace any read of u.i with the constant 42,
even if u.o has been assigned to in the meantime. It also means
that it can suppress any assignment to u.i that isn't followed
by a read of u.i.
In practice, I have actually used a compiler which did so. A
long time ago. In practice, however, I feel that regardless of
what the standard says, the idiom is rather widespread, and that
a responsible compiler should support it. I think that g++
does, for example, even when they break code which uses the
"approuved" solution involving reinterpret_cast.
if it's true tell_endian_good() from [1] is also UB.
[1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26069#c2
That's more or less what the bug report you cite says. Note the
opening sentence: "If you used GCC's *extension* of using an
union as not violating aliasing rules[...]". The crux of the
bug report is that the ways intended by the standard to work
don't, whereas the union, guaranteed only as a gcc extension,
does.
As I say, standard approval or no, it is widely used, and has
been for ages -- and I'm sure that g++ isn't the only one to
support it as an extension (although it may be one of the few to
actually document this support).
--
James Kanze GABI Software
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]