From e6f17baf6133fb83c5c72f7b173cf50c9c275224 Mon Sep 17 00:00:00 2001 From: inmarket Date: Thu, 24 Oct 2013 15:03:47 +1000 Subject: GMISC invsqrt() function. Fix a 64bit processor bug. Add support for processors where the floating point and integer endianness don't match. Add support for processors with a non-standard floating point format. Update gdisp_streaming demo with extra comments to reflect the above changes. --- src/gmisc/trig.c | 56 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 15 deletions(-) (limited to 'src/gmisc/trig.c') 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 + 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 */ -- cgit v1.2.3