找回密码
 欢迎注册
楼主: 无心人

[讨论] 二进制32位整数快速平方根

[复制链接]
发表于 2012-1-4 23:22:25 | 显示全部楼层
我抄过来改了下,只和sqrt()比较了下正确性
  1. #ifdef USING_ASM
  2. inline DWORD __fastcall Log2_Floor(DWORD x)
  3. {
  4. __asm
  5. {
  6. bsr eax,x
  7. jnz RETURN
  8. mov eax,0ffffffffh
  9. RETURN:
  10. }
  11. }
  12. #else
  13. inline DWORD Log2_Floor(DWORD x)
  14. {
  15. DWORD l=0;
  16. if(x&0xffff0000){l|=16;x>>=16;}
  17. if(x&0x0000ff00){l|= 8;x>>= 8;}
  18. if(x&0x000000f0){l|= 4;x>>= 4;}
  19. if(x&0x0000000c){l|= 2;x>>= 2;}
  20. if(x&0x00000002){l|= 1;/*x>>= 1;*/}
  21. return l;
  22. }
  23. #endif
  24. DWORD __fastcall Sqrt(DWORD n)
  25. {
  26. static WORD sqrtTab[]=
  27. {
  28. 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
  29. 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
  30. 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  31. 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  32. 256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,
  33. 288,288,290,292,294,296,298,300,300,302,304,306,308,310,310,312,
  34. 314,316,318,320,320,322,324,326,326,328,330,332,334,334,336,338,
  35. 340,340,342,344,346,346,348,350,352,352,354,356,356,358,360,362,
  36. 362,364,366,366,368,370,370,372,374,374,376,378,378,380,382,384,
  37. 384,386,386,388,390,390,392,394,394,396,398,398,400,402,402,404,
  38. 406,406,408,408,410,412,412,414,416,416,418,418,420,422,422,424,
  39. 424,426,428,428,430,430,432,434,434,436,436,438,438,440,442,442,
  40. 444,444,446,448,448,450,450,452,452,454,454,456,458,458,460,460,
  41. 462,462,464,464,466,468,468,470,470,472,472,474,474,476,476,478,
  42. 480,480,482,482,484,484,486,486,488,488,490,490,492,492,494,494,
  43. 496,496,498,498,500,500,502,502,504,504,506,506,508,508,510,512
  44. };
  45. static const DWORD Table2[]=
  46. {
  47. 0<<10,1<<10,4<<10,9<<10,16<<10,25<<10,36<<10,49<<10,
  48. };
  49. if(n<64) return sqrtTab[n];
  50. DWORD r;
  51. if(n<65536)
  52. {
  53. r=sqrtTab[n>>10];
  54. n-=Table2[r];
  55. r<<=10;
  56. DWORD c=0x100|r;r>>=1;
  57. if(n>=c){n-=c;r|=0x100;}
  58. c=0x40|r;r>>=1;
  59. if(n>=c){n-=c;r|=0x40;}
  60. c=0x10|r;r>>=1;
  61. if(n>=c){n-=c;r|=0x10;}
  62. c=0x04|r;r>>=1;
  63. if(n>=c){n-=c;r|=0x04;}
  64. c=0x01|r;r>>=1;
  65. if(n>=c) r|=0x01;
  66. return r;
  67. }
  68. switch(Log2_Floor(n)&0xfe)
  69. {
  70. #define SQRT_ADJUST {r=(r+n/r)>>1;if(r*r>n) --r;break;}
  71. case 16:r=sqrtTab[n>>10] ;SQRT_ADJUST;
  72. case 18:r=sqrtTab[n>>12]<<1;SQRT_ADJUST;
  73. case 20:r=sqrtTab[n>>14]<<2;SQRT_ADJUST;
  74. case 22:r=sqrtTab[n>>16]<<3;SQRT_ADJUST;
  75. case 24:r=sqrtTab[n>>18]<<4;SQRT_ADJUST;
  76. case 26:r=sqrtTab[n>>20]<<5;SQRT_ADJUST;
  77. case 28:r=sqrtTab[n>>22]<<6;SQRT_ADJUST;
  78. case 30:r=sqrtTab[n>>24]<<7;SQRT_ADJUST;
  79. #undef SQRT_ADJUST
  80. }
  81. return r;
  82. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-10 13:54:02 | 显示全部楼层
多谢分享!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 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的求证之路显然无止境。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-21 20:50 , Processed in 0.020419 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表