Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unusual conversion between float and long [duplicate]

I found a very complex function this is an implementation of Fast inverse square root. I honestly do not understand how this function works but the following conversion between a long and a float has caught my eye:

i  = *(long *) &y; 

And I leave the full code

inline float Q_rsqrt(float number)
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = *(long *) &y;                      
    i  = 0x5f3759df - (i >> 1);            
    y  = * (float *) &i;
    y  = y * (threehalfs - (x2 * y * y));  

    return y;
}
like image 554
CooperJames Avatar asked Mar 18 '23 11:03

CooperJames


1 Answers

The cast simply reinterprets the bits of y as a long so that it can perform integer arithmetic on them.

See Wikipedia for an explanation of the algorithm: Fast inverse square root.

The code makes use of the knowledge that, on the target platform, sizeof(long) == sizeof(float).

@R.. also helpfully adds the following in a comment:

It's also invalid C -- it's an aliasing violation. A correct version of this program needs use either memcpy or possibly (this is less clear that it's correct, but real compilers document support for it) union-based type punning. The version in OP's code will definitely be "miscompiled" (i.e. in a way different than the author's intent) by real compilers though.

This means that the code is not only architecture-specific, it is also compiler-specific.

like image 103
NPE Avatar answered Mar 28 '23 14:03

NPE