diff options
Diffstat (limited to 'src/gmisc/trig.c')
-rw-r--r-- | src/gmisc/trig.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/src/gmisc/trig.c b/src/gmisc/trig.c index 00b6365a..cd35bdc0 100644 --- a/src/gmisc/trig.c +++ b/src/gmisc/trig.c @@ -143,21 +143,47 @@ #endif #if GMISC_NEED_INVSQRT - // Algorithm based on Quake code - float invsqrt(float n) { - long i; - float x2, y; - const float threehalfs = 1.5F; - - x2 = n * 0.5F; - y = n; - i = * ( long * ) &y; // evil floating point bit level hacking - i = 0x5f3759df - ( i >> 1 ); // what the? - y = * ( float * ) &i; - y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration - //y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration for extra precision, this can be removed - return y; - } + // Algorithm based on Quake code. + #if GDISP_INVSQRT_REAL_SLOW + #include <math.h> + float invsqrt(float n) { + return 1.0/sqrt(n); + } + #else + float invsqrt(float n) { + int32_t i; + float x2; + + x2 = n * 0.5F; + + // Convert into an int32 (no binary format conversion) + #if GDISP_INVSQRT_MIXED_ENDIAN + ((char *)&i)[0] = ((char *)&n)[3]; + ((char *)&i)[1] = ((char *)&n)[2]; + ((char *)&i)[2] = ((char *)&n)[1]; + ((char *)&i)[3] = ((char *)&n)[0]; + #else + i = *(int32_t *)&n; + #endif + + // evil floating point bit level hacking + i = 0x5F3759DF - (i >> 1); + + // Convert back to a float (no binary format conversion) + #if GDISP_INVSQRT_MIXED_ENDIAN + ((char *)&n)[0] = ((char *)&i)[3]; + ((char *)&n)[1] = ((char *)&i)[2]; + ((char *)&n)[2] = ((char *)&i)[1]; + ((char *)&n)[3] = ((char *)&i)[0]; + #else + n = *(float *)&i; + #endif + + n = n * (1.5F - (x2 * n * n)); // 1st iteration + //n = n * (1.5F - (x2 * n * n)); // 2nd iteration for extra precision, this can be removed + return n; + } + #endif #endif #endif /* GFX_USE_GMISC */ |