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.
ugfx_release_2.6
inmarket 2013-10-24 15:03:47 +10:00
parent 21afd2b8f1
commit e6f17baf61
5 changed files with 97 additions and 29 deletions

View File

@ -35,9 +35,11 @@
/* Builtin Fonts */ /* Builtin Fonts */
#define GDISP_INCLUDE_FONT_UI2 FALSE #define GDISP_INCLUDE_FONT_UI2 FALSE
#define GFX_USE_GMISC TRUE #define GFX_USE_GMISC TRUE
#define GMISC_NEED_FIXEDTRIG FALSE #define GMISC_NEED_FIXEDTRIG FALSE
#define GMISC_NEED_FASTTRIG FALSE #define GMISC_NEED_FASTTRIG FALSE
#define GMISC_NEED_INVSQRT TRUE #define GMISC_NEED_INVSQRT TRUE
//#define GDISP_INVSQRT_MIXED_ENDIAN TRUE
//#define GDISP_INVSQRT_REAL_SLOW TRUE
#endif /* _GFXCONF_H */ #endif /* _GFXCONF_H */

View File

@ -31,15 +31,29 @@
#include "gfx.h" #include "gfx.h"
#include <math.h> #include <math.h>
#define Lightgrey () /**
#define Midgrey () * NOTE:
#define Darkgrey (HTML2COLOR(0x303030)) *
* This demo uses floating point operations. Don't expect it to work with any
#define BALLCOLOR1 Red * speed unless your processor has an FPU.
#define BALLCOLOR2 Yellow *
#define WALLCOLOR HTML2COLOR(0x303030) * If you see garbage inside the ball as it is running rather than the red and yellow
#define BACKCOLOR HTML2COLOR(0xC0C0C0) * checkerboard pattern then the fast invsqrt() function in GMISC does not work on
#define FLOORCOLOR HTML2COLOR(0x606060) * your processor.
*
* You can modify the implementation of invsqrt() by firstly defining
* #define GDISP_INVSQRT_MIXED_ENDIAN TRUE
* in your gfxconf.h file.
*
* If it still doesn't work then instead define
* #define GDISP_INVSQRT_REAL_SLOW TRUE
* in your gfxconf.h file. This should always work although it will probably be slow.
*/
#define BALLCOLOR1 Red
#define BALLCOLOR2 Yellow
#define WALLCOLOR HTML2COLOR(0x303030)
#define BACKCOLOR HTML2COLOR(0xC0C0C0)
#define FLOORCOLOR HTML2COLOR(0x606060)
#define SHADOWALPHA (255-255*0.2) #define SHADOWALPHA (255-255*0.2)
int main(void) { int main(void) {

View File

@ -181,11 +181,12 @@
#define GWIN_CONSOLE_USE_BASESTREAM FALSE #define GWIN_CONSOLE_USE_BASESTREAM FALSE
#define GWIN_CONSOLE_USE_FLOAT FALSE #define GWIN_CONSOLE_USE_FLOAT FALSE
#define GWIN_NEED_IMAGE_ANIMATION FALSE #define GWIN_NEED_IMAGE_ANIMATION FALSE
#define GDISP_INVSQRT_MIXED_ENDIAN FALSE
#define GDISP_INVSQRT_REAL_SLOW FALSE
*/ */
/* Optional Low Level Driver Definitions */ /* Optional Low Level Driver Definitions */
/* /*
#define GDISP_USE_CUSTOM_BOARD FALSE
#define GDISP_SCREEN_WIDTH 320 #define GDISP_SCREEN_WIDTH 320
#define GDISP_SCREEN_HEIGHT 240 #define GDISP_SCREEN_HEIGHT 240
#define GDISP_USE_FSMC #define GDISP_USE_FSMC

View File

@ -44,9 +44,34 @@
/** /**
* @} * @}
* *
* @name GMISC Optional Sizing Parameters * @name GMISC Optional Parameters
* @{ * @{
*/ */
/**
* @brief Modifies the @p invsqrt() function to assume a different integer to floating point endianness.
* @note Normally the floating point format and the integer format have
* the same endianness. Unfortunately there are some strange
* processors that don't eg. some very early ARM devices.
* For those where the endianness doesn't match you can fix it by
* defining GDISP_INVSQRT_MIXED_ENDIAN.
* @note This still assumes the processor is using an ieee floating point format.
*
* If you have a software floating point that uses a non-standard
* floating point format (or very strange hardware) then define
* GDISP_INVSQRT_REAL_SLOW and it will do it the hard way.
*/
#ifndef GDISP_INVSQRT_MIXED_ENDIAN
#define GDISP_INVSQRT_MIXED_ENDIAN FALSE
#endif
/**
* @brief Modifies the @p invsqrt() function to do things the long slow way.
* @note This causes the @p invsqrt() function to work regardless of the
* processor floating point format.
* @note This makes the @p invsqrt() function very slow.
*/
#ifndef GDISP_INVSQRT_REAL_SLOW
#define GDISP_INVSQRT_REAL_SLOW FALSE
#endif
/** @} */ /** @} */
#endif /* _GMISC_OPTIONS_H */ #endif /* _GMISC_OPTIONS_H */

View File

@ -143,21 +143,47 @@
#endif #endif
#if GMISC_NEED_INVSQRT #if GMISC_NEED_INVSQRT
// Algorithm based on Quake code // Algorithm based on Quake code.
float invsqrt(float n) { #if GDISP_INVSQRT_REAL_SLOW
long i; #include <math.h>
float x2, y; float invsqrt(float n) {
const float threehalfs = 1.5F; return 1.0/sqrt(n);
}
#else
float invsqrt(float n) {
int32_t i;
float x2;
x2 = n * 0.5F; x2 = n * 0.5F;
y = n;
i = * ( long * ) &y; // evil floating point bit level hacking // Convert into an int32 (no binary format conversion)
i = 0x5f3759df - ( i >> 1 ); // what the? #if GDISP_INVSQRT_MIXED_ENDIAN
y = * ( float * ) &i; ((char *)&i)[0] = ((char *)&n)[3];
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration ((char *)&i)[1] = ((char *)&n)[2];
//y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration for extra precision, this can be removed ((char *)&i)[2] = ((char *)&n)[1];
return y; ((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
#endif /* GFX_USE_GMISC */ #endif /* GFX_USE_GMISC */