Inverse sqrt for fixed point

前端 未结 3 713
栀梦
栀梦 2021-01-06 02:58

I am looking for the best inverse square root algorithm for fixed point 16.16 numbers. The code below is what I have so far(but basically it takes the square root and divide

3条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-06 03:44

    I have a solution that I characterize as "fast inverse sqrt, but for 32bit fixed points". No table, no reference, just straight to the point with a good guess.

    If you want, jump to the source code below, but beware of a few things.

    1. (x * y)>>16 can be replaced with any fixed-point multiplication scheme you want.
    2. This does not require 64-bit [long-words], I just use that for the ease of demonstration. Long words are used to prevent overflow in multiplication. A fixed-point math library will have fixed-point multiplication functions that handle this better.
    3. The initial guess is pretty good, so you get relatively precise results in the first incantation.
    4. The code is more verbose than needed for demonstration.
    5. Values less than 65536 (<1) and greater than 32767<<16 cannot be used.
    6. This is generally not faster than using a square root table and division if your hardware has a division function. If it does not, this avoids divisions.
    int fxisqrt(int input){
    
        if(input <= 65536){
            return 1;
        }
    
        long xSR = input>>1;
        long pushRight = input;
        long msb = 0;
        long shoffset = 0;
        long yIsqr = 0;
        long ysqr = 0;
        long fctrl = 0;
        long subthreehalf = 0;
    
        while(pushRight >= 65536){
            pushRight >>=1;
            msb++;
        }
    
        shoffset = (16 - ((msb)>>1));
        yIsqr = 1<>1) * ((y * y)>>16 ) )>>16 ) ) )>>16;   x2
        //Incantation 1
        ysqr = (yIsqr * yIsqr)>>16;
        fctrl = (xSR * ysqr)>>16;
        subthreehalf = 98304 - fctrl;
        yIsqr = (yIsqr * subthreehalf)>>16;
        //Incantation 2 - Increases precision greatly, but may not be neccessary
        ysqr = (yIsqr * yIsqr)>>16;
        fctrl = (xSR * ysqr)>>16;
        subthreehalf = 98304 - fctrl;
        yIsqr = (yIsqr * subthreehalf)>>16;
        return yIsqr;
    }
    

提交回复
热议问题