Fast Square Root

marcus • June 7th, 2007

void setup ()
{
    int runs = 100000;

    long ts = System.currentTimeMillis();
    for ( int i=0; i < runs; i++ )
    {
        fsqrt( random( 1000 ) );
    }
    long ts1 = System.currentTimeMillis() - ts;

    ts = System.currentTimeMillis();
    for ( int i=0; i < runs; i++ )
    {
        ffsqrt( random( 1000 ) );
    }
    long ts2 = System.currentTimeMillis() - ts;

    ts = System.currentTimeMillis();
    for ( int i=0; i < runs; i++ )
    {
        fastSqrt( random( 1000 ) );
    }
    long ts3 = System.currentTimeMillis() - ts;

    ts = System.currentTimeMillis();
    for ( int i=0; i < runs; i++ )
    {
        Math.sqrt( random( 1000 ) );
    }
    long ts4 = System.currentTimeMillis() - ts;

    ts = System.currentTimeMillis();
    for ( int i=0; i < runs; i++ )
    {
        invSqrt( random( 1000 ) );
    }
    long ts5 = System.currentTimeMillis() - ts;

    println( "fsqrt:  "+(ts1/(double)1000) );
    println( "ffsqrt:  "+(ts2/(double)1000) );
    println( "fastSqrt:  "+(ts3/(double)1000) );
    println( "Math.sqrt:  "+(ts4/(double)1000) );
    println( "invSqrt:  "+(ts5/(double)1000) );
}

public static float fsqrt(float x)
{
    if (x ==0) return 0;

    float root = x / 2;
    for (int k = 0; k < 10; k++)
  root = (root + (x / root)) / 2;
    return root;
}

public static float ffsqrt(float n)
{
    if(n==0) return 0;
    if(n==1) return 1;

    float guess = n/2.0;
    float oldguess = 0;
    while(guess!=oldguess)
    { 
        oldguess=guess;
        guess = (guess+n/guess)/2.0;
    }
    return guess;
}

public static float fastSqrt (float val)
{
    // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
    //

    int tmp = Float.floatToIntBits(val);
    tmp -= 1<<23;     /* Remove last bit to not let it go to mantissa */
                      /* tmp is now an approximation to logbase2(val) */
    tmp = tmp >> 1;   /* divide by 2 */
    tmp += 1<<29;     /* add 64 to exponent: (e+127)/2 =(e/2)+63, */
                      /* that represents (e/2)-64 but we want e/2 */
    return Float.intBitsToFloat(tmp);
}

public static float invSqrt(float x)
{
     float xhalf = 0.5f*x;
     int i = Float.floatToIntBits(x);
     i = 0x5f3759df - (i >> 1);
     x = Float.intBitsToFloat(i);
     x = x * (1.5f - xhalf * x * x);
     return 1.0f/x;
}

Tags

+math +processing.org +programming
3d 4-space abstract aesthetic system aesthetics algorithm alien ambient ambisonics animation architecture art artificial audio audio research black&white book caskets classic clicks & cuts code color computer-vision conceptual art consoles cpp culture ddr design devices digtial fabrication documenta documentation drawing dynamics electricity electromagnetism electronics environment event exhibition experimental exploration fashion festival film flocking folk food fractal furniture gamedev generative genetic geometry glitch graphic hacks haptics hardware history hyperspace ideas illustration images inspiration installation instrument intelligence interactive interieur japan java knowledge management landscape library life light liquid live london math micro minimal modernism monochrome motion motion graphics multiples music naming nature nervous ink networked networking opensource osx painting paper particles performance personal photography physics playful politics press print processing processing.org programming quotes recipes research retro romance ruby scripts sculpture SENDUNG.net shopping snippets social software sound space space exploration craft space exploration craft orbiter supercollider swiss systems technology theory theremin toys transformed travel tricks typography universe video visual vj water web2.0 xcode