Jon Cantwell
Stuff & Things. Mostly devtricks slides for synacor.
(Or: How To Get Profanity Into The Comments Of Famous, Well-Publicised Code)
float FastInvSqrt(float x) {
float xhalf = 0.5f * x;
int i = *(int*)&x; // evil floating point bit level hacking
i = 0x5f3759df - (i >> 1); // what the f***?
x = *(float*)&i;
x = x*(1.5f-(xhalf*x*x));
return x;
}
(actual, verbatim code from the Quake III Arena source, edited only to align with the Synacor HR policy...)
int i = *(int*)&x;
Reinterpret the floating point encoding of x as an integer!
Floating point numbers have three parts: sign, exponent, and mantissa:
s e e e e e e e e m m m m m m m m m m m m m m m m m m m m m m m
Mantissa encodes a value between 0 and 1, exponent is a signed int between -127 and 128.
M = integer rep. of mantissa, E = integer rep. of exponent
(for 32-bit floats, L = 2^23)
....
We can replace x and y with their floating point components...
Helpfully, for v between 0 and 1, log2(1+v) looks a lot like a straight line...
Suddenly, integer representations!
Or, back in C code...
i = K - (i >> 1); // for some magic K
Looks familiar~?
For sigma = 0.0450465...
...which, in hex, is 0x5f3759df!
Given a decent approximation, we can do a single iteration of Newton's method to get an /unreasonably/ accurate approximation of the inverse square root.
Used to use a lookup table for the approximation, before they figured out the mad science magic number.
More information at:
Further explanation and pretty graphs
(seriously, check it out, excellent explanation)
By Jon Cantwell