The code below performs a fast inverse square root operation by some bit hacks. The algorithm was probably developed by Silicon Graphics in early 1990's and it's appeared in Quake 3 too. more info
However I get the following warning from GCC C++ compiler: dereferencing type-punned pointer will break strict-aliasing rules
Should I use static_cast
, reinterpret_cast
or dynamic_cast
instead in such situations?
float InverseSquareRoot(float x)
{
float xhalf = 0.5f*x;
int32_t i = *(int32_t*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
Forget casts. Use memcpy
.
float xhalf = 0.5f*x;
uint32_t i;
assert(sizeof(x) == sizeof(i));
std::memcpy(&i, &x, sizeof(i));
i = 0x5f375a86 - (i>>1);
std::memcpy(&x, &i, sizeof(i));
x = x*(1.5f - xhalf*x*x);
return x;
The original code tries to initialize the int32_t
by first accessing the float
object through an int32_t
pointer, which is where the rules are broken. The C-style cast is equivalent to a reinterpret_cast
, so changing it to reinterpret_cast
would not make much difference.
The important difference when using memcpy is that the bytes are copied from the float
into the int32_t
, but the float
object is never accessed through an int32_t
lvalue, because memcpy
takes pointers to void and its insides are "magical" and don't break the aliasing rules.