# ida decompiler output

``````double __cdecl sub_401660(float a1)
{
double v1; // st7@1
float v2; // ST00_4@1
float v4; // [sp+8h] [bp+4h]@1
float v5; // [sp+8h] [bp+4h]@1

v1 = a1;
LODWORD(v2) = 0x5F3759DF - (SLODWORD(a1) >> 1);
v4 = 0.5 * a1;
v5 = (1.5 - v4 * v2 * v2) * v2;
return (float)(v1 * v5);
}
``````

above function do some calculation using float number i am not able to understand LODWORD line

Regards

• `LODWORD` is the first 2 bytes of the `DWORD` and `HIDWORD` is the second 2 bytes of `DWORD`.. see those commands as just putting 2 pieces of a pizza pie together and then you read the whole pizza pie as a new number, and cast it to whatever datatype is suitable for it. I would just declare those macros in a new project and do some expirements with them both to understand their operation completely output a few `printf("%x\n", DWORDAnswer);` afterwards. (SLODWORD is signed version of LODWORD). Also you could replace all macro's with equivalent code to the macro to make it easier on the eye. – SSpoke Dec 24 '15 at 19:51

The `0x5F3759DF` constant seems familiar...

It is the fast inverse square root algorithm: http://en.wikipedia.org/wiki/Fast_inverse_square_root

comparing against that code `SLODWORD` and `LODWORD` would be a bit-preserving conversion to an integral type.

The last line does `a1*invsqrt(a1)` which is equal to `sqrt(a1) * (sqrt(a1)/sqrt(a1))` so it ends up calculating the square root of the input parameter.

SLODWORD(a1) returns the hex representation of a input read the `wiki-link` by ratchet freak and take a look at the poc below

``````#include <stdio.h>
#include <stdlib.h>
long dodance(float number){
float y  = number;
long i  = * ( long * ) &y;
return i;
}
void main (void) {
long a = dodance((float)3.2865);
printf("%08X\n%f\n",a,*(float *)&a);
}
``````

compile without optimization the above code using say

``````cl /Zi /EHsc /nologo /W4 /analyze *.cpp /link /RELEASE
``````

and execute the resulting binary

``````magicnum.exe
40525604
3.286500
``````

Compiling the enhanced code below you can see the maximum precision attainable by the 32 bit float is exhausted when the third term is evaluated in the series

``````#include <stdio.h>
#include <stdlib.h>
long dodance(float number)
{
float y  = number;
long i  = * ( long * ) &y;
return i;
}
int main (int argc , char *argv[])
{
if(argc != 3){printf ("usage %s <float> <int>\n",argv[0]);return 0;}
float input = (float) atof(argv[1]);
int term = atoi(argv[2]);
long a = dodance(input);
printf("%-10s= %08X\n%-10s= %f\n","hex",a,"float",*(float *)&a);
long b = (0x5f3759df - (a >> 1));
float c = *(float *)&b ;
printf("%-10s= %08X\n%-10s= %f\n","hex",b,"~1stfloat",c);
for(int i=0; i< term;i++)
{
c = (float)(c * ( 1.5 - ( (input * 0.5) * c * c )) );
printf("%-10s= %f\n","~nxtfloat",c);
}
return 1;
}
``````

result

``````magicnum.exe
usage magicnum.exe <float> <int>

magicnum.exe 3.2 1
hex       = 404CCCCD
float     = 3.200000
hex       = 3F10F379
~1stfloat = 0.566215
~nxtfloat = 0.558877

magicnum.exe 3.2 2
hex       = 404CCCCD
float     = 3.200000
hex       = 3F10F379
~1stfloat = 0.566215
~nxtfloat = 0.558877
~nxtfloat = 0.559017

magicnum.exe 3.2 3
hex       = 404CCCCD
float     = 3.200000
hex       = 3F10F379
~1stfloat = 0.566215
~nxtfloat = 0.558877
~nxtfloat = 0.559017
~nxtfloat = 0.559017 <-- no improvement over the previous result
``````

some theory

``````Newtons method is a proof and extension of binomial expansion theoram
for fractions and negative numbers
simplified binomial exapnsion for (1+x)^n = 1 + (n*x) + ((n*(n-1)/2)*x^2) + .......
we can derive an approximation of the  squareroot
sqrt(3.2)   = (4 - 0.8)^ 1/2
= 2 * ( 1 - 1/5) ^ 1/2
= 2 * ( 1 + 1/2*(-1/5)  + (-1/8) * (1/25) + .....)
= 2 * ( 1 - 1/10 - 1/200)
= 2 * ( 200/200 - 20/200 - 1/200)
= 2 * (179/200)
= 2 * (0.895)
= 1.79
1 / sqrt(3.2)   = 1 / 1.79
= 0.55865921787709497206703910614525
using calc.exe
3.2^-0.5    = 0.55901699437494742410229341718282
``````

I use this line as reference to understand the hidden macros'

http://www.wekk.net/files/defcon/defs.h

``````double __cdecl sub_401660(float a1)
{
double v1; // st7@1
float v2; // ST00_4@1
float v4; // [sp+8h] [bp+4h]@1
float v5; // [sp+8h] [bp+4h]@1

v1 = a1;
LODWORD(v2) = 0x5F3759DF - (SLODWORD(a1) >> 1);
v4 = 0.5 * a1;
v5 = (1.5 - v4 * v2 * v2) * v2;
return (float)(v1 * v5);
}
``````

could be simplified easier on the eyes like this

``````double __cdecl sub_401660(float a1)
{
double v1; // st7@1
float v2; // ST00_4@1
float v4; // [sp+8h] [bp+4h]@1
float v5; // [sp+8h] [bp+4h]@1

v1 = a1;
*((_DWORD*)&(v2)) = 0x5F3759DF - (*((long*)&(a1)) >> 1);
v4 = 0.5 * a1;
v5 = (1.5 - v4 * v2 * v2) * v2;
return (float)(v1 * v5);
}
``````

or how I would do it..

``````double __cdecl sub_401660(float a1)
{
double v1; // st7@1
float v2; // ST00_4@1
float v4; // [sp+8h] [bp+4h]@1
float v5; // [sp+8h] [bp+4h]@1

v1 = a1;
*((unsigned int *)&(v2)) = 0x5F3759DF - (*((long*)&(a1)) >> 1);
v4 = 0.5 * a1;
v5 = (1.5 - v4 * v2 * v2) * v2;
return (float)(v1 * v5);
}
``````

But this is how you do it if you are a hacker. Google.com search > 0x5F3759DF

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

x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

return y;
}
``````