aboutsummaryrefslogtreecommitdiffstats
path: root/src/gmisc/trig.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gmisc/trig.c')
-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 */