aboutsummaryrefslogtreecommitdiffstats
path: root/src/gmisc
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2013-10-24 15:03:47 +1000
committerinmarket <andrewh@inmarket.com.au>2013-10-24 15:03:47 +1000
commite6f17baf6133fb83c5c72f7b173cf50c9c275224 (patch)
treed9bfb55a08c61ffa018d5c1bb6bdb32320d31d85 /src/gmisc
parent21afd2b8f19d522fab6b78670bf1afcf11388cd5 (diff)
downloaduGFX-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.c56
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 */