/*****************************************
* my_sqrt.c: Implmenting an integer square
* root using only bit-shifts
*
* Author: Mike Field <[email protected]>
*
*****************************************/
#include <stdio.h>
#include <math.h>
unsigned my_sqrt(unsigned a) {
unsigned s = 0; /* Where the result is assembled */
int q = 15; /* Bit we are working on */
while(q >= 0) {
/* 'change' represents how much setting bit
* 'q' in 's' will change the value of s^2
*
* It is (2^q)*(2^q) + s*(2^q) + s*(2^q),
* but can be calculated using addition and
* bit shift operations.
*/
unsigned change = (1<<(q+q))+ (s<<(q+1));
if(a >= change) {
a -= change;
s |= 1<<q;
}
q--;
}
return s;
}
/***************************************
* Verify my square root implementation
* for all 32-bit unsigned integers
**************************************/
int main(int argc, char *argv[])
{
unsigned a=0;
do {
unsigned s = my_sqrt(a);
if(s*s>a || s*s+2*s+1 < a) {
printf("ERROR %u: %u\r\n",a, my_sqrt(a));
}
a++;
} while(a != 0);
return 0;
}
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 for faster but less accurate result
return y;
}
int main(int argc, char *argv[])
{
unsigned a = 0;
a = 0;
do
{
unsigned s = my_sqrt(a);
printf("sqrt(%d)=%d\n", a, s);
if (s * s > a || s * s + 2 * s + 1 < a)
{
printf("ERROR %u: %u\r\n", a, my_sqrt(a));
}
a++;
} while (a != 10);
return 0;
}
Here's an equally awesome inverse square root function which is super fast and will leave you scratching your head as to how it works,Code: [Select]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 for faster but less accurate result
return y;
}
in the loop condition, it seems there is a missing char, probably "1"
while (a != 0); ----> while (a != 10);Code: [Select]int main(int argc, char *argv[])
{
unsigned a = 0;
a = 0;
do
{
unsigned s = my_sqrt(a);
printf("sqrt(%d)=%d\n", a, s);
if (s * s > a || s * s + 2 * s + 1 < a)
{
printf("ERROR %u: %u\r\n", a, my_sqrt(a));
}
a++;
} while (a != 10);
return 0;
}
interesting method
i = 0x5f3759df - ( i >> 1 );
Binary: 0101 1111 0011 0111 0101 1001 1101 1111
IEEE representation
sign exponent mantissa
0 10111110 (1.)01101110101100111011111
Positive
2^(exponent-127)*[1.]mantissa
2^(190-127)*(1+1/4+1/8+1/32+1/64+1/128+1/512+1/2048+1/4096+1/32768+1/65536+1/131072+1/524288+1/1048576+1/2097152+1/4194304+1/8388608)
2^63*1.43243014812469482421875
9223372036854775808 * 1.43243014812469482421875
Nice. Anyone got an equally simple ln function or e^x?
in the loop condition, it seems there is a missing char, probably "1"
while (a != 0); ----> while (a != 10);

Nice. Anyone got an equally simple ln function or e^x?
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
)i = 0x5f3759df - ( i >> 1 ); // what the fuck?
mm quake)
ze history on that one:
http://www.slideshare.net/maksym_zavershynskyi/fast-inverse-square-root
If you want the history of the algorithm you need to go back much farther. I really don't know just how far, but Gauss is usually a good guess for who originally came up with things like that. :-)
If you want the history of the algorithm you need to go back much farther. I really don't know just how far, but Gauss is usually a good guess for who originally came up with things like that. :-)
Here's an equally awesome inverse square root function which is super fast and will leave you scratching your head as to how it works,
Here's my awesome inverse square root function
function invsqroot(x)
return x*x
end
Did I miss something?
If you want the history of the algorithm you need to go back much farther. I really don't know just how far, but Gauss is usually a good guess for who originally came up with things like that. :-)
Something tells me the IEEE floating point format had yet to be invented 200 odd years ago
If you want the history of the algorithm you need to go back much farther. I really don't know just how far, but Gauss is usually a good guess for who originally came up with things like that. :-)
Something tells me the IEEE floating point format had yet to be invented 200 odd years agoIEEE754 only influences the bit pattern used. Not the principle.
IEEE754 only influences the bit pattern used. Not the principle.
If you want the history of the algorithm you need to go back much farther. I really don't know just how far, but Gauss is usually a good guess for who originally came up with things like that. :-)
Something tells me the IEEE floating point format had yet to be invented 200 odd years agoIEEE754 only influences the bit pattern used. Not the principle.As someone else already mentioned, the novel part of this function is optimisation made by performing specific integer operations on a floating point value, rather than the actual Newton method of finding roots.
Discounting the IEEE format, where there any other binary floating point formats 200 years ago that would have enabled this to be done?
That makes me strongly suspect someone will have done something like the software trick as a paper shortcut long ago, including their use to choose sensible starting approximations for interative algorithms. From the first floating point computers in the 1960s people were documenting all sorts of tricks to prime approximations based on the log nature that can be exposed by the interplay of integer and floating formats.
