PageRenderTime 62ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/sqrtvis/src/rsqrt_carmack.h

https://bitbucket.org/rayburgemeestre/sqrtvis
C Header | 108 lines | 81 code | 22 blank | 5 comment | 1 complexity | 61050f008e65e1936d2587e5956f52ac MD5 | raw file
  1. #ifndef SQRTS_RSQRT_CARMACK_H
  2. #define SQRTS_RSQRT_CARMACK_H
  3. #include <cstdint>
  4. #include <cmath>
  5. #include <cstring>
  6. namespace carmack
  7. {
  8. // original, as copied from the Quake 3 source, without useless preprocessor code
  9. inline float Q_rsqrt(float number)
  10. {
  11. long i;
  12. float x2, y;
  13. const float threehalfs = 1.5F;
  14. x2 = number * 0.5F;
  15. y = number;
  16. i = * (long *) &y; // evil floating point bit level hacking
  17. i = 0x5f3759df - (i >> 1); // what the fuck?
  18. y = * (float *) &i;
  19. y = y * (threehalfs - (x2 * y * y)); // 1st iteration
  20. return y;
  21. }
  22. inline float Q_frsqrt(float number)
  23. {
  24. long i;
  25. float x2, y;
  26. const float threehalfs = 1.5F;
  27. x2 = number * 0.5F;
  28. y = number;
  29. memcpy(&i, &y, 4);
  30. i = 0x5f3759df - (i >> 1); // what the fuck?
  31. memcpy(&y, &i, 4);
  32. y = y * (threehalfs - (x2 * y * y)); // 1st iteration
  33. return y;
  34. }
  35. // Doom 3's version of Q_rsqrt
  36. inline float D3RSqrt(float x)
  37. {
  38. long i;
  39. float y, r;
  40. y = x * 0.5f;
  41. i = *reinterpret_cast<long *>(&x);
  42. i = 0x5f3759df - (i >> 1);
  43. r = *reinterpret_cast<float *>(&i);
  44. r = r * (1.5f - r * r * y);
  45. return r;
  46. }
  47. // Doom 3's accurate InvSqrt function
  48. union _flint {
  49. uint32_t i;
  50. float f;
  51. };
  52. enum {
  53. LOOKUP_BITS = 8,
  54. EXP_POS = 23,
  55. EXP_BIAS = 127,
  56. LOOKUP_POS = (EXP_POS - LOOKUP_BITS),
  57. SEED_POS = (EXP_POS - 8),
  58. SQRT_TABLE_SIZE = (2 << LOOKUP_BITS),
  59. LOOKUP_MASK = (SQRT_TABLE_SIZE - 1)
  60. };
  61. static uint32_t iSqrt[SQRT_TABLE_SIZE];
  62. // needs to run to fill the sqrt lookup table
  63. inline void init()
  64. {
  65. union _flint fi, fo;
  66. for(int i = 0; i < SQRT_TABLE_SIZE; i++) {
  67. fi.i = ((EXP_BIAS - 1) << EXP_POS) | (i << LOOKUP_POS);
  68. fo.f = (float)(1.0 / sqrt(fi.f));
  69. iSqrt[i] = ((uint32_t)(((fo.i + (1 << (SEED_POS - 2))) >> SEED_POS) & 0xFF)) << SEED_POS;
  70. }
  71. iSqrt[SQRT_TABLE_SIZE / 2] = ((uint32_t)(0xFF)) << (SEED_POS);
  72. }
  73. // Doom 3's rsqrt/invsqrt version
  74. inline float D3InvSqrt(float x)
  75. {
  76. uint32_t a = ((union _flint*)(&x))->i;
  77. union _flint seed;
  78. double y = x * 0.5f;
  79. seed.i = ((((3 * EXP_BIAS - 1) - ((a >> EXP_POS) & 0xFF)) >> 1) << EXP_POS) | iSqrt[(a >> (EXP_POS-LOOKUP_BITS)) & LOOKUP_MASK];
  80. double r = seed.f;
  81. r = r * (1.5f - r * r * y);
  82. r = r * (1.5f - r * r * y);
  83. return (float) r;
  84. }
  85. } // namespace
  86. #endif