diff options
author | inmarket <andrewh@inmarket.com.au> | 2013-10-24 15:03:47 +1000 |
---|---|---|
committer | inmarket <andrewh@inmarket.com.au> | 2013-10-24 15:03:47 +1000 |
commit | e6f17baf6133fb83c5c72f7b173cf50c9c275224 (patch) | |
tree | d9bfb55a08c61ffa018d5c1bb6bdb32320d31d85 /src/gmisc | |
parent | 21afd2b8f19d522fab6b78670bf1afcf11388cd5 (diff) | |
download | uGFX-e6f17baf6133fb83c5c72f7b173cf50c9c275224.tar.gz uGFX-e6f17baf6133fb83c5c72f7b173cf50c9c275224.tar.bz2 uGFX-e6f17baf6133fb83c5c72f7b173cf50c9c275224.zip |
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.
Diffstat (limited to 'src/gmisc')
-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 */ |