仙剑魔 发表于 2012-1-4 23:22:25

我抄过来改了下,只和sqrt()比较了下正确性

#ifdef USING_ASM
        inline DWORD __fastcall Log2_Floor(DWORD x)
        {
                __asm
                {
                        bsr eax,x
                        jnz RETURN
                        mov eax,0ffffffffh
                RETURN:
                }
        }
#else
        inline DWORD Log2_Floor(DWORD x)
        {
                DWORD l=0;
                if(x&0xffff0000){l|=16;x>>=16;}
                if(x&0x0000ff00){l|= 8;x>>= 8;}
                if(x&0x000000f0){l|= 4;x>>= 4;}
                if(x&0x0000000c){l|= 2;x>>= 2;}
                if(x&0x00000002){l|= 1;/*x>>= 1;*/}
                return l;
        }
#endif

        DWORD __fastcall Sqrt(DWORD n)
        {
                static WORD sqrtTab[]=
                {
                          0,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,
                          4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,
                          5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,
                          6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
                        256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,
                        288,288,290,292,294,296,298,300,300,302,304,306,308,310,310,312,
                        314,316,318,320,320,322,324,326,326,328,330,332,334,334,336,338,
                        340,340,342,344,346,346,348,350,352,352,354,356,356,358,360,362,
                        362,364,366,366,368,370,370,372,374,374,376,378,378,380,382,384,
                        384,386,386,388,390,390,392,394,394,396,398,398,400,402,402,404,
                        406,406,408,408,410,412,412,414,416,416,418,418,420,422,422,424,
                        424,426,428,428,430,430,432,434,434,436,436,438,438,440,442,442,
                        444,444,446,448,448,450,450,452,452,454,454,456,458,458,460,460,
                        462,462,464,464,466,468,468,470,470,472,472,474,474,476,476,478,
                        480,480,482,482,484,484,486,486,488,488,490,490,492,492,494,494,
                        496,496,498,498,500,500,502,502,504,504,506,506,508,508,510,512

                };
                static const DWORD Table2[]=
                {
                        0<<10,1<<10,4<<10,9<<10,16<<10,25<<10,36<<10,49<<10,
                };

                if(n<64) return sqrtTab;

                DWORD r;
                if(n<65536)
                {
                        r=sqrtTab;
                        n-=Table2;
                        r<<=10;
                        DWORD c=0x100|r;r>>=1;
                        if(n>=c){n-=c;r|=0x100;}
                        c=0x40|r;r>>=1;
                        if(n>=c){n-=c;r|=0x40;}
                        c=0x10|r;r>>=1;
                        if(n>=c){n-=c;r|=0x10;}
                        c=0x04|r;r>>=1;
                        if(n>=c){n-=c;r|=0x04;}
                        c=0x01|r;r>>=1;
                        if(n>=c) r|=0x01;
                        return r;
                }

                switch(Log2_Floor(n)&0xfe)
                {
#define SQRT_ADJUST {r=(r+n/r)>>1;if(r*r>n) --r;break;}
                case 16:r=sqrtTab   ;SQRT_ADJUST;
                case 18:r=sqrtTab<<1;SQRT_ADJUST;
                case 20:r=sqrtTab<<2;SQRT_ADJUST;
                case 22:r=sqrtTab<<3;SQRT_ADJUST;
                case 24:r=sqrtTab<<4;SQRT_ADJUST;
                case 26:r=sqrtTab<<5;SQRT_ADJUST;
                case 28:r=sqrtTab<<6;SQRT_ADJUST;
                case 30:r=sqrtTab<<7;SQRT_ADJUST;
#undef SQRT_ADJUST
                }
                return r;
        }

sprime 发表于 2012-2-10 13:54:02

多谢分享!

G-Spider 发表于 2013-4-17 22:20:57

很多时间会跑来回顾下这里的经典算法,#137 应该是适合游戏中小浮点数的近似开方,然后也看到一段类似又有意思的话:
"人们很早就在Quake3源代码中发现了如下的C代码,它可以快速的求1/sqrt(x),在3D图形向量计算方面应用很广。
float InvSqrt(float x){
    float xhalf=0.5f*x;
    long i=*(long*)&x;
    i=0x5f3759df - (i>>1);
    x=*(float *)&i;
    x=x*(1.5f-xhalf*x*x);
    return x;
}
Beyond3D.com的Ryszard Sommefeldt一直在想到底是哪个家伙写了这些神奇的代码?2003年Chris Lomont还写了一篇文章(PDF)对这些代码进行了分析。毫无疑问写出这些代码的人绝对是天才。"
是John Carmack?Michael Abrash?John Carmack在邮件回复中明确表示不是他,也不是Michael,可能是Terje Matheson。于是侦探Ryszard又向Terje Mathisen寻求答案。Terje说他写过类似的高效代码,但上面的不是。他猜测可能在MIT的旧文档中可以找到。Ryszard的求证之路显然无止境。
页: 5 6 7 8 9 10 11 12 13 14 [15]
查看完整版本: 二进制32位整数快速平方根